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 です。
   所属(番号、リスト)、falseall_different(リスト)スマはN*(N*N + 1)/2checkC(リスト、N、N、スマ)チェックR(リスト、1、N、スマ)です。

属している (0, _) :- false .
所属(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 です。
   長さ(リスト, 数) ,
   所属(番号、リスト)、falseall_different(リスト)スマはN*(N*N + 1)/2checkC(リスト、N、N、スマ)チェックR(リスト、1、N、スマ)です。

属している (0, _) :- false .
所属(N1、リスト): -
   メンバー(N1,リスト),
   N2 は N1 - 1、
   属している (N2, リスト), false .

N1負の場合もあるため、これは終了しません。追加することを改善する必要がありN1 > 0ます。

falseここで、の前に があるプログラムを考えると、次のall_different/1ようになります。

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

それは非常に多くの推論のように見えます!実際、あなたがやっていることは、可能なすべての構成を最初に列挙することです。したがって、制約プログラミングの機能は使用しません。これについては、チュートリアルを参照してください。ここから始めてください

しかし、問題はこれだけではありません!まだまだありますが、残りのプログラムは理解するのが非常に困難です!。まったく関係のない場所で を使用しているためです。

于 2016-11-16T14:42:26.747 に答える