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

Problem 24


この問題は解くだけなら手計算レベルです。例えば、0〜3までを使ったとして9番目の順列は、そこまで列挙すると、

0123
0132
0213
0231
0312
0321
1023
1032
1203

となります。これをこのように分けるとわかりやすいです。

0123
0132
0213
0231
0312
0321

1023
1032

1203

9-1=8を6で割って1なので、0ベースで数えて0123の1番目を前に持ってきて1023、余りの2を2で割って1なので、1+1=2番目の2を前に1番目に持ってきて1203、余りは0なのでそのままというように計算できます。この程度の計算ならバッチファイルでも一瞬です。

@echo off

setlocal enabledelayedexpansion
set /a N = 1000000
set /a M = 10
set /a f = 1
set /a M_2 = %M% - 2
for /L %%k in (0, 1, %M_2%) do (
    set /a f *= %%k + 1
    set /a fs_%%k = !f!
)
set /a fs.size = %M% - 1

set /a r = %N% - 1
for /L %%k in (0, 1, %M_2%) do (
    set /a l = %M_2% - %%k
    set /a f = "fs_!l!"
    set /a a_%%k = !r! / !f!
    set /a r %%= !f!
)
set /a a.size = %M% - 1

call :range b %M%
for /L %%k in (0, 1, %M_2%) do (
    set /a l = "a_%%k" + %%k
    set /a tmp = "b_!l!"
    set /a k_1 = %%k + 1
    for /L %%i in (!l!, -1, !k_1!) do (
        set /a j = %%i - 1
        set /a b_%%i = "b_!j!"
    )
    set /a b_%%k = !tmp!
)
call :print_vector b
exit /b 0

:range
    set /a max_index = %2 - 1
    for /L %%k in (0, 1, %max_index%) do set /a %1_%%k = %%k
    set /a %1.size = %2
    exit /b 0

:print_vector
    setlocal
    set /a size = "%1.size"
    if %size% == 0 echo %2 & exit /b 0
    set /a e = "%1_0"
    set s=%e%
    set /a k = 1
    :loop_print_vector
        if %k% == %size% echo %s% & exit /b 0
        set /a e = "%1_%k%"
        set s=%s%%e%
        set /a k += 1
        goto :loop_print_vector