並んだタイルの塗り方は何通りかというパズルを解く
問題
9個の白マスが横一列に並んでいます。このうち、いくつかの白マスを黒く塗ります。ただし、少なくとも一つは黒く塗り、また、黒マスが連続することはありません。
このとき、塗り方は全部で何通りあるでしょう。
Ruby で解いてみた
index: 左から何マス目か
pred: 左隣りの色(左端の場合は nil)
再帰を使っています。
def paint(index, pred = nil) return 1 if index == 9 s = 0 if index.zero? || pred == :white s += paint(index + 1, :white) s += paint(index + 1, :black) else s += paint(index + 1, :white) end s end puts paint(0) - 1 #=>88
答えは88通りです。最後に 1 を引いているのは、これだとすべて白マスで黒く塗らない場合が一つ含まれてしまうからです。
メモ化
100マスだとフリーズするので、メモ化してみます。
def paint(index, pred = nil) return 1 if index == 100 return @memo[[index, pred]] if @memo.has_key?([index, pred]) s = 0 if index.zero? || pred == :white s += paint(index + 1, :white) s += paint(index + 1, :black) else s += paint(index + 1, :white) end @memo[[index, pred]] = s end @memo = {} puts paint(0) - 1 #=>927372692193078999175