我正在尝试一个说明以下内容的序言:
魔方是3×3矩阵的不同数字(1到9之间),所有行和列加起来相同(但不一定是对角线)。例如:
2 7 6
9 5 1
4 3 8
是一个神奇的广场。
我们将Prolog中的正方形表示为3×3矩阵,即列表[R1,R2,R3],其中每个R_i是三个数字的列表。例如,
上述魔方的表示是
[[2,7,6],[9,5,1],[4,3,8]]
定义一个谓词魔法/ 1,用于测试地面3×3矩阵(即 所有条目都是数字的地方)是一个魔术广场。
我已经通过以下方式完成了这项工作,而且我很确定如果我在考试中也这样做也是允许的,但对我来说这似乎是一种黑客攻击:
magic([[A,B,C], [D,E,F], [G,H,I]]) :-
Y is A + B + C,
Y is D + E + F,
Y is G + H + I,
Y is A + D + G,
Y is B + E + H,
Y is C + F + I.
我想要的方法是递归外部列表中的每个列表,然后总结一下。对于外部列表中的每个列表,它们应该总结为相同的值(我认为15实际上是这个“魔术”矩阵的唯一可能解决方案)。同样,我对列做同样的事情(取每个列表的第一个,第二个和第三个并分别加起来)。但是,我并不完全确定如何做后者,因为我没有使用列表列表。如果有人能就这些计算如何进行整体解决,我将不胜感激。
由于
答案 0 :(得分:0)
请注意,您的解决方案不会检查A,..,I值是否相同且在1..9范围内。这是针对N>的N×N平方的解决方案。 2:
magic(L) :-
magic_range(L),
magic_sum(S, L),
magic_line(S, L),
transpose(L, T),
magic_line(S, T).
% S value from https://oeis.org/A006003
magic_sum(S, L) :-
length(L, N),
S is N * (N*N + 1) / 2.
magic_range(L) :-
flatten(L, F),
sort(F, S),
length(L, N),
N2 is N * N,
numlist(1, N2, S).
magic_line(_, []).
magic_line(S, [A | As]) :-
sumlist(A, S),
magic_line(S, As).
% https://github.com/SWI-Prolog/swipl-devel/blob/9452af09962000ebb5157fe06169bbf51af5d5c9/library/clp/clpfd.pl#L6411
transpose(Ls, Ts) :-
must_be(list(list), Ls),
lists_transpose(Ls, Ts).
lists_transpose([], []).
lists_transpose([L|Ls], Ts) :-
foldl(transpose_, L, Ts, [L|Ls], _).
transpose_(_, Fs, Lists0, Lists) :-
maplist(list_first_rest, Lists0, Fs, Lists).
list_first_rest([L|Ls], L, Ls).
一些查询
?- magic([[1,1,1],[1,1,1],[1,1,1]]).
false.
?- magic([[2,7,6],[9,5,1],[4,3,8]]).
true ;
false.
?- magic([[16,3,2,13], [5,10,11,8], [9,6,7,12], [4,15,14,1]]).
true ;
false.
transpose
谓词是最复杂的部分。有关其他选择,请参阅here。