My goal is to implement the pivot(Before,After)
predicate that returns true when Before
's first half is equal to After
's second half and Before
's second half is equal to After
's first half.
I tried to implement the predicate and it is working but not perfectly. Below is my predicate.
pivot(Before,After) :-
append(A,B,Before),
length(A,N),
length(B,N),
append(B,A,After).
pivot(Before,After) :-
append(A,B,Before),
length(A,N),
N1 is N + 1,
length(B,N1),
append(C,Tail,B),
length(C,1),
append(Tail,C,F),
append(F,A,After).
The pivot(A,[1,2,3,4,5])
is running, but I do not get output.
I am expecting A = [4,5,3,1,2]
.
A possible solution is:
pivot(In, Out) :-
pivot(In, In, Left, Middle, Right),
prepend(Middle, Left, New),
append(Right, New, Out).
pivot([], Ys, [], [], Ys).
pivot([_], [Y|Ys], [], [Y], Ys).
pivot([_,_|Xs], [Y|Ys], [Y|Left], Middle, Right) :-
pivot(Xs, Ys, Left, Middle, Right).
prepend([], Xs, Xs).
prepend([X], Xs, [X|Xs]).
How does the predicate work?
?- trace(pivot,+all), pivot([1,2,3,4], L), trace(pivot,-all).
% pivot/2: [all]
% pivot/5: [all]
T [11] Call: pivot([1, 2, 3, 4], _15324)
T [20] Call: pivot([1, 2, 3, 4], [1, 2, 3, 4], _19198, _19200, _19202)
T [29] Call: pivot([3, 4], [2, 3, 4], _20104, _19200, _19202)
T [38] Call: pivot([], [3, 4], _21006, _19200, _19202)
T [38] Exit: pivot([], [3, 4], [], [], [3, 4])
T [29] Exit: pivot([3, 4], [2, 3, 4], [2], [], [3, 4])
T [20] Exit: pivot([1, 2, 3, 4], [1, 2, 3, 4], [1, 2], [], [3, 4])
T [11] Exit: pivot([1, 2, 3, 4], [3, 4, 1, 2])
% pivot/2: Not tracing
% pivot/5: Not tracing
L = [3, 4, 1, 2].
?- trace(pivot,+all), pivot([1,2,3,4,5], L), trace(pivot,-all).
% pivot/2: [all]
% pivot/5: [all]
T [11] Call: pivot([1, 2, 3, 4, 5], _27180)
T [20] Call: pivot([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], _222, _224, _226)
T [29] Call: pivot([3, 4, 5], [2, 3, 4, 5], _778, _224, _226)
T [38] Call: pivot([5], [3, 4, 5], _1680, _224, _226)
T [38] Exit: pivot([5], [3, 4, 5], [], [3], [4, 5])
T [29] Exit: pivot([3, 4, 5], [2, 3, 4, 5], [2], [3], [4, 5])
T [20] Exit: pivot([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2], [3], [4, 5])
T [11] Exit: pivot([1, 2, 3, 4, 5], [4, 5, 3, 1, 2])
% pivot/2: Not tracing
% pivot/5: Not tracing
L = [4, 5, 3, 1, 2].
Another examples:
?- length(In, _), pivot(In, Out).
In = Out, Out = [] ;
In = Out, Out = [_] ;
In = [_A, _B],
Out = [_B, _A] ;
In = [_A, _B, _C],
Out = [_C, _B, _A] ;
In = [_A, _B, _C, _D],
Out = [_C, _D, _A, _B] ;
In = [_A, _B, _C, _D, _E],
Out = [_D, _E, _C, _A, _B] ;
In = [_A, _B, _C, _D, _E, _F],
Out = [_D, _E, _F, _A, _B, _C] ;
In = [_A, _B, _C, _D, _E, _F, _G],
Out = [_E, _F, _G, _D, _A, _B, _C]
A comparison of the various suggested solutions for this problem, using SWI-Prolog 8.4.3.
slago(In, Out) :-
pivot(In, In, Left, Middle, Right),
prepend(Middle, Left, New),
append(Right, New, Out).
pivot([], Ys, [], [], Ys).
pivot([_], [Y|Ys], [], [Y], Ys).
pivot([_,_|Xs], [Y|Ys], [Y|Left], Middle, Right) :-
pivot(Xs, Ys, Left, Middle, Right).
prepend([], Xs, Xs).
prepend([X], Xs, [X|Xs]).
brebs([A,B|T], LstPivot) :-
same_length([A,B|T], LstPivot),
pivot_list_half_([A,B|T], [A,B|T], Half1, Half2),
append(Half2, Half1, LstPivot).
pivot_list_half_([], H2, [], H2).
pivot_list_half_([_|T], [H|Sgl], H1, H2) :-
pivot_list_half_dbl_(T, H, Sgl, H1, H2).
pivot_list_half_dbl_([], H, H2, [], H2Full) :-
append(H2, [H], H2Full).
pivot_list_half_dbl_([_|T], H, Sgl, [H|H1], H2) :-
pivot_list_half_(T, Sgl, H1, H2).
gusbro(Before, After):-
pivot_df(Before, Before, Before, LAcc-LAcc, LAcc2-LAcc2, After, After, After, RAcc-RAcc, RAcc2-RAcc2).
pivot_df([], _, Before, Before-RightFirstHalf, LeftFirstHalf-[], [], _, After, After-LeftFirstHalf, RightFirstHalf-[]).
pivot_df([_], _, Before, Before-[Middle|RightFirstHalf], LeftFirstHalf-[], [_], _, After, After-[Middle|LeftFirstHalf], RightFirstHalf-[]).
pivot_df([_,_|L1], [A|L2], Before, LAcc-LTail, LAcc2-LTail2, [_,_|L3], [B|L4], After, RAcc-RTail, RAcc2-RTail2):-
LTail=[A|LTail1], RTail=[B|RTail1],
LTail2=[A|LTail21], RTail2=[B|RTail21],
pivot_df(L1, L2, Before, LAcc-LTail1, LAcc2-LTail21, L3, L4, After, RAcc-RTail1, RAcc2-RTail21).
damiano(L,LP):-
length(L,N),
N2 is div(N,2),
findall(E, (nth1(I, L, E), I >= 1, I =< N2), S1),
( 0 is N mod 2 ->
findall(E, (nth1(I, L, E), I > N2, I =< N), S2),
append(S2,S1,LP) ;
N21 is N2 + 2,
findall(E, (nth1(I, L, E), I >= N21, I =< N), S2),
N11 is N2 + 1,
nth1(N11,L,El),
append([El],S1,S11),
append(S2,S11,LP)
).
comparison :-
format(' Length Slago Brebs Gusbro Damiano\n', []),
forall(between(1, 8, I),
( N is 10^6*I,
length(L, N),
findall(T,
( member(P, [slago, brebs, gusbro, damiano]),
runtime(P, L, T)),
Ts),
format('~|~t~w~8+ ~|~t~5f~8+ ~|~t~5f~8+ ~|~t~5f~8+ ~|~t~5f~8+\n', [N|Ts]) )).
runtime(P, L, T) :-
garbage_collect,
T0 is cputime,
call(P, L, _),
T is cputime - T0.
Results:
?- comparison.
Length Slago Brebs Gusbro Damiano
1000000 0.04688 0.07812 0.68750 0.60938
2000000 0.09375 0.17188 0.92188 1.23438
3000000 0.15625 0.26562 0.67188 1.92188
4000000 0.21875 0.35938 1.84375 2.60938
5000000 0.28125 0.46875 1.10938 3.35938
6000000 0.32812 0.56250 1.35938 3.87500
7000000 0.39062 0.64062 3.21875 4.67188
8000000 0.45312 0.70312 3.51562 5.20312
true.
Gusbro's solution caused stack overflow for list with length 9000000.