Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -1,12 +1,9 @@
{{Template:clarify task}}
[[Category:Recursion]]
'''Background''': The '''man or boy test''' was proposed by computer scientist [[wp:Donald_Knuth|Donald Knuth]] as a means of evaluating implementations of the [[:Category:ALGOL 60|ALGOL 60]] programming language. The aim of the test was to distinguish compilers that correctly implemented "recursion and non-local references" from those that did not.
<blockquote style="font-style:italic">
I have written the following simple routine, which may separate the 'man-compilers' from the 'boy-compilers'<br> &mdash; <span style="font-style:normal">Donald Knuth</span></blockquote>
'''Task''': Imitate Knuth's example in Algol 60 in another language, as far as possible.
'''Task''': Imitate [[#ALGOL 60 - Knuth's example|Knuth's example in Algol 60]] in another language, as far as possible.
'''Details''': Local variables of routines are often kept in [http://c2.com/cgi/wiki?ActivationRecord ''activation records''] (also ''call frames''). In many languages, these records are kept on a [[System stack|call stack]]. In Algol (and e.g. in [[Smalltalk]]), they are allocated on a [[heap]] instead. Hence it is possible to pass references to routines that still can use and update variables from their call environment, even if the routine where those variables are declared already returned. This difference in implementations is sometimes called the [[wp:Funarg_problem|Funarg Problem]].
@ -18,11 +15,11 @@ in completely different parts of the call tree.
Knuth used this to test the correctness of the compiler, but one can of course also use it to test that other languages can emulate the Algol behavior correctly. If the handling of activation records is correct, the computed value will be &minus;67.
'''Performance and Memory''': Man or Boy is intense and can be pushed to challenge any machine. Memory not CPU time is the constraining resource as the recursion creates a proliferation activation records which will quickly exhaust memory and present itself through a stack error. Each language may have ways of adjusting the amount of memory or increasing the recursion depth. Optionally, show how you would make such adjustments.
'''Performance and Memory''': Man or Boy is intense and can be pushed to challenge any machine. Memory (both stack and heap) not CPU time is the constraining resource as the recursion creates a proliferation activation records which will quickly exhaust memory and present itself through a stack error. Each language may have ways of adjusting the amount of memory or increasing the recursion depth. Optionally, show how you would make such adjustments.
The table below shows the result, call depths, and total calls for a range of k:
{| class="wikitable"
! k
The table below shows the result, call depths, and total calls for a range of ''k'':
{| class="wikitable" style="font-size: 85%"
! ''k''
! 0
! 1
! 2
@ -55,7 +52,7 @@ The table below shows the result, call depths, and total calls for a range of k:
! 29
! 30
|-
! A
! ''A''
|align="right"| 1
|align="right"| 0
|align="right"| -2
@ -88,7 +85,7 @@ The table below shows the result, call depths, and total calls for a range of k:
|align="right"| -230,560,902
|align="right"| -512,016,658
|-
! A called
! ''A'' called
|align="right"| 1
|align="right"| 2
|align="right"| 3
@ -121,7 +118,7 @@ The table below shows the result, call depths, and total calls for a range of k:
|&nbsp;
|&nbsp;
|-
! A depth
! ''A'' depth
|align="right"| 1
|align="right"| 2
|align="right"| 3
@ -154,7 +151,7 @@ The table below shows the result, call depths, and total calls for a range of k:
|&nbsp;
|&nbsp;
|-
! B called
! ''B'' called
|align="right"| 0
|align="right"| 1
|align="right"| 2
@ -187,7 +184,7 @@ The table below shows the result, call depths, and total calls for a range of k:
|&nbsp;
|&nbsp;
|-
! B depth
! ''B'' depth
|align="right"| 0
|align="right"| 1
|align="right"| 2

View file

@ -1,2 +1,4 @@
---
category:
- Recursion
note: Classic CS problems and programs

View file

@ -1,13 +1,13 @@
integer
F(list l)
{
return l_q_integer(l, 1);
return l[1];
}
integer
eval(list l)
{
return call(l_query(l, 0), l);
return call(l[0], l);
}
integer A(list);
@ -17,12 +17,11 @@ B(list l)
{
integer x;
x = l_q_integer(l, 1);
x = l[1];
x -= 1;
l_r_integer(l, 1, x);
return A(l_assemble(B, x, l, l_query(l, -5), l_query(l, -4),
l_query(l, -3), l_query(l, -2)));
return A(l_assemble(B, x, l, l[-5], l[-4], l[-3], l[-2]));
}
integer
@ -31,9 +30,9 @@ A(list l)
integer x;
if (l_q_integer(l, 1) < 1) {
x = eval(l_q_list(l, -2)) + eval(l_q_list(l, -1));
x = eval(l[-2]) + eval(l[-1]);
} else {
x = B(l);
x = B(l);
}
return x;

View file

@ -1,14 +1,14 @@
import std.stdio;
int A(int k, int delegate()[] x ...) {
int b() {
int A(int k, int delegate() nothrow @safe[] x...) nothrow @safe {
int b() nothrow @safe {
k--;
return A(k, &b, x[0], x[1], x[2], x[3]);
}
return (k <= 0) ? x[3]() + x[4]() : b();
return (k > 0) ? b() : x[3]() + x[4]();
}
void main() {
writeln(A(10, 1, -1, -1, 1, 0));
import std.stdio;
A(10, 1, -1, -1, 1, 0).writeln;
}

View file

@ -1,7 +1,5 @@
import std.stdio;
int delegate() mb(T)(T mob) { // embeding function
int b() {
auto mb(T)(T mob) nothrow @safe { // Embeding function.
int b() nothrow @safe @nogc {
static if (is(T == int))
return mob;
else
@ -11,11 +9,11 @@ int delegate() mb(T)(T mob) { // embeding function
return &b;
}
int A(T)(int k, T x1, T x2, T x3, T x4, T x5) {
int A(T)(int k, T x1, T x2, T x3, T x4, T x5) nothrow @safe {
static if (is(T == int)) {
return A(k, mb(x1), mb(x2), mb(x3), mb(x4), mb(x5));
} else {
int b() {
int b() nothrow @safe {
k--;
return A(k, &b, x1, x2, x3, x4);
}
@ -24,5 +22,7 @@ int A(T)(int k, T x1, T x2, T x3, T x4, T x5) {
}
void main() {
writeln(A(10, 1, -1, -1, 1, 0));
import std.stdio;
A(10, 1, -1, -1, 1, 0).writeln;
}

View file

@ -0,0 +1,27 @@
define method a
(k :: <integer>, x1 :: <function>, x2 :: <function>, x3 :: <function>,
x4 :: <function>, x5 :: <function>)
=> (i :: <integer>)
local b() => (i :: <integer>)
k := k - 1;
a(k, b, x1, x2, x3, x4)
end;
if (k <= 0) x4() + x5() else b() end if
end method a;
define method man-or-boy
(x :: <integer>)
=> (i :: <integer>)
a(x, method() 1 end,
method() -1 end,
method() -1 end,
method() 1 end,
method() 0 end)
end method man-or-boy;
format-out("%d\n", man-or-boy(10))

View file

@ -0,0 +1,14 @@
Range
a := method(k, xs,
b := block(
k = k -1
a(k, list(b, xs slice(0,4)) flatten))
if(k <= 0,
(xs at(3) call) + (xs at(4) call),
b call))
f := method(x, block(x))
1 to(500) foreach(k,
(k .. " ") print
a(k, list(1, -1, -1, 1, 0) map (x, f(x))) println)

View file

@ -0,0 +1,21 @@
import java.util.function.DoubleSupplier;
public class ManOrBoy {
static double A(int k, DoubleSupplier x1, DoubleSupplier x2,
DoubleSupplier x3, DoubleSupplier x4, DoubleSupplier x5) {
DoubleSupplier B = new DoubleSupplier() {
int m = k;
public double getAsDouble() {
return A(--m, this, x1, x2, x3, x4);
}
};
return k <= 0 ? x4.getAsDouble() + x5.getAsDouble() : B.getAsDouble();
}
public static void main(String[] args) {
System.out.println(A(10, () -> 1.0, () -> -1.0, () -> -1.0, () -> 1.0, () -> 0.0));
}
}

View file

@ -0,0 +1,25 @@
program manorboy(output);
function zero: integer; begin zero := 0 end;
function one: integer; begin one := 1 end;
function negone: integer; begin negone := -1 end;
function A(
k: integer;
function x1: integer;
function x2: integer;
function x3: integer;
function x4: integer;
function x5: integer
): integer;
function B: integer;
begin k := k - 1;
B := A(k, B, x1, x2, x3, x4)
end;
begin if k <= 0 then A := x4 + x5 else A := B
end;
begin writeln(A(10, one, negone, negone, one, zero))
end.

View file

@ -0,0 +1,16 @@
/*REXX program performs the "man or boy" test as far as possible for N. */
do n=0 /*increment N from 0 forever.*/
say 'n='n a(N,x1,x2,x3,x4,x5) /*display the result to the term.*/
end /*n*/ /* [↑] do until something breaks*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────A subroutine────────────────────────*/
a: procedure; parse arg k,x1,x2,x3,x4,x5
if k<=0 then return f(x4)+f(x5)
else return f(b)
/*──────────────────────────────────one─liner subroutines───────────────*/
b: k=k-1; return a(k,b,x1,x2,x3,x4)
f: interpret 'v=' arg(1)"()"; return v
x1: procedure; return 1
x2: procedure; return -1
x3: procedure; return -1
x4: procedure; return 1