I've been trying to write a program that compares two lists hat are the same except the last two elements of List 2 are in reverse order, i.e [4,5,6] and [4,6,5], and that returns the last two elements that have been swapped.
For example:
SwapLastTwo([4, 5, 6] , [ 4, 6, 5], X).
should return
X = [6, 5]
So far my code looks like this:
lastTwoReversed([Z,A|T],[_,Y,X]) :-reverse([Z,A|T],[Y,X|_]).
My predicate so far only takes two arguments and checks, if are the same except the last two elements of List 2 are in reverse order and returns true
, if the condsitions are met
I don't know how I can modify my predicate to incoparate the X
as its third argument and make it return the swapped elements.
You just want the last element of the list. Try this: lastElement([Head]) :- write(Head). lastElement([_|Tail]):- lastElement(Tail).
Count the number of element in the list before call the predicate that delete the last element. Iterate by recursion and decrement the value of the number of element each time. If it is true that the number of element is 0 it means that this is the last element so I delete it from the original list.
You can move unification into the head of the clause and simply write: second([_, Second| _], Second). The notation for lists is to write the initial elements separated by commas and then a vertical bar to separate the list tail, i.e. the list containing the rest of the elements.
This predicate can be used to select an element from a list, delete an element or insert it. The definition of this Prolog library predicate is: select(A, [A|B], B). select(A, [B, C|D], [B|E]) :- select(A, [C|D], E).
Try this:
lastTwoReversed(L1, L2, [X1,X2]) :-
reverse(L1, [X1,X2|Rest]),
reverse(L2, [X2,X1|Rest]).
Notice that by using the variable Rest
in both subgoals, you establish that the lists must be the same, except for the last two items (which are swapped).
Example:
?- lastTwoReversed([1,2,3,4,5,6], [1,2,3,4,6,5], R).
R = [6, 5].
?- lastTwoReversed([1,2,3,4,5,6], [1,2,3,6,5], R).
false.
?- lastTwoReversed([1,2,3,4,5,6], [1,2,3,4,5,6], R).
false.
Using first-argument indexing, and improved performance by removing the unnecessary reverse(), and also same_length():
swap_last_2([Elem1, Elem2|Tail], SwappedLst, Last2) :-
% same_length would prevent an unwanted choicepoint on: swap_last_2(L, [a,b], SL).
%same_length([Elem1, Elem2|Tail], SwappedLst),
swap_last_2_(Tail, Elem1, Elem2, SwappedLst, Last2).
% Swap the last 2 elements
swap_last_2_([], Elem1, Elem2, [Elem2, Elem1], [Elem2, Elem1]).
swap_last_2_([Head|Tail], Elem1, Elem2, [Elem1|SwappedLst], Last2) :-
% Move the elements along
swap_last_2_(Tail, Elem2, Head, SwappedLst, Last2).
Result in swi-prolog:
?- swap_last_2([4, 5, 6], [4, 6, 5], X).
X = [6,5].
Performance comparison (this method is fastest):
?- cmp(1000, 1000).
% 7,011,001 inferences, 0.503 CPU in 0.497 seconds (101% CPU, 13941510 Lips)
% 2,001,001 inferences, 0.282 CPU in 0.278 seconds (101% CPU, 7098617 Lips)
% 2,007,001 inferences, 0.205 CPU in 0.203 seconds (101% CPU, 9782721 Lips)
% 1,002,001 inferences, 0.063 CPU in 0.063 seconds (101% CPU, 15819840 Lips)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With