アルゴリズム・パズルです。
問題:
表が白で裏が黒の 16 枚のカードがあります。まず、これらを白と黒が 8 枚ずつ連続して見えるように円形に並べます。
そして、連続した 3 枚のカードを裏返していくことにします。適当な位置でこのように反転していくとき、すべてのカードが白と黒の互いちがいになるような手順の回数は、最小で何回で済むでしょうか。
Ruby で解いてみました。
q49.rb
mask = [14, 28, 56, 112, 224, 448, 896, 1792, 3584, 7168, 14336, 28672, 57344, 49153, 32771] 15.times do |i| mask.combination(i + 1) do |m| field = 0b0000000011111000 m.each do |x| field = field ^ x if field == 0b1010101010101010 p [i + 2, m] #=>[8, [14, 28, 448, 896, 14336, 28672, 57344]] exit end end end end
答えは 8 回ですね。かかった時間は自分の環境で 0.084 秒でした。ループの回数は 59669 回です。
考え方としては、ビット演算で XOR を取ればビットが反転することを使っています。それから、ビットの反転の順序は答えに関係がないことがポイントです。円形というのは、一箇所を固定して横一列で考えればいいです。なので、始める前に適当に1箇所あらかじめ反転させておきます。
XOR でビットの反転というのは、こういうことですね。
[1] pry(main)> (0b01010101 ^ 0b111).to_s(2) => "1010010"
演算 ^
で XOR を取ります。01010101 の右3桁が反転しているのがわかります。
プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問
- 作者: 増井敏克
- 出版社/メーカー: 翔泳社
- 発売日: 2015/10/16
- メディア: Kindle版
- この商品を含むブログ (8件) を見る