「今週のお題:隣り合うと消えちゃうんです」問題解答 ( CodeIQ )
はじめに
CodeIQという所で週次で出題される「今週のお題」シリーズに解答しましたので、ネタバレです。
問題
問題については、CodeIQ Magazineの、以下の記事に載っています。
解答
以下が提出版のgolf解、Ruby(39)です。計算量的にもΟ(n)で速いです。
a=s=1 11.times{|i|s+=(2*i+3)*a=s-a} p a
解説
コードの構成
ちょっとコードを見易くしてみます。と言ってもあまり変わりませんが。
a=s=1 11.times{|i| a=s-a s+=(2*i+3)*a } puts a
これは実は、2つの数列の漸化式を11回分回すという次の計算をそのままコード化したものなのですね。
という事で、実はとても素直な解なのです。
詳細
提出したコードのコメントを使い回し、もとい再掲します。
色の数に対する塗り分け方をとします。 そして、箇所のマスの左端の色をAとし、もう1箇所のAのマスに着目します。
もし、もう1箇所の両隣が異なる色の場合 ( 端で隣がない場合含む ) 、2箇所のAを取り除いた マスも 「隣り合うマスが同じ色にならない」という条件を満たします。 そのため、Aの箇所毎に塗り方は通りです。また、Aを配置できるのは箇所ですので、計通りです。
次に、Aの両隣が同じ色、その更に両隣が異なる色の場合 ( 同じく隣がない場合含む )、 2箇所のA、Aの両隣の2マスを取り除いたマスも同じく条件を満たします。 このケースは、計 通りです。
…このように次々、Aを挟んで同じ色を配置するマスを増やしていくと、 という組み合わせの数が浮かび上がります。 便宜的に とすると、これは と一般化でき、ここまでの合計は となります。
しかしながら、これだとAが隣り合う通りを含んでしまいます。よって、それを除いた
が に対する塗り分け方の適切な組み合わせの数であり、漸化式を表すものです。
コード化する際には、計算の簡略化のため、 を導入し、
という2数列の漸化式を与えられたの値の回数分評価します。
ここではの漸化式を導いていますが、これをの漸化式に書き換えれば、コードの構成の所で挙げた漸化式になります。
おわりに
絵でもつけた方が分かり易いのでしょうが、ご勘弁を。
ところで、挑戦者の中から抽選で、出題者増井さんの本「プログラマ脳を鍛える数学パズル」がプレゼントされるそうです。当たると嬉しいですね。