Проблема сопоставления с образцом с Прологом - PullRequest
2 голосов
/ 12 апреля 2011

РЕДАКТИРОВАТЬ: Смотрите мой ответ ниже, почему я дурак.В этом все еще есть загадка, на которую я бы хотел ответить.

Я застрял на этом слишком долго.Я пытаюсь распечатать решение судоку в красивой сетке.

Думаю, у меня возникли проблемы, потому что я не понимаю какую-то ключевую часть работы сопоставления с образцом в Прологе.

Без лишних слов, мой код:

prettier_print([]).
prettier_print([Puzzle]) :- prettier_print(0, [Puzzle]).

prettier_print(0, Puzzle) :- 
    writeln('┌───────┬───────┬───────┐'), 
    prettier_print(1, Puzzle).
prettier_print(4, Puzzle) :- 
    writeln('│───────┼───────┼───────│'), 
    prettier_print(5, Puzzle).
prettier_print(8, Puzzle) :- 
    writeln('│───────┼───────┼───────│'), 
    prettier_print(9, Puzzle).
prettier_print(12, []) :- 
    writeln('└───────┴───────┴───────┘').

prettier_print(N, [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9 | Puzzle]) :- 
    member(N, [1,2,3,5,6,7,9,10,11]),  % tried this when the line below did not work
    % N =\= 0, N =\= 4, N =\= 8, N =\= 13,

    format('│ ~d ~d ~d │ ~d ~d ~d │ ~d ~d ~d │~n', [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9]), 
    succ(N, N1),
    prettier_print(N1, Puzzle).

Вот вызов:

prettier_print(0, [1,2,3,4,5,6,7,8,9, 
                   2,2,3,4,5,6,7,8,9, 
                   3,2,3,4,5,6,7,8,9, 
                   4,2,3,4,5,6,7,8,9, 
                   5,2,3,4,5,6,7,8,9, 
                   6,2,3,4,5,6,7,8,9,
                   7,2,3,4,5,6,7,8,9,
                   8,2,3,4,5,6,7,8,9,
                   9,2,3,4,5,6,7,8,9]).

А вот вывод:

┌───────┬───────┬───────┐
│ 1 2 3 │ 4 5 6 │ 7 8 9 │
│ 2 2 3 │ 4 5 6 │ 7 8 9 │
│ 3 2 3 │ 4 5 6 │ 7 8 9 │
│───────┼───────┼───────│
│ 4 2 3 │ 4 5 6 │ 7 8 9 │
│ 5 2 3 │ 4 5 6 │ 7 8 9 │
│ 6 2 3 │ 4 5 6 │ 7 8 9 │
│───────┼───────┼───────│
│ 7 2 3 │ 4 5 6 │ 7 8 9 │
│ 8 2 3 │ 4 5 6 │ 7 8 9 │
│ 9 2 3 │ 4 5 6 │ 7 8 9 │
└───────┴───────┴───────┘
true ;
false.

Проблемаесли он НЕ ПРОСТО возвращает с истиной, я должен нажать ;, а затем он возвращает ложь.Это, в свою очередь, означает, что мое prettier_print/1 правило не работает должным образом.

Я думаю, что знаю достаточно, чтобы понять, что это означает:

Пролог откатывает назад и пытается по-другому интерпретировать мои правила(видя, есть ли что-то еще, с чем это может объединиться, если я правильно понимаю мои условия).Это находит еще одну вещь, которую можно объединить с этим, но это немедленно терпит неудачу.Это правильно?

Я хочу, чтобы была только одна возможная интерпретация.Как я могу исправить свою функцию, чтобы это значило?

Спасибо за любую помощь, я чувствую себя таким дураком!

Ответы [ 4 ]

4 голосов
/ 12 апреля 2011

Чтобы увидеть это, попробуйте графический трассировщик SWI-Prolog:

?- gtrace, your_goal.

Трассировщик покажет вам, где создаются точки выбора, вводя недетерминизм. При возврате (например, когда вы нажимаете SPACE или «;» на верхнем уровне), будут рассматриваться оставшиеся альтернативные предложения.

