2013-10-04 13 views
0

Ma tâche est la suivante: Faire en sorte que ce programme de hanoi écrive un nombre successif avant d'écrire chaque phrase.Prolog - écrire des nombres successifs_

Le programme hanoi est le suivant:

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. 

Et je veux la sortie de ressembler à ceci:

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 

Répondre

0

Une approche directe serait d'utiliser un prédicat dynamique représentant le numéro de ligne . Utiliser assert/retract n'est pas convivial en temps réel, mais cela fonctionne bien pour une application comme celle-ci. Je reformater votre code Hanoi travail pour une meilleure lisibilité, et j'ai ajouté les lignes indiquées avec des commentaires:

% 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. 

Il existe d'autres façons de générer des numéros successifs, comme le cas le plus simple suivant.

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

| ?- sequence(X). 

X = 1 ? ; 

X = 2 ? ; 

X = 3 ? ; 

X = 4 ? 

Dans certains cas, quelque chose comme cela peut être intégré avec un prédicat pour vous donner les numéros séquencer. Puisque le prédicat hanoi a une récursivité arborescente, j'ai trouvé plus facile d'utiliser un mécanisme assertz.

1

d'abord envisager d'utiliser un DCG pour décrire la liste des mouvements:

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). 

Cela vous permet de séparer la logique du programme des effets secondaires comme des résultats d'impression. Une fois que vous avez une liste de mouvements, il est facile de les écrire, par exemple avec:

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). 

Exemple requête et son résultat:

?- 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), ...]. 
Questions connexes