Как разобрать список в прологе пока не подведет

Просто вызовите scanf ("% * [^\n]\n") внутри цикла и отбросит «кеш».

1
задан coder 27 February 2019 в 08:43
поделиться

3 ответа

Если вы хотите более краткое решение, используя maplist/2, вы можете сделать что-то вроде:

isTwo(2) :- write('Yes'), !.
isTwo(_):- write('No').

test(L):-
    maplist(isTwo,L).

?- test([1,3,3,2,2,7,2,9]).
NoNoNoYesYesNoYesNo
true

test/1 не является обязательным, я добавил его только для ясности ...

0
ответ дан damianodamiano 27 February 2019 в 08:43
поделиться

Что ж, простым решением было бы использование второй переменной в iter, которая поможет вам понять, если найдено число, отличное от 2:

isTwo(2, X, X) :- 
    write('Yes').

isTwo(_, _, 0) :- 
    write('No').


iter([],  0):- fail,!.
iter([],  1).
iter([Head|Tail], X) :-
    isTwo(Head, X, Y),
    iter(Tail, Y).


iter(L) :- iter(L, 1).
0
ответ дан coder 27 February 2019 в 08:43
поделиться

Другие ответы тоже хороши, но случайное смешение побочных эффектов заставляет меня немного нервничать. Кроме того, у вас есть проблема, если список, который вы «анализируете», имеет свободную переменную (она станет 2 молча).

Почему бы не так:

is_two(X) :- X == 2, !, format("Yes").
is_two(X) :- X \== 2, !, format("No").

, а затем:

?- forall(member(X, [1,3,3,2,2,7,2,9]), is_two(X)).
NoNoNoYesYesNoYesNo
true.

?- forall(member(X, [Y, 2, Z]), is_two(X)).
NoYesNo
true.

Используйте == и \== для сравнения без объединения. Используйте forall и member, чтобы прояснить, что вы делаете это для побочного эффекта. Обход списка (или использование maplist) немного обманывает.

forall - это просто более ясный способ сделать цикл, управляемый отказом, используя отрицание вместо сокращений и неудач. Вышеприведенный запрос идентичен:

?- \+ ( member(X, [1,3,3,2,2,7,2,9]), \+ is_two(X) ).
0
ответ дан User9213 27 February 2019 в 08:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: