反転で作る互い違い(Ruby)

アルゴリズム・パズルです。

問題:
表が白で裏が黒の 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桁が反転しているのがわかります。