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

Problem 4

この手の問題は、回文数であるかを判定するのではなく、回文数を生成するのが定番です。回文数を生成するには、例えば987なら反転して789にして結合して987789とします。まず、反転です。

:reverse
    setlocal
    if %1 == 0 exit /b %2
    set /a d = %1 %% 10
    set /a n = %1 / 10
    call :reverse %n% %2%d%
    exit /b %ERRORLEVEL%

下の数字を上に持っていくだけです。文字列でなく整数として扱うのは、文字列だと終了判定がうまくいかないからです。この関数の引数は2つなのですが、最初に呼び出されたときは1つで、%2に値がセットされていません。しかし、文字列にすると最後に第1引数が長さ0の文字列になり、第2引数が%1になります。そうすると最初と区別がつかなくなります。

@echo off

set /a k = 990
:loop
    call :create_palindrome %k%
    set /a n = %ERRORLEVEL%
    call :is_product %n%
    if %ERRORLEVEL% == 0 (
        set /a k -= 1
        goto :loop
    )

echo %n%
exit /b 0

rem // 123 -> 123321
:create_palindrome
    setlocal
    call :reverse %1
    set /a n = %1 * 1000 + %ERRORLEVEL%
    exit /b %n%

rem // 123 -> 321
:reverse
    setlocal
    if %1 == 0 exit /b %2
    set /a d = %1 %% 10
    set /a n = %1 / 10
    call :reverse %n% %2%d%
    exit /b %ERRORLEVEL%

rem // 3桁の掛け算になっているか
:is_product
    setlocal
    set /a d = 999
    :loop_is_product
        set /a q = %1 / %d%
        if %q% GTR %d% exit /b 0
        set /a r = %1 %% %d%
        if %r% == 0 exit /b 1
        set /a d -= 1
        goto :loop_is_product