0

私のタスクは次のとおりです。このハノイ プログラムに、各文を書き込む前に連続した番号を書き込ませることです。

ハノイのプログラムは次のとおりです。

hanoi(N):-move(N,left,middle,right). 
move(0,_,_,_):- !. 
move(N,A,B,C):- M is N-1, move(M,A,C,B), inform(A,B), move(M,C,B,A). 
inform(A,B):- write('MOVING DISK FROM '), write(A),write(' TO '),write(B),nl.

そして、出力を次のようにしたい:

1: MOVING DISK FROM left TO middle 
2: MOVING DISK FROM left TO right 
3: MOVING DISK FROM middle TO right 
4: MOVING DISK FROM left TO middle 
5: MOVING DISK FROM right TO left 
6: MOVING DISK FROM right TO middle 
7: MOVING DISK FROM left TO middle
4

2 に答える 2

1

最初に、DCG を使用して移動のリストを記述することを検討してください。

hanoi(N, Moves) :- phrase(moves(N,left,middle,right), Moves).

moves(0,_,_,_) --> [].
moves(N,A,B,C) --> { N #> 0, M #= N-1 }, moves(M,A,C,B), [A->B], moves(M,C,B,A).

これにより、結果の出力などの副作用からプログラム ロジックを分離できます。動きのリストを作成したら、次のように簡単に記述できます。

write_moves([], _).
write_moves([From->To|Ms], N) :-
        format("~w: move disk from ~w to ~w\n", [N,From,To]),
        N1 #= N + 1,
        write_moves(Ms, N1).

クエリとその結果の例:

?- hanoi(3, Moves), write_moves(Moves, 1).
1: move disk from left to middle
2: move disk from left to right
3: move disk from middle to right
4: move disk from left to middle
5: move disk from right to left
6: move disk from right to middle
7: move disk from left to middle
Moves = [ (left->middle), (left->right), (middle->right), ...].
于 2013-10-05T12:30:01.083 に答える
0

簡単な方法は、行番号を表す動的述語を使用することです。assert/retract の使用はリアルタイムには適していませんが、このようなアプリケーションでは問題なく機能します。読みやすくするために、作業中のハノイ コードを再フォーマットし、コメント付きの行を追加しました。

% hanoi
%
:- dynamic(line/1).         % Define a dynamic predicate "line"

hanoi(N) :-
    assertz(line(1)),       % Assert the first line as 1
    move(N, left, middle, right).

move(0, _, _, _) :- !.
move(N, A, B, C) :-
    M is N-1,
    move(M, A, C, B),
    inform(A, B),
    move(M, C, B, A).

inform(A, B) :-
    line(N),                % get the current line number
    NextN is N + 1,         % next line number will be current one plus 1
    retract(line(_)),       % retract the old line number
    assertz(line(NextN)),   % assert the next line number for next time
    write(N),               % write the line number
    write(': '),            %   and a delimiter
    write('MOVING DISK FROM '),
    write(A),
    write(' TO '),
    write(B),
    nl.

次の最も単純なケースのように、連続した数を生成する方法は他にもあります。

sequence(1).
sequence(X) :- sequence(Y), X is Y + 1.

| ?- sequence(X).

X = 1 ? ;

X = 2 ? ;

X = 3 ? ;

X = 4 ?

場合によっては、このようなものを述語と統合して、シーケンス番号を与えることができます。述語はツリーのような再帰を持っているので、メカニズムhanoiを使用する方が簡単であることがわかりました。assertz

于 2013-10-04T20:46:23.197 に答える