「プロジェクトオイラー問55」の編集履歴(バックアップ)一覧はこちら
「プロジェクトオイラー問55」(2014/02/19 (水) 15:26:53) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2055
*Problem 55 「Lychrel数」 †
47とその反転を足し合わせると, 47 + 74 = 121となり, 回文数になる.
全ての数が素早く回文数になるわけではない. 349を考えよう,
349 + 943 = 1292,
1292 + 2921 = 4213
4213 + 3124 = 7337
349は, 3回の操作を経て回文数になる.
まだ証明はされていないが, 196のようないくつかの数字は回文数にならないと考えられている. 反転したものを足すという操作を経ても回文数にならないものをLychrel数と呼ぶ. 先のような数の理論的な性質により, またこの問題の目的のために, Lychrel数で無いと証明されていない数はLychrel数だと仮定する.
更に, 10000未満の数については,常に以下のどちらか一方が成り立つと仮定してよい.
50回未満の操作で回文数になる
まだ誰も回文数まで到達していない
実際, 10677が50回以上の操作を必要とする最初の数である: 4668731596684224866951378664 (53回の操作で28桁のこの回文数になる).
驚くべきことに, 回文数かつLychrel数であるものが存在する. 最初の数は4994である.
10000未満のLychrel数の個数を答えよ.
注: 2007/04/24にLychrel数の理論的な性質を強調するために文面が修正された.
解法
愚直に計算するだけです。
チェックが容易になるようリストのまま計算します。
349+943=943+349なので349の計算結果は943の計算結果と同じになることを利用してすこしだけ計算量が下がるらしいです。
もう少し賢い方法がありそうですね。
num_to_list(0,[]):-!.
num_to_list(Num,[X|Result]):-
!,
X is Num mod 10,
Num1 is Num//10,
num_to_list(Num1,Result).
revAdd([],[],0,[]):-!.
revAdd([],[],1,[1]):-!.
revAdd([X|Xs],[Y|Ys],Add,[Z|Result]):-
!,
T is X+Y+Add,
Add1 is T // 10,
Z is T mod 10,
revAdd(Xs,Ys,Add1,Result).
calc(50,_):-!.
calc(Deep,Num):-
Deep>0,
reverse(Num,Num),
!,
fail.
calc(Deep,Num):-
reverse(Num,Num1),
revAdd(Num,Num1,0,Num2),
Deep1 is Deep+1,
calc(Deep1,Num2).
search(1):-
between(1,9999,A),
num_to_list(A,ListNum),
calc(0,ListNum).
main55:-
findall(R,search(R),Count),
length(Count,Ans),
write(Ans).