2017-02-17 18 views
0

Я делаю это упражнение с Learn Prolog Now:своп первые два элемента списка в Прологе

Упражнение 4.4
Написать предикат swap12 (List1, list2), которая проверяет, является ли List1 идентичны List2, за исключением того, что первые два элемента обмениваются.

Это то, что я до сих пор:

swap12([],[]). 
swap12([a, b | Ta], [b, a | Tb]) :- swap12(Ta, Tb). 

Но когда я пытаюсь оценить это, я получаю следующее:

?- swap12(X, Y). 
X = Y, Y = [] ; 
X = [a, b], 
Y = [b, a] ; 
X = [a, b, a, b], 
Y = [b, a, b, a] . 

Что я делаю неправильно?

Цель состоит в том, чтобы иметь что-то вроде следующего:

swap12(X,Y). 
X = [a, b]. 
Y = [b, a]. 
X = [a, b, b]. 
Y = [b, a, a]. 

и т.д., пожалуйста, помогите!

+7

Проблема заключается в замене только первых двух элементов. Вы делаете рекурсивный вызов, который будет заменять каждую последующую пару элементов. Кроме того, вы используете атомы, а не переменные. Атомы начинаются с строчной буквы. Переменные начинаются с заглавной буквы или '_'. Поэтому вы должны написать 'swap12 ([A, B | T], [B, A | T]).' Это все, что вам нужно для замены первых двух элементов любого списка, например, *, 'swap ([a, b, c, d], L). 'будет давать' L = [b, a, c, d] '. – lurker

+0

Я не уверен, что понимаю. вы имеете в виду redefine 'swap12' как' swap12 ([A, B | T], [B, A | T]) '? или передать разные аргументы существующей функции? – dopatraman

+0

Я имею в виду * redefine *. Тебе ничего не нужно. 'swap ([A, B | T], [B, A | T]).' говорит, что '[B, A | T]' является '[A, B | T]', когда первые два элемента заменены (и они в противном случае идентичны, так как они имеют один и тот же хвост 'T'). Разве это не похоже на полное определение для решения проблемы? Вы должны попробовать, если вы все еще не уверены. – lurker

ответ

0

Первый пункт:

swap12([],[]). 

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

Ваша вторая оговорка:

swap12([a, b | Ta], [b, a | Tb]) :- swap12(Ta, Tb). 

Это говорит о том, что , если поменять местами первые два элемента [a, b | Ta] результат [b, a | Tb] если Tb является Ta с его первые два элемента местами. Это правило для любого списка, который начинается с a и b, но не будет работать, если у вас есть какой-либо другого первых два элемента, потому что a и b являются атомами, а не переменных. Так, например, swap12([1,2,3,4], L) потерпит неудачу, так как ваш список начинается с 1 и 2, а не a и b. Кроме того, ваша проблема заключается в обмене ТОЛЬКО первых двух элементов, тогда как ваше решение имеет рекурсивный вызов swap12(Ta, Tb), который продолжает рекурсивно менять.

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

?- swap12([a,b], R). 
R = [b,a]. 

?- swap12([b,a], R). 
false. % This fails because `b`, `a` doesn't match `a`, `b`. 

?- swap12([a,b,c], R). 
false. % This fails because [a,b,c] has an odd number of elements 

?- swap12([a,b,c,d], R). 
false. % This fails because `c`, `d` doesn't match `a` and `b` 

?- swap12([a,b,a,b], R). 
R = [b, a, b, a]. 

?- swap12(X, Y). 
X = Y, Y = [] ; 
X = [a, b], 
Y = [b, a] ; 
X = [a, b, a, b], 
Y = [b, a, b, a] ; 
X = [a, b, a, b, a, b], 
Y = [b, a, b, a, b, a] ; 
X = [a, b, a, b, a, b, a, b], 
Y = [b, a, b, a, b, a, b, a] ; 
... 

Последнее исполнение показывает, что на самом деле означают ваши правила. Это удается только в том случае, если первый список пуст или любое количество пар a, b, а второй список одинаковый для каждой пары a, b, замененной на b, a.

Давайте начнем сначала. Проблема, опять же, заключается в создании правила, которое является истинным, если второй список является первым списком с ТОЛЬКО первые два элемента заменены.Список, имеющий по крайней мере два элемента, выглядит как [X, Y|T] (первые два элемента: X и Y - переменные). Если я хочу поменять ТОЛЬКО первые два элемента, я хотел бы написать, [Y, X|T] поэтому я сменил X и Y, но держать же хвост, T (я не хочу, чтобы поменять местами какие-либо другие элементы).

Таким образом, правило просто выглядит следующим образом:

swap12([X, Y|T], [Y, X|T]). 

Это говорит о том, что если у меня есть список [X, Y|T], то [Y, X|T] тот же список, но только первые два элемента поменялись. Вы можете попробовать:

?- swap12([a], R). 
false.  % fails because `[a]` only has one element! 

?- swap12([a,b], R). 
R = [b, a]. 

?- swap12([a,b,c], R). 
R = [b, a, c]. 

?- swap12([a,b,c,d], R). 
R = [b, a, c, d]. 

?- swap12([a,b,c,e,f], R). 
R = [b, a, c, e, f]. 

?- ... 
+1

Я получаю его сейчас. Спасибо – dopatraman