動機
覆面算(ふくめんざん)と呼ばれる一種の算数パズルがある。
下図はその一例。
A B
+) B C
--------
A D D
二桁+二桁の足し算の筆算の形をしていて,数字が文字という覆面で覆い隠されている。この式が成り立つような A〜D を,以下のルールのもとに求めよ,という問題だ。
- すべての文字は 0 から 9 までの数字のどれかを表す。
- 同じ文字は同じ数字を表す。
- 異なる文字は異なる数字を表す。
- 数の表記で先頭に 0 が来ることはない(今の場合,A, B はゼロではない)
上に掲げた覆面算は,しらみつぶしに調べなくても理詰めで一意の解にたどり着くので,ぜひ考えてみてほしい。
この記事では,計算機にあらゆる数の組み合わせをしらみつぶしに調べさせて解を求めることにする。
方針
こんなふうにしたい。
0 から 9 までの 10 個の数から四つを取り出し,A〜D にあてる。これを,あらゆるパターンについてやる。
A や B が 0 の場合を排除する。
以上で,先に掲げた四つのルールは満たされる。
あとは筆算の式が成り立つときに A〜D の組み合わせを表示するだけ。
作譜
Ruby の Array#permutation
を使えばアホみたいに簡単だ。
このメソッドは,要するに〈配列から n 個の要素を取り出して並べた配列〉を網羅的に作ってイテレート(繰り返しブロック実行)してくれるもの。
こうなる:
[*0..9].permutation 4 do |a, b, c, d|
next if a.zero? || b.zero?
if (10 * a + b) + (10 * b + c) == (100 * a + 10 * d + d)
puts "A=#{a}, B=#{b}, C=#{c}, D=#{d}"
end
end
条件式の ( )
は分かりやすさのためにつけただけで,無くてもいい。
感想
当初 Array#permutation
の存在を忘れていて,自分で実装した。まあ数行で書けるけど,動作が正しいことを確信するのに少し時間がかかった。それに,書き捨てプログラムとはいえ,どういうメソッド名にしてよいか悩んだ。
もしや,と思って公式リファレンスマニュアルで Array クラスを調べたら,あった。
Ruby の組み込みクラスには,こういう「あってもよくね?」的なメソッドがてんこ盛りに詰め込まれている。
感想:Ruby ばんざい