Остановите Пролог из выводящих значений - PullRequest
0 голосов
/ 27 декабря 2018

Если я запускаю solved([[x, o, o], [o, o, o], [o, o, o]]), он должен вывести true, поскольку есть только x, а если я запускаю solved([[x, o, o], [o, o, o], [o, o, x]]), он должен вывести false, поскольку существует более 1 x.Тем не менее, при его запуске все время выводится значение true, поскольку выводится значение для C.

:- use_module(library(clpfd)).

rotate_clock(Xss, Zss) :-
   transpose(Xss, Yss),
   maplist(reverse, Yss, Zss).

rotate_anti(Xss, Zss) :-
   maplist(reverse, Xss, Yss),
   transpose(Yss, Zss).

linjmp([x, x, o | T], [o, o, x | T]).
linjmp([o, x, x | T], [x, o, o | T]).
linjmp([H|T1], [H|T2]) :- linjmp(T1,T2).

horizjmp([A|T],[B|T]) :- linjmp(A,B).
horizjmp([H|T1],[H|T2]) :- horizjmp(T1,T2).

jump(B,A) :- horizjmp(B,A).
jump(B,A) :- rotate_clock(B,BR), horizjmp(BR,BRJ), rotate_anti(BRJ, A).

num_x(A, C) :- count(A, x, C).

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([_|T],X,Z):- count(T,X,Z).

sum_list([], 0).
sum_list([H|T], Sum) :-
   sum_list(T, Rest),
   Sum is H + Rest.

solved(A) :-
   maplist(num_x, A, B),
   sum_list(B, C),
   C == 1.

1 Ответ

0 голосов
/ 27 декабря 2018

Вместо того, чтобы пытаться изменить поведение языка (что может быть возможно, но, конечно, является проблемой), было бы лучше выяснить, почему в конечном итоге Пролог находит C с C == 1.Если мы сами оценим maplist(num_x, A, B), то увидим:

?- maplist(num_x, [[x, o, o], [o, o, o], [o, o, x]], B).
B = [1, 0, 1] ;
B = [1, 0, 0] ;
B = [0, 0, 1] ;
B = [0, 0, 0].

Таким образом, получается, что предикат num_x/2 может генерировать несколько результатов для одного и того же списка: для списка с одним xсначала генерируется 1, а затем 0.

Это подтверждается, если мы проведем несколько тестов с count/3:

?- count([x, o, o], x, C).
C = 1 ;
C = 0.

?- count([x, x, o], x, C).
C = 2 ;
C = 1 ;
C = 1 ;
C = 0.

Таким образом, кажется, что count/3 каждыйвремя имеет точку возврата, где оно может решить подсчитать данный x или нет.

Действительно, если мы посмотрим на предикат count/3, мы увидим:

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count(<b>[_|T]</b>,X,Z):- count(T,X,Z).

Так что здесь для непустого списка есть два предложения way: одно, где head равен X, элемент, который мы хотим считать, в этом случае Y is 1+Z, но последнее предложение говорит, что независимо отКакова ценность головы, Пролог не будет считать этот элемент.Prolog выполняет откат назад и, таким образом, в конечном итоге выберет оба предложения.

Мы можем добавить dif/2, чтобы добавить ограничение на то, что заголовок и X должны быть dif ferrent, например:

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count(<b>[H|T]</b>,X,Z):- <b>dif(H, X)</b>, count(T,X,Z).

Так что теперь, если в списке появится X, мы будем считать этот элемент.

...