Magic Square NxN

时间:2016-11-15 17:53:18

标签: prolog magic-square failure-slice

我是Prolog的新手,我正在努力编写完全正常的魔术方案,但说实话我真的不知道该怎么办,我已经开始但我觉得我做错了。我正在分享我的代码,我希望有人会帮助我,现在当数字很好时我就会变成现实,但是当它们不是我时,我就会发现堆栈错误...(这里只是检查我知道的有关斜行的行和列校验) 谢谢你的关注!

:- use_module(library(clpfd)).
:- use_module(library(lists)).

magicSq(List, N) :-
   Number is N * N,
   belongs(Number ,List), % check if numbers are correct.
   all_different(List), % check if numbers not occur.
   Suma is N*(N*N + 1)/2,
   checkC(List,N,N,Suma), % check column
   checkR(List,1,N,Suma). % check row

belongs(0, _).
belongs(N, List) :- member(N,List) , Index is N - 1 , belongs(Index, List).

consecutiveSum(_, 0 , _,0).
consecutiveSum(List, HowMuch , From,Sum):-
    Index is HowMuch - 1,
    From1 is From +1,
    nth1(From, List,Element),
    consecutiveSum(List,Index,From1,Z),
    Sum is Z + Element,!.

sumObliCol(0,_, [], _,_). % sums by columns or obliquely
sumObliCol(X,Number, [H|T], Ind, Residue) :-
   Index is Ind + 1,
   Y is mod(Index,Number),
   Y =:= Residue,
   sumObliCol(Z,Number, T, Index,Residue),
   X is Z + H, !.
sumObliCol(X,Number, [_|T], Ind,Residue) :-
   Index is Ind + 1,
   sumObliCol(X,Number, T, Index,Residue).


checkC(_,0,_,_).  % check column
checkC(List,N, Number,Answ):-
   N1 is N-1,
   checkC(List,N1, Number,Answ),
   sumObliCol(Ats,Number,List,0,N1),Ats is Answ,!.

checkR(_,N,Number,_):- N>(Number*Number). % check row
checkR(List,N,Number,Answ):-
    consecutiveSum(List,Number,N,Sum), Sum is Answ,
    N1 is N + Number,
    checkR(List,N1, Number,Answ),!.

1 个答案:

答案 0 :(得分:3)

在编程中,人们常常认为

  

一切都在深深地交织在一起......因为这个 world / program的无数主题之间的交叉关系根本无法整齐划分。1

但是在Prolog中,有时候,我们可以更加整洁地划分事物。特别是,如果你专注于单一属性,如非终止。因此,让我们考虑一下大小的魔术方块 - 确实非常神奇!像这样使用

?- magicSq(Xs,1), false.

magicSq(List, N) :-
   Number is N * N,
   belongs(Number ,List), false, 
   all_different(List),
   Suma is N*(N*N + 1)/2,
   checkC(List,N,N,Suma),
   checkR(List,1,N,Suma).

belongs(0, _) :- false.
belongs(N1, List) :-
   member(N1,List), false,
   N2 is N1 - 1,
   belongs(N2, List).

您需要了解的全部内容!显然,List不受约束,因此目标member(N1, List)无法终止。这很容易修复,添加目标length(List, Number)。然而,该计划并没有终止,而是在另一个领域:

?- magicSq(Xs,1), false.

magicSq(List, N) :-
   Number is N * N,
   length(List, Number),
   belongs(Number ,List), false, 
   all_different(List),
   Suma is N*(N*N + 1)/2,
   checkC(List,N,N,Suma),
   checkR(List,1,N,Suma).

belongs(0, _) :- false.
belongs(N1, List) :-
   member(N1,List),
   N2 is N1 - 1,
   belongs(N2, List), false.

现在这不会终止,因为N1也可能是否定的。我们需要改进添加N1 > 0

现在,考虑false前面有all_different/1的程序,我得到:

?- time(magicSq(List, 3)).
% 8,571,007 inferences

这看起来像是一个非常多的推论!实际上,您所做的是首先枚举所有可能的配置。因此,您不使用约束编程的权力。请仔细阅读相关教程。 Start here

然而,问题不止于此!还有更多内容,但剩下的程序很难理解,因为你在完全不相关的地方使用!