ここでは、Windows2000/XP のコマンドプロンプトで簡単な計算を行うバッチファイルを紹介します。
まずは、小手調べとして、九九の表を表示するバッチです。バッチでの数値演算は set /a を使います(2000/XPのみ)。ただし、整数演算のみなので注意が必要です。
環境変数 line に一行分の表示が入ります。n×9 のタイミングで echo %line% で表示して、set line= で空にしています。
echo off for /L %%x in (1,1,9) do for /L %%y in (1,1,9) do call :plot %%x %%y exit /b :plot set /a ans=%1 * %2 if %ans% LSS 10 set ans= %ans% set line=%line% %ans% if %2==9 echo %line% & set line= goto :EOF
バッチで階乗を求めてみましょう。素直に引数までのループで順番にかけ算するバッチは以下の通りです。
(その1)ループ版
: 桁あふれがでないのは 12! まで @echo off set x=1 for /L %%i in (1,1,%1) do set /a x = x * %%i echo %x%
ちょっと考え方をかえて、自分自身を呼び出す再帰呼び出し版を作ってみました。自分自身を呼び出すのは call %0 で可能です。そのまま終了しないとオーバーフローしてしまいます。このバッチでは 引数が1の時に無条件に1を返すようにしています。
この例だと再帰呼び出し版よりループ版のほうがシンプルでわかりやすいですね。
(その2)再帰呼び出し版
: 桁あふれがでないのは 12! まで @echo off if %1==1 set ret=1& exit /b set /a x = %1 - 1 call %0 %x% dummy set /a ret= %1 * %ret% if "%2"=="" echo %ret%
1から1000までの素数を求めるバッチファイルです。引数で指定するので1から100までの素数を求めることも、10000までの素数を求めることも出来ます。
素数を求める方法としては、エラトステネスのふるいという方法を使って解きます。
(その1)ファイルを使う方法
ふるいにかける数字をファイル名として覚えておく方法です。ふるいにかける数字というのは、素数の倍数ですでに素数じゃないと判っている数のこと。この数を例えば 4.X というようなファイル名で覚えておくわけです。if not exist Ans\%%1.X ( でふるいにかけられていない数が見つかれば、その数を素数として表示するようになっています。
ファイルを読み書きする作業が出てしまうため、どうしても速度が遅くなります。
@echo off setlocal if "%1"=="" goto usage set /a max= %1 + 0 if %max% LEQ 1 echo 2以上の整数を指定してください && goto usage if exist Ans\NUL rd /q /s Ans md Ans set n=0 set st=%time% for /L %%i in (2,1,%max%) do ( if not exist Ans\%%i.X ( set /a n+=1 echo %%i for /L %%x in (%%i,%%i,%max%) do ( echo.>Ans\%%x.X ) ) ) echo %max%までの素数は%n%個ありました echo %st% - %time% if exist Ans\NUL rd /q /s Ans goto end :usage echo. echo usage:prime num echo. echo numまでの素数を求めます。numに2以上の整数を指定してください。 :end endlocal
(その2)環境変数を使う方法
ふるいにかける数字を環境変数に覚えておく方法です。この数を例えば set Ans%%x=. というよに"."(ピリオド)をセットして覚えます。if not dirined Ans%%i ( でふるいにかけられていない数が環境変数にセットされていない場合、その数を素数として表示するようになっています。
ファイルを読み書きする前のバッチより、メモリ上で覚えておく今回の方法の方が早く求めることが出来ます。
@echo off setlocal if "%1"=="" goto usage set /a max= %1 + 0 if %max% LEQ 1 echo 2以上の整数を指定してください && goto usage set n=0 set st=%time% for /L %%i in (2,1,%max%) do ( if not defined Ans%%i ( set /a n+=1 echo %%i for /L %%x in (%%i,%%i,%max%) do ( set Ans%%x=. ) ) ) echo %max%までの素数は%n%個ありました echo %st% - %time% goto end :usage echo. echo usage:prime num echo. echo numまでの素数を求めます。numに2以上の整数を指定してください。 :end endlocal
(その3)環境変数を使う方法・改良編
ふるいにかける数字を環境変数に覚えておく方法の改良版です。まず2を素数すでに素数であると決めて、3から奇数のみチェックするようにします。これでループ回数が半減します。またチェックする数の二乗が最大数を超えたらチェックを終了するようにします。 これによりかなり所要時間が短縮されます。
@echo off setlocal ENABLEDELAYEDEXPANSION if "%1"=="" goto usage set /a max= %1 + 0 if %max% LEQ 1 echo 2以上の整数を指定してください && goto usage set st=%time% set n=1 echo 2 for /L %%i in (3,2,%max%) do ( if not defined Ans%%i ( set /a n+=1 echo %%i set /a pwr= %%i * %%i if !pwr! LEQ %max% for /L %%x in (%%i,%%i,%max%) do ( set Ans%%x=. ) ) ) echo %max%までの素数は%n%個ありました echo %st% - %time% goto end :usage echo. echo usage:prime num echo. echo numまでの素数を求めます。numに2以上の整数を指定してください。 :end endlocal
バッチで覆面算を解いてみましょう。おまけと書いたのは、完全に正答を求めるのではなく、ある程度の解答候補をバッチで求めて、正答は自分で判断するからです。求める問題は、wikipedia の覆面算に載っていた問題 → 【 バナナ + バナナ = シナモン 】です。
求め方ですが、ループによる総当たりがベースになっています。式のバナナのバ=1〜9のいずれか、ナ=0〜9のいずれかであるという条件で バナナ+バナナ(=シナモン)≧1000 であり、かつ求めたシナモンの百の位が「ナ」の値と一致するというのを条件にして、一致する数値を式として表示するようになっています。完全な正答を求めるなら、シ≠ナ≠モ≠ンも記述すればいいのですが、面倒なのでこれは人間が判断すると割り切っています。
echo off for /L %%b in (1,1,9) do for /L %%n in (0,1,9) do call :sub %%b %%n exit /b :sub set バ=%1 set ナ=%2 if %バ% EQU %ナ% goto :EOF set /a シナモン=%バ%%ナ%%ナ% + %バ%%ナ%%ナ% if %シナモン% GEQ 1000 if %シナモン:~1,1%==%ナ% echo %バ%%ナ%%ナ%+%バ%%ナ%%ナ%=%シナモン% goto :EOF
実行してみた結果は次のようになります。
候補として5つ表示されています。このなかでシ≠ナ≠モ≠ンを満たすのは、877+877=1754 で、これが正答です。バナナ=877のしゃれになっている問題なんですね。
C:\Documents and Settings\jak-san\My Documents>echo off 500+500=1000 622+622=1244 744+744=1488 755+755=1510 877+877=1754 C:\Documents and Settings\jak-san\My Documents>