問題はこちら->http://nabetani.sakura.ne.jp/hena/ordf06numit/
prologで解いてみました。
簡易的にリストでツリーを作りました。
やはり大きい数ではスタックオーバーフローしました。
tree(Data,[]):-Data=<0,!.
tree(Data,List):-DL is floor(Data/2-10), DR is floor(Data*2/3),
tree(DL,L),tree(DR,R),List=[L,Data,R].
counter([],_,0):-!.
counter([L,D,R],N,C):-counter(L,N,C1),counter(R,N,C2),
C3 is C1+C2,(D==N->C is C3+1;C=C3).
solve(T,C,N):-tree(T,L),counter(L,C,N).
go([]):-!.
go([A,B,C,D|T]):-solve(B,C,N),write(A),write("->"),write(N),
(N==D,Str=" ok";Str=" no"),write(" "),write(Str),write("\n"),go(T).
ston([],[]):-!.
ston([H|T],L):-ston(T,L1),number_string(N,H),L=[N|L1].
begin:-str(S),split_string(S,"\s,\n","\s",L),ston(L,L1),go(L1).
str("0 123,4 5
1 1,1 1
2 2,1 1
3 3,3 1
4 19,5 1
5 69,5 3
6 88,9 2
7 1,100 0
8 100,4 4
9 101,9 0
10 456,7 7
11 567,8 12
12 756,10 10
13 789,10 12
14 896,29 2
15 7764,6 664
23 592741,216 55"):-true.
2017.9.22追加
解を求めるだけならツリーを作らなくてもよいので、
時間はかかってもout of stackはなさそうですが、
prologらしさもでませんね。
tree(D,_):-D=<0,!.
tree(D,N):-(D==N->(cou(C),C1 is C+1,assert(cou(C1)),retract(cou(C)));true),
DL is floor(D/2-10), DR is floor(D*2/3),
tree(DL,N),tree(DR,N).
solve(D,N,C):-assert(cou(0)),tree(D,N),cou(C),retract(cou(C)).
2018.2.17追加
別のページ->https://qiita.com/drafts/f6747ae2001d8f39c05a/edit
で言及したメモ化プログラムです。
最初に普通の再帰(データベースは作らない)。
tree(D,N,0):-D<N,!.
tree(D,N,1):-D==N,!.
tree(D,N,C):-
DL is floor(D/2-10), DR is floor(D*2/3),tree(DL,N,CL),tree(DR,N,CR),
C is CL+CR.
solve(D,N,C):-tree(D,N,C).
go([]):-!.
go([A,B,C,D|T]):-solve(B,C,N),write(A),write("->"),write(N),
(N==D,Str=" ok";Str=" no"),write(" "),write(Str),write("\n"),go(T),!.
ston([],[]):-!.
ston([H|T],L):-ston(T,L1),number_string(N,H),L=[N|L1].
begin:-str(S),split_string(S,"\s,\n","\s",L),ston(L,L1),go(L1).
次にメモ化プログラム
tree(D,N,_,0):-D<N,!.
tree(D,N,_,1):-D==N,!.
tree(D,N,F,C):-arg(D,F,V),
(var(V)->(DL is floor(D/2-10), DR is floor(D*2/3),tree(DL,N,F,CL),tree(DR,N,F,CR),
C is CL+CR,arg(D,F,C));C=V).
solve(D,N,C):-functor(F,x,D),tree(D,N,F,C).
go([]):-!.
go([A,B,C,D|T]):-solve(B,C,N),write(A),write("->"),write(N),
(N==D,Str=" ok";Str=" no"),write(" "),write(Str),write("\n"),go(T).
ston([],[]):-!.
ston([H|T],L):-ston(T,L1),number_string(N,H),L=[N|L1].
begin:-str(S),split_string(S,"\s,\n","\s",L),ston(L,L1),go(L1).
str("0 123,4 5
1 1,1 1
2 2,1 1
3 3,3 1
4 19,5 1
5 69,5 3
6 88,9 2
7 1,100 0
8 100,4 4
9 101,9 0
10 456,7 7
11 567,8 12
12 756,10 10
13 789,10 12
14 896,29 2
15 7764,6 664
23 592741,216 55
24 913826,584 81
25 1234567,89 2293
26 10000000,1 19383507
27 12345678,9 3567354
28 6215879,358 2907
29 12345678,90 79419
30 5745432,1032 1287"):-true.