views:

191

answers:

2

I'm trying to get to calculate the Ackermann function. A description of what I'm trying to achieve is at http://rosettacode.org/wiki/Ackermann_function.

Using the test script, Test 0 4 gives me 5 which is correct. However Test 1 4 gives 5 not 6, and Test 2 4 gives 5 instead of 11.

Where am I going wrong?

::echo off
set depth=0
:ack
if %1==0 goto m0
if %2==0 goto n0

:else
set /a n=%2-1
set /a depth+=1
call :ack %1 %n%
set t=%errorlevel%
set /a depth-=1
set /a m=%1-1
set /a depth+=1
call :ack %m% %t%
set t=%errorlevel%
set /a depth-=1
if %depth%==0 ( exit %t% ) else ( exit /b %t% )

:m0
set/a n=%2+1
if %depth%==0 ( exit %n% ) else ( exit /b %n% )

:n0
set /a m=%1-1
set /a depth+=1
call :ack %m% %2
set t=%errorlevel%
set /a depth-=1
if %depth%==0 ( exit %t% ) else ( exit /b %t% )

I use this script to test it

@echo off
cmd/c ackermann.cmd %1 %2
echo Ackermann of %1 %2 is %errorlevel%

A sample output, for Test 1 1, gives:

>test 1 1
>set depth=0
>if 1 == 0 goto m0
>if 1 == 0 goto n0
>set /a n=1-1
>set /a depth+=1
>call :ack 1 0
>if 1 == 0 goto m0
>if 0 == 0 goto n0
>set /a m=1-1
>set /a depth+=1
>call :ack 0 0
>if 0 == 0 goto m0
>set/a n=0+1
>if 2 == 0 (exit 1  )  else (exit /b 1  )
>set t=1
>set /a depth-=1
>if 1 == 0 (exit 1  )  else (exit /b 1  )
>set t=1
>set /a depth-=1
>set /a m=1-1
>set /a depth+=1
>call :ack 0 1
>if 0 == 0 goto m0
>set/a n=1+1
>if 1 == 0 (exit 2  )  else (exit /b 2  )
>set t=2
>set /a depth-=1
>if 0 == 0 (exit 2  )  else (exit /b 2  )
Ackermann of 1 1 is 2
A: 

What is the scope of your variables m and n?

You set values within one call to :ack, and then recursively call again, setting values. Do you overwrite them? In Stack-based languages such as C and Java, local variables are fine, each level of recursion gets new variables. What happens in cmd?

djna
No scope issue here. It always uses the arguments to the subroutine or the return code, so there is no place where variables are set before a recursive call and re-used afterwards again (except for `depth` but that is intentional).
Joey
@Johannes: yes, you're right. I was looking variables m and n but they are transient.
djna
+2  A: 

Change line 27 above from

call :ack %m% %2 

to

call :ack %m% 1
Patrick Cuff
(blush) such a simple thing too. Oh well, that's the winning solution. Thanks very much, Patrick.
boost