#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. Это прекрасно работает! Большое спасибо за ответы на такие глупые вопросы! Я думаю, что нет необходимости что-то объяснять, этот пример очень ясен. Спасибо!