0

我是 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),!.
4

1 回答 1

3

在编程中,人们经常假设

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

但在 Prolog 中,有时我们可以更整齐地划分事物。特别是,如果您专注于单个属性,例如不终止。所以让我们考虑一下大小为 1 的魔方——确实非常神奇!像这样使用

?- magicSq(Xs,1), false。

magicSq(列表,N):-
   数量为 N * N,
   属于(Number ,List), false , 
    all_different(List) ,
    Suma 是 N*(N*N + 1)/2 ,
    checkC(List,N,N,Suma) ,
    checkR(List,1,N,Suma)属于(0,_):-。
属于(N1,列表):-
   member(N1,List), false ,
    N2 是 N1 - 1 ,
    belongs(N2, List)

这就是你需要了解的一切!显然,List是不受约束的,因此目标member(N1, List)不能终止。这很容易解决,添加一个目标length(List, Number)。而且,程序并没有终止,而是在不同的区域:

?- magicSq(Xs,1), false。

magicSq(列表,N):-
   数量为 N * N,
   长度(列表,数字),
   属于(Number ,List), false , 
    all_different(List) ,
    Suma 是 N*(N*N + 1)/2 ,
    checkC(List,N,N,Suma) ,
    checkR(List,1,N,Suma)属于(0,_):-。
属于(N1,列表):-
   成员(N1,列表),
   N2 是 N1 - 1,
   属于(N2,列表),

现在这并没有终止,因为N1也可能是负面的。我们需要改进这一添加N1 > 0

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

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

这看起来像一个可怕的推论!实际上,您所做的是首先枚举所有可能的配置。因此,您不使用约束规划的力量。请阅读这方面的教程。从这里开始

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

于 2016-11-16T14:42:26.747 回答