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

Problem 29

この問題は、なにも考えなければ、素因数分解して掛け算してsetに入れる、ですね。これをバッチファイルで実現しましょう。
例えば、24 = 23 * 3を次のように表すことにしましょう。

set f= 2 3 3 1

こうすると構造がシンプルで掛け算しやすいです。このfをそのままサブルーチンに渡すと、スペースで区切られて渡されるので扱いやすいのです。shiftを使えば容易に掛け算ができます。
そして、これをsetに入れます。例えば、243 = 29 * 33なら、

set set_fac 2 9 3 3=1

とします。そして、setコマンドで

set set_fac

とすると、set_facで始まる環境変数の一覧が得られるのを利用します。forコマンドで"usebackq"というオプションを使うとコマンドの結果を取り込むことができるので、これを使って環境変数がいくつあるのかを数えます。

@echo off

setlocal enabledelayedexpansion
set /a N = 100
for /L %%n in (2, 1, %N%) do (
    call :factorize %%n
    for /L %%m in (2, 1, %N%) do (
        call :f_mul %%m !f!
        set set_fac!fm!=1
    )
)

set /a counter = 0
for /F "usebackq" %%f in (`set set_fac`) do (
    set /a counter += 1
)
echo %counter%
exit /b 0

:factorize
    set f=
    set /a m = %1
    set /a p = 2
    :loop_factorize
        set /a r = %m% %% %p%
        if %r% == 0 (
            call :div_exp %p%
            set f=%f% %p% !e!
        )
        set /a p += 1
        set /a p_sq = %p% * %p%
        if %n% GEQ %p_sq% goto :loop_factorize
    
    if %m% GTR 1 set f=%f% %m% 1
    exit /b 0

:div_exp
    set /a e = 0
    :loop_div_exp
        set /a r = %m% %% %1
        if %r% NEQ 0 exit /b 0
        set /a m /= %1
        set /a e += 1
        goto :loop_div_exp

:f_mul
    set fm=
    :loop_f_mul
        set /a e = %1 * %3
        set fm=%fm% %2 %e%
        shift /2
        shift /2
        if "%2" NEQ "" goto :loop_f_mul
    exit /b 0