バッチファイルでProject Euler(36)

Problem 14


コラッツは、再帰+メモ化で速く美しく解くことができます。

def Collatz(n):
    if n < N:
        if a[n] > 0:
            return a[n]
    
    m = n
    if m % 2 == 0:
        m /= 2
    else:
        m = m * 3 + 1
    
    l = Collatz(m) + 1
    if n < N:
        a[n] = l
    return l

N = 10 ** 6
a = [ 0 ] * N
a[1] = 1
print max((Collatz(n), n) for n in xrange(1, N))[1]

しかし、これをバッチファイルでやると非常に遅いんですね。

@echo off

setlocal
set /a N = 1000
set /a N -= 1
set /a half = (%N + 1) /2
set /a s = 0
set /a a1 = 1
for /L %%i in (%half%, 1, %N%) do call :max_Collatz %%i
echo %s%
exit /b 0

rem // 引数からのコラッツの列の長さを求め、
rem // それがsより大きければそれをsとする
:max_Collatz
    call :Collatz %1
    if %ERRORLEVEL% GTR %s% set /a s = %ERRORLEVEL%
    exit /b 0

:Collatz
    if %1 == 1 exit /b 1
    set /a e = "a%1"
    if %e% GTR 0 exit /b %e%
    
    set /a r = %1 %% 2
    if %r% == 0 (
        set /a m = %1 / 2
    ) else (
        set /a m = %1 * 3 + 1
    )
    call :Collatz %m%
    set /a len = %ERRORLEVEL% + 1
    if %1 LEQ %N% (
        set /a a%1 = %len%
    )
    exit /b %len%