私は最近、ピタゴラストリプルを見つけるためのPrologソリューションについても考えていました。少し違うコードを思いついた。次の関数があると仮定します。
isqrt(a) = floor(sqrt(a))
次に、xとyを列挙し、x * x + y*yがいくつかのzの2乗であるかどうかを確認するだけで十分です。つまり、以下をチェックします。
h = x*x+y*y, z = isqrt(h), z*z = h ?
関数isqrtは、bisectionを介して実装できます。対称性の破れの場合、xの後にyを列挙できます。N = 99と仮定すると、結果のコードは次のようになります。
% between(+Integer, +Integer, -Integer)
between(Lo, Hi, _) :-
Lo > Hi, !, fail.
between(Lo, _, Lo).
between(Lo, Hi, X) :-
Lo2 is Lo+1, between(Lo2, Hi, X).
% bisect(+Integer, +Integer, +Integer, -Integer)
bisect(Lo, Hi, X, Y) :-
Lo+1 < Hi, !,
M is (Lo+Hi) // 2,
S is M*M,
(S > X -> bisect(Lo, M, X, Y);
S < X -> bisect(M, Hi, X, Y);
M = Y).
bisect(Lo, _, _, Lo).
% pythago(-List)
pythago(X) :-
X = [A,B,C],
between(1, 99, A),
between(A, 99, B),
H is A*A+B*B,
bisect(0, H, H, C),
C =< 99, H =:= C*C.
そのようなピタゴラスの三重項が50個あるはずです。SloanのA046083も参照してください。
?- findall(-, pythago(_), L), length(L, N).
N = 52.
次のCLP(FD)ソリューションとクロスチェックすることをお勧めします。
:- use_module(library(clpfd)).
% pythago3(-List)
pythago3(X) :-
X = [A,B,C],
X ins 1..99,
A*A+B*B #= C*C,
A #=< B,
label(X).
それは同じ数の解決策を与えます:
?- findall(-, pythago3(_), L), length(L, N).
N = 50.