Comment detail

ダブル完全数 (Nested Flatten)
ずいぶん冗長ですが、ポイントは ・複素数が見つかればprime_factor/1として定義する。 ・計算した全ての数値に対する約数リストは保存しておき、後の計算に利用 です。prologらしいかしら。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
inc(A,N,R):-A=<N,(perfect3(A)->R=[A|Rs];R=Rs),succ(A,Ax),!,inc(Ax,N,Rs),!.
inc(_,_,[]):-!.

divisible(X,Y):-Z is X mod Y, Z == 0.

:-assert(prime_factor(2)).
:-assert(factorCache(1,[])).

factor(N,X):-factorCache(N,X).
factor(N,Xss):-
        prime_factor(X),
        divisible(N,X),!,
        Ns is N // X,
        factor(Ns, Xs),
        multi(X,[1|Xs],Xs,Xss),
        assert(factorCache(N,Xss)).
factor(1,[1]):-!.
factor(N,[N,1]):-assert(prime_factor(N)),assert(factorCache(N,[N,1])).

multi(_,[],R,R).
multi(X,[L|Ls],S,R):-A is X * L,(member(A,S)->Ss=S;Ss=[A|S]),!,multi(X,Ls,Ss,R).

perfect3(A):-factor(A,X),sum(X,Xs),X3 is A * 3,!,X3==Xs.

sum(L,X):-sum(L,0,X).
sum([],X,X).
sum([N|Ns],A,X):-plus(N,A,As),!,sum(Ns,As,X).

:-inc(3,100000,R),writeln(R),halt.
ずいぶんカットしていますが、カットしないとメモリが足らなくて辛いことになります。
こちらの方がprologらしいですね。
でもやっぱり、10000だとずいぶん時間がかかります。
1
2
3
4
5
measure(N,I):-between(1,N,I), Xmod is N mod I, Xmod =:= 0.
measures(N,R):-findall(X,measure(N,X),R).
perfect_double(N,I):-between(1,N,I), measures(I,M), sumlist(M,S), I3 is I * 3, I3 =:= S.

:-findall(X,perfect_double(10000,X),Xs),writeln(Xs).

Index

Feed

Other

Link

Pathtraq

loading...