2013-10-04 1 views
0

Моя задача: Сделать эту программу hanoi написать последовательное число перед тем, как записать каждое предложение.Пролог - запись последовательных чисел_

Программа ханой это:

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 

ответ

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.

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), ...]. 
Смежные вопросы