3 голосов
/ 12 апреля 2011

Это «возврат» true, затем false, потому что вы заставляете его вернуться с помощью ;.Поскольку существует только одно решение, возврат не выполняется.

Это происходит только в интерактивных интерпретаторах Пролога;если вы скомпилируете программу или запустите ее в неинтерактивном интерпретаторе, она просто напечатает результат и ничего не «вернет».Это несколько похоже на поведение, например, интерпретатора Python

>>> 'foo'
'foo'

, который отражает значение последнего введенного выражения, но только в интерактивном режиме.Скрипт ничего не напечатает, если вы не введете print операторов.

Если вы не хотите видеть сообщение false, либо не возвращайтесь, то есть нажмите Enter вместо ;или используйте метапредикат once/1:

?- member(X,[1,2,3]).
X = 1 ;
X = 2 .    % ENTER pressed here

?- once(member(X,[1,2,3])).
X = 1.

?- 

, но не делайте этого где-либо в программе, так как это меняет семантику программы.

2 голосов
/ 12 апреля 2011

Причиной возврата значения true, а затем false при возврате является то, что вы оставляете точки выбора в своих пунктах. Ваш поток приложений выполнит только один пункт prettier_print / 2, но интерпретатор пролога не знает об этом заранее, поэтому он оставляет точку выбора и затем, при возврате, попытается увидеть, будет ли какое-либо из оставшихся предложений prettier_print / 2 успех.

Вы можете «сократить» откат, совершив один выбор, используя команду cut (!):

prettier_print([]).
prettier_print([Puzzle]) :- prettier_print(0, [Puzzle]).

prettier_print(0, Puzzle) :-
    writeln('┌───────┬───────┬───────┐'),
    !,
    prettier_print(1, Puzzle).
prettier_print(4, Puzzle) :-
    writeln('│───────┼───────┼───────│'),
    !,
    prettier_print(5, Puzzle).
prettier_print(8, Puzzle) :-
    writeln('│───────┼───────┼───────│'),
    !,
    prettier_print(9, Puzzle).
prettier_print(12, []) :-
    writeln('└───────┴───────┴───────┘'),
    !.
prettier_print(N, [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9 | Puzzle]) :-
    member(N, [1,2,3,5,6,7,9,10,11]),  % tried this when the line below did not work

    format('│ ~d ~d ~d │ ~d ~d ~d │ ~d ~d ~d │~n', [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9]),
    succ(N, N1),
    prettier_print(N1, Puzzle),
    !.

Вы также можете переписать свое решение, чтобы не оставлять точек выбора, используя некоторые другие предикаты вместо других предложений для prettier_print. Таким образом, вам не нужно использовать разрез:

prettier_print(Puzzle) :-
  Puzzle \= [] ->
  (
    print_head,
    print_rows(Puzzle, NRows1),
    print_line,
    print_rows(Puzzle, NRows1),
    print_line,
    print_rows(Puzzle, NRows1),
    print_end
  ).

print_rows(Rows, NRows):-
  print_row(Rows, Rows1),
  print_row(Rows1, Rows2),
  print_row(Rows2, NRows).

print_head:-
    writeln('┌───────┬───────┬───────┐').

print_line:-
    writeln('│───────┼───────┼───────│').

print_end:-
    writeln('└───────┴───────┴───────┘').

print_row([Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9 | NRows], NRows) :-
    format('│ ~d ~d ~d │ ~d ~d ~d │ ~d ~d ~d │~n', [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9]).
0 голосов
/ 12 апреля 2011

Ага, не бери в голову, я идиот!

Я определил что-то, что не было проблемой с самого начала.Меняя prettier_print/1 на это:

prettier_print([]).
prettier_print(Puzzle) :- prettier_print(0, Puzzle).

Обеспечивает нормальную работу.

Я все еще хотел бы понять, почему он возвращает true, а затем false.Если кто-то может ответить, я отмечу его ответ принятым.

...