Первый пункт:
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].
?- ...
Проблема заключается в замене только первых двух элементов. Вы делаете рекурсивный вызов, который будет заменять каждую последующую пару элементов. Кроме того, вы используете атомы, а не переменные. Атомы начинаются с строчной буквы. Переменные начинаются с заглавной буквы или '_'. Поэтому вы должны написать 'swap12 ([A, B | T], [B, A | T]).' Это все, что вам нужно для замены первых двух элементов любого списка, например, *, 'swap ([a, b, c, d], L). 'будет давать' L = [b, a, c, d] '. – lurker
Я не уверен, что понимаю. вы имеете в виду redefine 'swap12' как' swap12 ([A, B | T], [B, A | T]) '? или передать разные аргументы существующей функции? – dopatraman
Я имею в виду * redefine *. Тебе ничего не нужно. 'swap ([A, B | T], [B, A | T]).' говорит, что '[B, A | T]' является '[A, B | T]', когда первые два элемента заменены (и они в противном случае идентичны, так как они имеют один и тот же хвост 'T'). Разве это не похоже на полное определение для решения проблемы? Вы должны попробовать, если вы все еще не уверены. – lurker