Неожиданный результат правила

#prolog

Вопрос:

Я попытался написать правило, которое проверяет, является ли список цепочкой, как:
[[5,2],[2,4]] — правда
[[7,2],[4,0]] — false
[[1,2]] — ложь, списки с одним элементом тоже не являются цепочками.

Итак, шаблон такой [[a,b], [b,c], [c,d], ...] (внутренние списки всегда содержат два элемента, и любой из a, b, c, d… может быть равен).

 chain([]):-!. chain([X]):-false. chain([_|[]]):-!. chain([[_, X2]|[[Y1, Y2]|Tail]]):-  X2 == Y1,  chain([[Y1, Y2]|Tail]).  

С -? chain([[1,2]]). Я понял правду, что сбивает меня с толку.

Также я пытался заменить вторую строку на chain(L):-length(L, Len),Lengt;1. , но результат остался прежним.

Я ценю любую помощь и объяснение.

Комментарии:

1. Можете ли вы объяснить своими словами, что такое «цепочка»? Минимальная длина его, минимальная длина отдельных звеньев в цепи? Являются ли они обязательно целыми числами или они могут быть другими терминами пролога? и так далее. Слишком много, чтобы гадать в данный момент. Например, это цепочка: [[1],[1]] ? Как насчет этого: [[a,b],[b,a]] ?

2. как насчет этого: [[1,1,1],[1]] ? Или ссылки всегда состоят ровно из 2 элементов?

3. Извините, я должен был объяснить это более подробно. В моем случае значения всегда являются целыми числами. Внутренние списки больше похожи на кортежи, чем на самом деле списки, их длина всегда должна быть 2. Итак, шаблон, который я хочу проверить, [[a, b], [b, c], [c, d],…], включая случай, когда любое из этих значений равно.

4. Так получается, что в «цепочке» есть 2 или более звеньев, где каждое звено представляет собой пару, а первый элемент пары совпадает со вторым элементом предыдущей пары? Никаких других ограничений (потому что во всех ваших примерах элементы также монотонно увеличиваются… является ли это цепочкой: [[a, b], [b,a]] ?

5. Вопрос тоже обновлен. Спасибо за комментарии. И да, никаких других особых ограничений нет и [[a, b], [b,a]] есть цепочка.

Ответ №1:

Нет необходимости явно терпеть неудачу. Просто не пишите правило для этого случая, тогда правило потерпит неудачу, потому что оно не может быть успешным.

Вот один из способов сделать это:

 chain([[_,X],[X,Y]|Rest]) :-  chain_1(Rest, Y).  chain_1([], _). chain_1([[X,Y]|Rest], X) :-  chain_1(Rest, Y).  

Работает ли это для всех ваших угловых случаев?


Здесь очень мало что можно объяснить. Если что-то не очевидно, задавайте конкретные вопросы.

Поскольку в этих краях существует определенная одержимость самыми общими вопросами, и я прирожденный угодник толпы, я поступлю так, как поступают римляне:

 ?- chain(X). X = [[_, _A], [_A, _]] ; X = [[_, _A], [_A, _B], [_B, _]] ; X = [[_, _A], [_A, _B], [_B, _C], [_C, _]] ; X = [[_, _A], [_A, _B], [_B, _C], [_C, _D], [_D, _]] .  

Круто!

Поскольку chain_1/2 является левой складкой в списке, вы можете записать это как:

 chain([[_,X],[X,Y]|Rest]) :-  foldl(chain_rule, Rest, Y, _).  chain_rule([X,Y], X, Y).  

Это не становится более читабельным, но вы можете похвастаться перед своими друзьями.

Комментарии:

1. Это прекрасно работает! Большое спасибо за ответы на такие глупые вопросы! Я думаю, что нет необходимости что-то объяснять, этот пример очень ясен. Спасибо!