適度短的和基本的方式來寫它,沒有findall
和aggregate
等是這樣的。
首先,發現座標兩個列表之間的歐幾里得距離謂詞:
d([P|Ps], [Q|Qs], D) :-
sum_diff_sq(Ps, Qs, (P-Q)^2, R),
D is sqrt(R).
sum_diff_sq([], [], V, V).
sum_diff_sq([P|Ps], [Q|Qs], V0, V+V0) :-
sum_diff_sq(Ps, Qs, (P-Q)^2, V).
這將計算一對座標之間的距離,每個號碼的列表。
?- d([1], [1], D).
D = 0.0.
?- d([1], [2], D).
D = 1.0.
?- d([1,1], [2,2], D).
D = 1.4142135623730951.
?- d([1,1,1], [2,2,2], D).
D = 1.7320508075688772.
?- d([1,1,1,1], [2,2,2,2], D).
D = 2.0.
然後,爲了計算所有可能距離:
points_distances([], []).
points_distances([P|Ps], Ds) :-
rest_distances(Ps, P, Ds, Ds0),
points_distances(Ps, Ds0).
points_distances/2
使得頭部和各座標的在列表的尾部之間的距離的列表,遞歸(因此在該距離每對之間會有結果)。
rest_distances([], _, Back, Back).
rest_distances([P|Ps], X, [D|Ds], Back) :-
d(P, X, D),
rest_distances(Ps, X, Ds, Back).
這只是計算座標列表和座標之間的距離。結果是一個差異列表。
要使用此:
?- points_distances([[1,1],[1,2],[6,3],[8,2]], D).
D = [1.0, 5.385164807134504, 7.0710678118654755, 5.0990195135927845, 7.0, 2.23606797749979].
?- points_distances([[1,2,3],[2,3,4],[1,7,3],[1,6,3]], D).
D = [1.7320508075688772, 5.0, 4.0, 4.242640687119285, 3.3166247903554, 1.0].
如果你願意,你可以「拯救」,這對座標是在彼此的距離。例如,改變rest_distances/4
從第二條款的頭:
rest_distances([P|Ps], X, [D|Ds], Back)
到:現在
rest_distances([P|Ps], X, [D-pq(X,P)|Ds], Back)
,重裝程序後,可以排序的points_distances/2
結果和採取的第一個元素它,就像在其他答案:
?- points_distances([[1,2,3],[2,3,4],[1,7,3],[1,6,3]] , D),
keysort(D, [Min_dist-pq(P,Q)|_]).
D = [1.7320508075688772-pq([1, 2, 3], [2, 3, 4]),
5.0-pq([1, 2, 3], [1, 7, 3]),
4.0-pq([1, 2, 3], [1, 6, 3]),
4.242640687119285-pq([2, 3, 4], [1, 7, 3]),
3.3166247903554-pq([2, 3|...], [1, 6|...]),
1.0-pq([1|...], [1|...])],
Min_dist = 1.0,
P = [1, 7, 3],
Q = [1, 6, 3].