LoginSignup
0
0

More than 5 years have passed since last update.

オフラインリアルタイムどう書くF06の問題

Last updated at Posted at 2017-09-21

問題はこちら->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.
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0