[INDEX] [TOP]

バッチで計算に挑戦(素数を求める)

ここでは、Windows2000/XP のコマンドプロンプトで簡単な計算を行うバッチファイルを紹介します。

九九の表を表示する(小手調べ)
バッチで階乗を求める(再帰呼び出し)
1000までの素数を求める(やり方いろいろ)
覆面算を解いてみる(おまけ)

九九の表を表示する

まずは、小手調べとして、九九の表を表示するバッチです。バッチでの数値演算は 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%

1000までの素数を求める

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>


Copyright (c) 2003-2007 じゃく
last update:2007-09-25