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

Problem 25


フィボナッチ数列なので足していくだけです。1000桁まで計算しなければならないわけですが、過去に作った長い整数のための関数群を使えば簡単です。16分かかって答えが出ました。

@echo off

setlocal enabledelayedexpansion
set /a N = 1000
set /a k = 2
set /a a.size = 1
set /a a_0 = 1
set /a b.size = 1
set /a b_0 = 1
:loop
    call :add_long a b
    set /a k += 1
    call :num_digits a
    if %ERRORLEVEL% == %N% goto :end
    call :add_long b a
    set /a k += 1
    call :num_digits b
    if %ERRORLEVEL% == %N% goto :end
    goto :loop
    
:end
echo %k%
exit /b 0

rem // %1を%2に
:copy_long
    set /a %2.size = "%1.size"
    set /a max_index = %1.size - 1
    for /L %%i in (0, 1, %max_index%) do set /a %2_%%i = "%1_%%i"
    exit /b 0

rem // %1 += %2
:add_long
    set /a size1 = "%1.size"
    set /a size2 = "%2.size"
    if %size1% GEQ %size2% (
        set /a size = %size1%
    ) else (
        set /a size = %size2%
    )
    set /a %1.size = %size%
    set /a kk = 0
    :loop_add_long
        set /a %1_%kk% += "%2_%kk%"
        set /a e = "%1_%kk%"
        set /a k_1 = %kk% + 1
        if %e% GTR 100000000 (
            set /a %1_%kk% -= 100000000
            set /a %1_%k_1% += 1
        )
        set /a kk += 1
        if %kk% LSS %size% goto loop_add_long
    
    set /a e = "%1_%kk%"
    if %e% GTR 0 set /a %1.size = %kk% + 1
    exit /b 0

:num_digits
    setlocal
    set /a s = ("%1.size" - 1) * 8
    set /a max_index = "%1.size" - 1
    set /a top = "%1_%max_index%"
    for /L %%k in (1, 1, 8) do (
        set /a top /= 10
        if !top! == 0 (
            set /a s += %%k
            exit /b !s!
        )
    )

:print_long
    call :long_to_string %1
    echo %res_long_to_string%
    exit /b 0

:long_to_string
    set res_long_to_string=
    set /a size = "%1.size"
    set /a k = 0
    :loop_long_to_string
        set /a e = "%1_%k%"
        set res_long_to_string=%e%%res_long_to_string%
        set /a k += 1
        if %k% LSS %size% goto :loop_long_to_string
    exit /b 0

:push_vector
    set /a size = "%1.size"
    set /a %1_%size% = %2
    set /a %1.size += 1
    exit /b 0