new tasks

This commit is contained in:
Ingy döt Net 2013-04-09 00:46:50 -07:00
parent 2a4d27cea0
commit 80737d5a6a
1194 changed files with 15353 additions and 1 deletions

View file

@ -0,0 +1,12 @@
The '''[[wp:Ackermann function|Ackermann function]]''' is a classic recursive example in computer science. It is a function that grows very quickly (in its value and in the size of its call tree). It is defined as follows:
:<math> A(m, n) =
\begin{cases}
n+1 & \mbox{if } m = 0 \\
A(m-1, 1) & \mbox{if } m > 0 \mbox{ and } n = 0 \\
A(m-1, A(m, n-1)) & \mbox{if } m > 0 \mbox{ and } n > 0.
\end{cases}
</math>
<!-- <table><tr><td width=12><td><td><math>n+1</math><td>if <math>m=0</math> <tr><td> <td><math>A(m, n) =</math> <td><math>A(m-1, 1)</math> <td>if <math>m>0</math> and <math>n=0</math> <tr><td><td><td><math>A(m-1, A(m, n-1))</math>&nbsp;&nbsp;<td> if <math>m>0</math> and <math>n>0</math></table> -->
Its arguments are never negative and it always terminates. Write a function which returns the value of <math>A(m, n)</math>. Arbitrary precision is preferred (since the function grows so quickly), but not required.

View file

@ -0,0 +1,5 @@
---
category:
- Memoization
- Classic CS problems and programs
note: Recursion

View file

@ -0,0 +1,18 @@
function ackermann(m, n)
{
if ( m == 0 ) {
return n+1
}
if ( n == 0 ) {
return ackermann(m-1, 1)
}
return ackermann(m-1, ackermann(m, n-1))
}
BEGIN {
for(n=0; n < 7; n++) {
for(m=0; m < 4; m++) {
print "A(" m "," n ") = " ackermann(m,n)
}
}
}

View file

@ -0,0 +1,13 @@
public function ackermann(m:uint, n:uint):uint
{
if (m == 0)
{
return n + 1;
}
if (n == 0)
{
return ackermann(m - 1, 1);
}
return ackermann(m - 1, ackermann(m, n - 1));
}

View file

@ -0,0 +1,12 @@
DECLARE FUNCTION ack! (m!, n!)
FUNCTION ack (m!, n!)
IF m = 0 THEN ack = n + 1
IF m > 0 AND n = 0 THEN
ack = ack(m - 1, 1)
END IF
IF m > 0 AND n > 0 THEN
ack = ack(m - 1, ack(m, n - 1))
END IF
END FUNCTION

View file

@ -0,0 +1,53 @@
main:
{((0 0) (0 1) (0 2)
(0 3) (0 4) (1 0)
(1 1) (1 2) (1 3)
(1 4) (2 0) (2 1)
(2 2) (2 3) (3 0)
(3 1) (3 2) (4 0))
{ dup
"A(" << { %d " " . << } ... ") = " <<
reverse give
ack
%d cr << } ... }
ack!:
{ dup zero?
{ <-> dup zero?
{ <->
cp
1 -
<- <- 1 - ->
ack ->
ack }
{ <->
1 -
<- 1 ->
ack }
if }
{ zap 1 + }
if }
zero?!: { 0 = }
Output:
A(0 0 ) = 1
A(0 1 ) = 2
A(0 2 ) = 3
A(0 3 ) = 4
A(0 4 ) = 5
A(1 0 ) = 2
A(1 1 ) = 3
A(1 2 ) = 4
A(1 3 ) = 5
A(1 4 ) = 6
A(2 0 ) = 3
A(2 1 ) = 5
A(2 2 ) = 7
A(2 3 ) = 9
A(3 0 ) = 5
A(3 1 ) = 13
A(3 2 ) = 29
A(4 0 ) = 13

View file

