RosettaCodeData/Task/Perfect-shuffle/Picat/perfect-shuffle-1.picat
2023-07-01 13:44:08 -04:00

83 lines
1.8 KiB
Text

go =>
member(N,[8,24,52,100,1020,1024,10_000]),
println(n=N),
InOut = out, % in/out shuffling
println(inOut=InOut),
Print = cond(N < 100, true,false),
if Print then
println(1..N),
end,
Count = show_all_shuffles(N,InOut,Print),
println(count=Count),
nl,
fail,
nl.
%
% Show all the shuffles
%
show_all_shuffles(N,InOut) = show_all_shuffles(N,InOut,false).
show_all_shuffles(N,InOut,Print) = Count =>
Order = 1..N,
Perfect1 = perfect_shuffle(1..N,InOut),
Perfect = copy_term(Perfect1),
if Print == true then
println(Perfect)
end,
Count = 1,
while (Perfect != Order)
Perfect := [Perfect1[Perfect[I]] : I in 1..N],
if Print == true then
println(Perfect)
end,
Count := Count + 1
end.
%
% Perfect shuffle a list
%
% InOut = in|out
% in: first card in Top half is the first card in the new deck
% out: first card in Bottom half is the first card in the new deck
%
perfect_shuffle(List,InOut) = Perfect =>
[Top,Bottom] = split_deck(List,InOut),
if InOut = out then
Perfect = zip2(Top,Bottom)
else
Perfect = zip2(Bottom,Top)
end.
%
% split the deck in two "halves"
%
% For odd out shuffles, we have to adjust the
% range of the top and bottom.
%
split_deck(L,InOut) = [Top,Bottom] =>
N = L.len,
if InOut = out, N mod 2 = 1 then
Top = 1..(N div 2)+1,
Bottom = (N div 2)+2..N
else
Top = 1..(N div 2),
Bottom = (N div 2)+1..N
end.
%
% If L1 and L2 has uneven lengths, we add the odd element last
% in the resulting list.
%
zip2(L1,L2) = R =>
L1Len = L1.len,
L2Len = L2.len,
R1 = [],
foreach(I in 1..min(L1Len,L2Len))
R1 := R1 ++ [L1[I],L2[I]]
end,
if L1Len < L2Len then
R1 := R1 ++ [L2[L2Len]]
elseif L1Len > L2Len then
R1 := R1 ++ [L1[L1Len]]
end,
R = R1.