Haskell で虫食い算を解く

Haskell で虫食い算を解いた。とは言っても全自動ではなく、Haskell の助けを借りながら解いただけだ。

まず、Haskell で問題を表示する関数を記述した。

dispExp xs = putStrLn $ unlines $ map (unwords . map showNum) xs
  where
    showNum x = case x of
                  -3 -> "-"
                  -2 -> " "
                  -1 -> "*"
                  _ -> show x

これを使って問題を表示した。
Main> dispExp [[-2,-2,-1,-1,7],[-2,-2,3,-1,-1],[-3,-3,-3,-3,-3],[-2,-1,0,-1,-1],[-2,-1,-1,-1,-2],[-1,5,-1,-2,-2],[-3,-3,-3,-3,-3],[-1,7,-1,-1,3]]
     * * 7
     3 * *
- - - - -
   * 0 * *
   * * *
* 5 *
- - - - -
* 7 * * 3

掛け算の記号が抜けているが、掛け算の筆算のつもり。星印が虫食いの場所だ。被乗数の一位の数が7で、答えの一位の数が3だから、7と掛けて一位の数が3になる数を検索した。

Main> [(7,x)| x<-[1..9], 7*x `mod` 10 == 3]
[(7,9)]

がそうなので、乗数の一位の数を9にした。上矢印キーで表示のときの行をコマンドラインに呼び出して、編集して実行した。

Main> dispExp [[-2,-2,-1,-1,7],[-2,-2,3,-1,9],[-3,-3,-3,-3,-3],[-2,-1,0,-1,3],[-2,-1,-1,-1,-2],[-1,5,-1,-2,-2],[-3,-3,-3,-3,-3],[-1,7,-1,-1,3]]
     * * 7
     3 * 9
- - - - -
   * 0 * 3
   * * *
* 5 *
- - - - -
* 7 * * 3

被乗数の一位の数7と乗数の百位の3をかけると21になるので、

     * * 7
     3 * 9
- - - - -
   * 0 * 3
   * * *
* 5 1
- - - - -
* 7 * * 3

被乗数と乗数の百位の3をかけた数の十位の数が5、で下から2が繰り上がっているから被乗数の十位の数と3をかけた数の一位の数は3でないといけない。

Main> [(3,x)| x <- [1..9], 3*x `mod` 10 == 3]
[(3,1)]

     * 1 7
     3 * 9
- - - - -
   * 0 * 3
   * * *
* 5 1
- - - - -
* 7 * * 3

乗数の一位の9と被乗数の17をかけると、153だから計算欄の一行目の十位の数は5だ

     * 1 7
     3 * 9
- - - - -
   * 0 5 3
   * * *
* 5 1
- - - - -
* 7 * * 3

9かける17つまり、153の百位の1とたして0になる数は9だから、被乗数の百位の数は1になる。

Main> [(x,9)| x <- [1..9], x*9 `mod` 10 == 9]
[(1,9)]

     1 1 7
     3 * 9
- - - - -
   1 0 5 3
   * * *
* 5 1
- - - - -
* 7 * * 3

被乗数が117だとわかったので、途中計算欄の3行目は351で確定する。

     1 1 7
   3 * 9
- - - - -
   1 0 5 3
   * * *
3 5 1
- - - - -
* 7 * * 3

答えの千の位が7だから、計算欄の2行目の3桁目は1だ。

     1 1 7
     3 * 9
- - - - -
   1 0 5 3
   1 * *
3 5 1
- - - - -
* 7 * * 3

乗数が117で途中計算の2行目の3桁目が1だから、2行目は117だ。

     1 1 7
     3 1 9
- - - - -
   1 0 5 3
   1 1 7
3 5 1
- - - - -
3 7 * * 3

あとは、答えの虫食いの部分を補うだけ。

     1 1 7
     3 1 9
- - - - -
   1 0 5 3
   1 1 7
3 5 1
- - - - -
3 7 3 2 3

検算してみた。

Main> 117*319
37323

紙で計算したほうが速かったかもしれないが、計算を表示するプログラムを作成する手間をいれた問題解決までのトータルの時間は、かなり短かったのではないだろうか。虫食い算の計算くらいならExcel を使ったほうが速かったかもしれないが、それでも、思考補助手段としての Haskell の有望さが伺われる。


今日の Haskell
Hugs> foldl (flip (:)) [] [1,2,3,4,5]
[5,4,3,2,1]

reverse を foldl で作ってみただけ。
[PR]
by tnomura9 | 2010-11-29 21:27 | Haskell | Comments(0)
<< リストをテーブル表示する 畳み込み >>