2014年3月20日木曜日

プロジェクトオイラー Problem 55 「Lychrel数」 †

Problem 55 「Lychrel数」 

47とその反転を足し合わせると, 47 + 74 = 121となり, 回文数になる.
全ての数が素早く回文数になるわけではない. 349を考えよう,
  1. 349 + 943 = 1292,
  2. 1292 + 2921 = 4213
  3. 4213 + 3124 = 7337
349は, 3回の操作を経て回文数になる.
まだ証明はされていないが, 196のようないくつかの数字は回文数にならないと考えられている. 反転したものを足すという操作を経ても回文数にならないものをLychrel数と呼ぶ. 先のような数の理論的な性質により, またこの問題の目的のために, Lychrel数で無いと証明されていない数はLychrel数だと仮定する.
更に, 10000未満の数については,常に以下のどちらか一方が成り立つと仮定してよい.
  1. 50回未満の操作で回文数になる
  2. まだ誰も回文数まで到達していない
実際, 10677が50回以上の操作を必要とする最初の数である: 4668731596684224866951378664 (53回の操作で28桁のこの回文数になる).
驚くべきことに, 回文数かつLychrel数であるものが存在する. 最初の数は4994である.
10000未満のLychrel数の個数を答えよ.
注: 2007/04/24にLychrel数の理論的な性質を強調するために文面が修正された.

http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2055




解法
単調増加なのでメモ化しても特に意味はないでしょう。
愚直に計算するのが一番に思えます。

calc(_,50):-!.
calc(List,Len):-
      Len>0,
      reverse(List,List),
      !,
      fail.
calc(List,Len):-
      !,
      number_codes(Num,List),
      reverse(List,List1),
      number_codes(Num1,List1),
      Num2 is Num1+Num,
      number_codes(Num2,List2),
      Len1 is Len+1,
      calc(List2,Len1).

search(1):-
      between(1,9999,N),
      number_codes(N,List),
      calc(List,0).
main55:-
      findall(E,search(E),List),
      length(List,Ans),
      write(Ans).

0 件のコメント:

コメントを投稿