@ -0,0 +1,8 @@
r[1&&{0
>v
j
u>.@
1> \:v
^ v:\_$1+
\^v_$1\1-
u^>1-0fp:1-\0fg101-

View file

@ -0,0 +1,41 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int m_bits, n_bits;
int *cache;
int ackermann(int m, int n)
{
int idx, res;
if (!m) return n + 1;
if (n >= 1<<n_bits) {
printf("%d, %d\n", m, n);
idx = 0;
} else {
idx = (m << n_bits) + n;
if (cache[idx]) return cache[idx];
}
if (!n) res = ackermann(m - 1, 1);
else res = ackermann(m - 1, ackermann(m, n - 1));
if (idx) cache[idx] = res;
return res;
}
int main()
{
int m, n;
m_bits = 3;
n_bits = 20; /* can save n values up to 2**20 - 1, that's 1 meg */
cache = malloc(sizeof(int) * (1 << (m_bits + n_bits)));
memset(cache, 0, sizeof(int) * (1 << (m_bits + n_bits)));
for (m = 0; m <= 4; m++)
for (n = 0; n < 6 - m; n++) {
printf("A(%d, %d) = %d\n", m, n, ackermann(m, n));
return 0;
}

View file

@ -0,0 +1,18 @@
#include <stdio.h>
int ackermann(int m, int n)
{
if (!m) return n + 1;
if (!n) return ackermann(m - 1, 1);
return ackermann(m - 1, ackermann(m, n - 1));
}
int main()
{
int m, n;
for (m = 0; m <= 4; m++)
for (n = 0; n < 6 - m; n++)
printf("A(%d, %d) = %d\n", m, n, ackermann(m, n));
return 0;
}

View file

@ -0,0 +1,4 @@
(defn ackermann [m n]
(cond (zero? m) (inc n)
(zero? n) (ackermann (dec m) 1)
:else (ackermann (dec m) (ackermann m (dec n)))))

View file

@ -0,0 +1,4 @@
ackermann = (m, n) ->
if m is 0 then n + 1
else if m > 0 and n is 0 then ackermann m - 1, 1
else ackermann m - 1, ackermann m, n - 1

View file

@ -0,0 +1,6 @@
define method ack(m == 0, n :: <integer>)
n + 1
end;
define method ack(m :: <integer>, n :: <integer>)
ack(m - 1, if (n == 0) 1 else ack(m, n - 1) end)
end;

View file

@ -0,0 +1,41 @@
note
description: "Example of Ackerman function"
URI: "http://rosettacode.org/wiki/Ackermann_function"
class
ACKERMAN_EXAMPLE
create
make
feature {NONE} -- Initialization
make
do
print ("%N A(0,0):" + ackerman (0, 0).out)
print ("%N A(1,0):" + ackerman (1, 0).out)
print ("%N A(0,1):" + ackerman (0, 1).out)
print ("%N A(1,1):" + ackerman (1, 1).out)
print ("%N A(2,0):" + ackerman (2, 0).out)
print ("%N A(2,1):" + ackerman (2, 1).out)
print ("%N A(2,2):" + ackerman (2, 2).out)
print ("%N A(0,2):" + ackerman (0, 2).out)
print ("%N A(1,2):" + ackerman (1, 2).out)
print ("%N A(3,3):" + ackerman (3, 3).out)
print ("%N A(3,4):" + ackerman (3, 4).out)
end
feature -- Access
ackerman (m: NATURAL; n: NATURAL): NATURAL
do
if m = 0 then
Result := n + 1
elseif m > 0 and n = 0 then
Result := ackerman (m - 1, 1)
elseif m > 0 and n > 0 then
Result := ackerman (m - 1, ackerman (m, n - 1))
end
end
end

View file

@ -0,0 +1,11 @@
-module(main).
-export([main/1]).
main( [ A | [ B |[]]]) ->
io:fwrite("~p~n",[ack(toi(A),toi(B))]).
toi(E) -> element(1,string:to_integer(E)).
ack(0,N) -> N + 1;
ack(M,0) -> ack(M-1, 1);
ack(M,N) -> ack(M-1,ack(M,N-1)).

View file

@ -0,0 +1,14 @@
: ackermann ( m n -- u )
over ( case statement)
0 over = if drop nip 1+ else
1 over = if drop nip 2 + else
2 over = if drop nip 2* 3 + else
3 over = if drop swap 5 + swap lshift 3 - else
drop swap 1- swap dup
if
1- over 1+ swap recurse recurse exit
else
1+ recurse exit \ allow tail recursion
then
then then then then
;

View file

@ -0,0 +1,5 @@
: acker ( m n -- u )
over 0= IF nip 1+ EXIT THEN
swap 1- swap ( m-1 n -- )
dup 0= IF 1+ recurse EXIT THEN
1- over 1+ swap recurse recurse ;

View file

@ -0,0 +1,27 @@
PROGRAM EXAMPLE
IMPLICIT NONE
INTEGER :: i, j
DO i = 0, 3
DO j = 0, 6
WRITE(*, "(I10)", ADVANCE="NO") Ackermann(i, j)
END DO
WRITE(*,*)
END DO
CONTAINS
RECURSIVE FUNCTION Ackermann(m, n) RESULT(ack)
INTEGER :: ack, m, n
IF (m == 0) THEN
ack = n + 1
ELSE IF (n == 0) THEN
ack = Ackermann(m - 1, 1)
ELSE
ack = Ackermann(m - 1, Ackermann(m, n - 1))
END IF
END FUNCTION Ackermann
END PROGRAM EXAMPLE

View file

@ -0,0 +1,15 @@
func Ackermann2(m, n uint) uint {
switch {
case m == 0:
return n + 1
case m == 1:
return n + 2
case m == 2:
return 2*n + 3
case m == 3:
return 8 << n - 3
case n == 0:
return Ackermann2(m - 1, 1)
}
return Ackermann2(m - 1, Ackermann2(m, n - 1))
}

View file

@ -0,0 +1,53 @@
package main
import (
"fmt"
"math/big"
"unsafe"
)
var one = big.NewInt(1)
var two = big.NewInt(2)
var three = big.NewInt(3)
var eight = big.NewInt(8)
var u uint
var uBits = int(unsafe.Sizeof(u))*8 - 1
func Ackermann2(m, n *big.Int) *big.Int {
if m.Cmp(three) <= 0 {
switch m.Int64() {
case 0:
return new(big.Int).Add(n, one)
case 1:
return new(big.Int).Add(n, two)
case 2:
r := new(big.Int).Lsh(n, 1)
return r.Add(r, three)
case 3:
if n.BitLen() > uBits {
panic("way too big")
}
r := new(big.Int).Lsh(eight, uint(n.Int64()))
return r.Sub(r, three)
}
}
if n.BitLen() == 0 {
return Ackermann2(new(big.Int).Sub(m, one), one)
}
return Ackermann2(new(big.Int).Sub(m, one),
Ackermann2(m, new(big.Int).Sub(n, one)))
}
func main() {
show(0, 0)
show(1, 2)
show(2, 4)
show(3, 100)
show(4, 1)
show(4, 3)
}
func show(m, n int64) {
fmt.Printf("A(%d, %d) = ", m, n)
fmt.Println(Ackermann2(big.NewInt(m), big.NewInt(n)))
}

View file

@ -0,0 +1,9 @@
func Ackermann(m, n uint) uint {
switch {
case m == 0:
return n + 1
case n == 0:
return Ackermann(m - 1, 1)
}
return Ackermann(m - 1, Ackermann(m, n - 1))
}

View file

@ -0,0 +1,9 @@
-- everything here are [Int] or [[Int]], which would overflow
-- * had it not overrun the stack first *
ackermann = iterate ack [1..] where
ack a = s where
s = a!!1 : f (tail a) (zipWith (-) s (1:s))
f a (b:bs) = (head aa) : f aa bs where
aa = drop b a
main = mapM_ print $ map (\n -> take (6 - n) $ ackermann !! n) [0..5]

View file

@ -0,0 +1,3 @@
ack 0 n = n + 1
ack m 0 = ack (m-1) 1
ack m n = ack (m-1) (ack m (n-1))

View file

@ -0,0 +1,8 @@
import java.math.BigInteger;
public static BigInteger ack(BigInteger m, BigInteger n) {
return m.equals(BigInteger.ZERO)
? n.add(BigInteger.ONE)
: ack(m.subtract(BigInteger.ONE),
n.equals(BigInteger.ZERO) ? BigInteger.ONE : ack(m, n.subtract(BigInteger.ONE)));
}

View file

@ -0,0 +1,4 @@
function ack(m, n)
{
return m === 0 ? n + 1 : ack(m - 1, n === 0 ? 1 : ack(m, n - 1));
}

View file

@ -0,0 +1,5 @@
function ack(M,N)
if M == 0 then return N + 1 end
if N == 0 then return ack(M-1,1) end
return ack(M-1,ack(M, N-1))
end

View file

@ -0,0 +1,15 @@
function ackermann( $m , $n )
{
if ( $m==0 )
{
return $n + 1;
}
elseif ( $n==0 )
{
return ackermann( $m-1 , 1 );
}
return ackermann( $m-1, ackermann( $m , $n-1 ) );
}
echo ackermann( 3, 4 );
// prints 125

View file

@ -0,0 +1,6 @@
sub A {
my ($m, $n) = @_;
if ($m == 0) { $n + 1 }
elsif ($n == 0) { A($m - 1, 1) }
else { A($m - 1, A($m, $n - 1)) }
}

View file

@ -0,0 +1,6 @@
sub A {
my ($m, $n) = @_;
$m == 0 ? $n + 1 :
$n == 0 ? A($m - 1, 1) :
A($m - 1, A($m, $n - 1))
}

View file

@ -0,0 +1,13 @@
{
my @memo;
sub A {
my( $m, $n ) = @_;
$memo[ $m ][ $n ] and return $memo[ $m ][ $n ];
$m or return $n + 1;
return $memo[ $m ][ $n ] = (
$n
? A( $m - 1, A( $m, $n - 1 ) )
: A( $m - 1, 1 )
);
}
}

View file

@ -0,0 +1,5 @@
(de ack (X Y)
(cond
((=0 X) (inc Y))
((=0 Y) (ack (dec X) 1))
(T (ack (dec X) (ack X (dec Y)))) ) )

View file

@ -0,0 +1,3 @@
ack(0, N, Ans) :- Ans is N+1.
ack(M, 0, Ans) :- M>0, X is M-1, ack(X, 1, Ans).
ack(M, N, Ans) :- M>0, N>0, X is M-1, Y is N-1, ack(M, Y, Ans2), ack(X, Ans2, Ans).

View file

@ -0,0 +1,7 @@
def ack2(M, N):
if M == 0:
return N + 1
elif N == 0:
return ack1(M - 1, 1)
else:
return ack1(M - 1, ack1(M, N - 1))

View file

@ -0,0 +1,10 @@
>>> import sys
>>> sys.setrecursionlimit(3000)
>>> ack1(0,0)
1
>>> ack1(3,4)
125
>>> ack2(0,0)
1
>>> ack2(3,4)
125

View file

@ -0,0 +1,6 @@
def ack2(M, N):
return (N + 1) if M == 0 else (
(N + 2) if M == 1 else (
(2*N + 3) if M == 2 else (
(8*(2**N - 1) + 5) if M == 3 else (
ack2(M-1, 1) if N == 0 else ack2(M-1, ack2(M, N-1))))))

View file

@ -0,0 +1,3 @@
def ack1(M, N):
return (N + 1) if M == 0 else (
ack1(M-1, 1) if N == 0 else ack1(M-1, ack1(M, N-1)))

View file

@ -0,0 +1,3 @@
for ( i in 0:3 ) {
print(ackermann(i, 4))
}

View file

@ -0,0 +1,9 @@
ackermann <- function(m, n) {
if ( m == 0 ) {
n+1
} else if ( n == 0 ) {
ackermann(m-1, 1)
} else {
ackermann(m-1, ackermann(m, n-1))
}
}

View file

@ -0,0 +1,21 @@
/*REXX program calculates/shows some values for the Ackermann function. */
high=24
do j=0 to 3; say
do k=0 to high%(max(1,j))
call Ackermann_tell j,k
end /*k*/
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────ACKERMANN_TELL subroutine───────────*/
ackermann_tell: parse arg mm,nn; calls=0 /*display an echo message.*/
nnn=right(nn,length(high))
say 'Ackermann('mm","nnn')='right(ackermann(mm,nn),high),
left('',12) 'calls='right(calls,10)
return
/*──────────────────────────────────ACKERMANN subroutine────────────────*/
ackermann: procedure expose calls /*compute the Ackerman function. */
parse arg m,n; calls=calls+1
if m==0 then return n+1
if n==0 then return ackermann(m-1,1)
if m==2 then return n*2+3
return ackermann(m-1,ackermann(m,n-1))

View file

@ -0,0 +1,36 @@
/*REXX program calculates/shows some values for the Ackermann function. */
high=24
numeric digits 100 /*have REXX to use up to 100 digit integers.*/
/*When REXX raises a number to a power (via */
/* the ** operator), the power must be an */
/* integer (positive, zero, or negative). */
do j=0 to 4; say /*Ackermann(5,1) is a bit impractical to calc.*/
do k=0 to high%(max(1,j))
call Ackermann_tell j,k
if j==4 & k==2 then leave /*no sense in going overboard.*/
end /*k*/
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────ACKERMANN_TELL subroutine───────────*/
ackermann_tell: parse arg mm,nn; calls=0 /*display an echo message.*/
nnn=right(nn,length(high))
say 'Ackermann('mm","nnn')='right(ackermann(mm,nn),high),
left('',12) 'calls='right(calls,10)
return
/*──────────────────────────────────ACKERMANN subroutine────────────────*/
ackermann: procedure expose calls /*compute the Ackerman function. */
parse arg m,n; calls=calls+1
if m==0 then return n+1
if m==1 then return n+2
if m==2 then return n+n+3
if m==3 then return 2**(n+3)-3
if m==4 then do; a=2
do (n+3)-1 /*ugh!*/
a=2**a
end
return a-3
end
if n==0 then return ackermann(m-1,1)
return ackermann(m-1,ackermann(m,n-1))

View file

@ -0,0 +1,25 @@
/*REXX program calculates/shows some values for the Ackermann function. */
/*Note: the Ackermann function (as implemented) is */
/* higly recursive and is limited by the */
/* biggest number that can have "1" added to */
/* a number (successfully, accurately). */
high=24
do j=0 to 3; say
do k=0 to high%(max(1,j))
call Ackermann_tell j,k
end /*k*/
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────ACKERMANN_TELL subroutine───────────*/
ackermann_tell: parse arg mm,nn; calls=0 /*display an echo message.*/
nnn=right(nn,length(high))
say 'Ackermann('mm","nnn')='right(ackermann(mm,nn),high),
left('',12) 'calls='right(calls,high)
return
/*──────────────────────────────────ACKERMANN subroutine────────────────*/
ackermann: procedure expose calls /*compute the Ackerman function. */
parse arg m,n; calls=calls+1
if m==0 then return n+1
if n==0 then return ackermann(m-1,1)
return ackermann(m-1,ackermann(m,n-1))

View file

@ -0,0 +1,7 @@
#lang racket
(define (ackermann m n)
(cond [(zero? m) (add1 n)]
[(and (> m 0) (zero? n))
(ackermann (sub1 m) 1)]
[(and (> m 0) (> n 0))
(ackermann (sub1 m) (ackermann m (sub1 n)))]))

View file

@ -0,0 +1,4 @@
(0..3).each do |m|
(0..6).each { |n| print ack(m, n), ' ' }
puts
end

View file

@ -0,0 +1,9 @@
def ack(m, n)
if m == 0
n + 1
elsif n == 0
ack(m-1, 1)
else
ack(m-1, ack(m, n-1))
end
end

View file

@ -0,0 +1,12 @@
/==!/==atoi=@@@-@-----#
| | Ackermann function
| | /=========\!==\!====\ recursion:
$,@/>,@/==ack=!\?\<+# | | | A(0,j) -> j+1
j i \<?\+>-@/# | | A(i,0) -> A(i-1,1)
\@\>@\->@/@\<-@/# A(i,j) -> A(i-1,A(i,j-1))
| | |
# # | | | /+<<<-\
/-<<+>>\!=/ \=====|==!/========?\>>>=?/<<#
? ? | \<<<+>+>>-/
\>>+<<-/!==========/
# #

View file

@ -0,0 +1,19 @@
class MAIN is
ackermann(m, n:INTI):INTI is
zero ::= 0.inti; -- to avoid type conversion each time
one ::= 1.inti;
if m = zero then return n + one; end;
if n = zero then return ackermann(m-one, one); end;
return ackermann(m-one, ackermann(m, n-one));
end;
main is
n, m :INT;
loop n := 0.upto!(6);
loop m := 0.upto!(3);
#OUT + "A(" + m + ", " + n + ") = " + ackermann(m.inti, n.inti) + "\n";
end;
end;
end;
end;

View file

@ -0,0 +1,19 @@
class MAIN is
ackermann(m, n:INT):INT
pre m >= 0 and n >= 0
is
if m = 0 then return n + 1; end;
if n = 0 then return ackermann(m-1, 1); end;
return ackermann(m-1, ackermann(m, n-1));
end;
main is
n, m :INT;
loop n := 0.upto!(6);
loop m := 0.upto!(3);
#OUT + "A(" + m + ", " + n + ") = " + ackermann(m, n) + "\n";
end;
end;
end;
end;

View file

@ -0,0 +1,2 @@
scala> for ( m <- 0 to 3; n <- 0 to 6 ) yield ack(m,n)
res0: Seq.Projection[BigInt] = RangeG(1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 3, 5, 7, 9, 11, 13, 15, 5, 13, 29, 61, 125, 253, 509)

View file

@ -0,0 +1,40 @@
val maxDepth = 4
val ackMMap = scala.collection.mutable.Map[BigInt, BigInt]()
val ackNMaps = Array.fill(maxDepth + 1) { scala.collection.mutable.Map[BigInt, BigInt]() }
def ack(m: Int, n: BigInt): BigInt = {
if ((m < 0) || (n < 0)) {
throw new Exception("Negative parameters are not allowed: ack(%s, %s)".format(m, n))
}
if (m > maxDepth) {
throw new Exception("First parameter is greater as %s: ack(%s, %s)".format(maxDepth, m, n))
}
val newM = m - 1
val newN = n - 1
if (m == 0) {
n + 1
} else if (n == 0) {
ackMMap.getOrElseUpdate(newM, ack(newM, 1))
} else {
val createStep = 125
val index = m
val mapCurrent = ackNMaps(index)
val mapPrevious = ackNMaps(index - 1)
val maxRecursion = 2 * createStep
val nrOfElements : BigInt = if (mapCurrent.isEmpty) 0 else mapCurrent.max._1
if ((nrOfElements + maxRecursion) < n) {
for (i <- nrOfElements + createStep to n by createStep) {
mapCurrent.getOrElseUpdate(i, ack(m, i))
}
}
mapCurrent.getOrElseUpdate(n, {
val ackVal = mapCurrent.getOrElseUpdate(newN, ack(m, newN))
mapPrevious.getOrElseUpdate(ackVal, ack(newM, ackVal))
})
}
}

View file

@ -0,0 +1,5 @@
if ((nrOfElements + maxRecursion) < n) {
for (i <- nrOfElements + createStep to n by createStep) {
mapCurrent.getOrElseUpdate(i, ack(m, i))
}
}

View file

@ -0,0 +1,5 @@
def ack(m: BigInt, n: BigInt): BigInt = {
if (m==0) n+1
else if (n==0) ack(m-1, 1)
else ack(m-1, ack(m, n-1))
}

View file

@ -0,0 +1,5 @@
(define (A m n)
(cond
((= m 0) (+ n 1))
((= n 0) (A (- m 1) 1))
(else (A (- m 1) (A m (- n 1))))))

View file

@ -0,0 +1,15 @@
|ackermann|
ackermann := [ :n :m |
(n = 0) ifTrue: [ (m + 1) ]
ifFalse: [
(m = 0) ifTrue: [ ackermann value: (n-1) value: 1 ]
ifFalse: [
ackermann value: (n-1)
value: ( ackermann value: n
value: (m-1) )
]
]
].
(ackermann value: 0 value: 0) displayNl.
(ackermann value: 3 value: 4) displayNl.

View file

@ -0,0 +1,9 @@
proc ack {m n} {
if {$m == 0} {
expr {$n + 1}
} elseif {$n == 0} {
tailcall ack [expr {$m - 1}] 1
} else {
tailcall ack [expr {$m - 1}] [ack $m [expr {$n - 1}]]
}
}

View file

@ -0,0 +1,55 @@
package require Tcl 8.6
# A memoization engine, from http://wiki.tcl.tk/18152
oo::class create cache {
filter Memoize
variable ValueCache
method Memoize args {
# Do not filter the core method implementations
if {[lindex [self target] 0] eq "::oo::object"} {
return [next {*}$args]
}
# Check if the value is already in the cache
set key [self target],$args
if {[info exist ValueCache($key)]} {
return $ValueCache($key)
}
# Compute value, insert into cache, and return it
return [set ValueCache($key) [next {*}$args]]
}
method flushCache {} {
unset ValueCache
# Skip the cacheing
return -level 2 ""
}
}
# Make an object, attach the cache engine to it, and define ack as a method
oo::object create cached
oo::objdefine cached {
mixin cache
method ack {m n} {
if {$m==0} {
expr {$n+1}
} elseif {$m==1} {
# From the Mathematica version
expr {$m+2}
} elseif {$m==2} {
# From the Mathematica version
expr {2*$n+3}
} elseif {$m==3} {
# From the Mathematica version
expr {8*(2**$n-1)+5}
} elseif {$n==0} {
tailcall my ack [expr {$m-1}] 1
} else {
tailcall my ack [expr {$m-1}] [my ack $m [expr {$n-1}]]
}
}
}
# Some small tweaks...
interp recursionlimit {} 100000
interp alias {} ack {} cacheable ack

View file

@ -0,0 +1,9 @@
proc ack {m n} {
if {$m == 0} {
expr {$n + 1}
} elseif {$n == 0} {
ack [expr {$m - 1}] 1
} else {
ack [expr {$m - 1}] [ack $m [expr {$n - 1}]]
}
}