Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,2 @@
---
from: http://rosettacode.org/wiki/Perfect_shuffle

View file

@ -0,0 +1,86 @@
A perfect shuffle (or [https://en.wikipedia.org/wiki/Faro_shuffle faro/weave shuffle]) means splitting a deck of cards into equal halves, and perfectly interleaving them - so that you end up with the first card from the left half, followed by the first card from the right half, and so on:
<big>
<!-- START OF DIAGRAM -->
::: <div style="display:inline-block;margin:0.5em 1.5em"><tt><span style="background:#8DF">7♠</span> <span style="background:#8DF">8♠</span> <span style="background:#8DF">9♠</span> <span style="background:#FB5">J♠</span> <span style="background:#FB5">Q♠</span> <span style="background:#FB5">K♠</span></tt></div><div style="display:inline-block">&rarr;<div style="display:inline-block;vertical-align:middle;margin:0.5em 1.5em"><tt><span style="background:#8DF">7♠</span>&nbsp; <span style="background:#8DF">8♠</span>&nbsp; <span style="background:#8DF">9♠</span></tt><br><tt>&nbsp;&nbsp;<span style="background:#FB5">J♠</span>&nbsp; <span style="background:#FB5">Q♠</span>&nbsp; <span style="background:#FB5">K♠</span></tt></div></div><div style="display:inline-block">&rarr;<div style="display:inline-block;vertical-align:middle;margin:0.5em 1.5em"><tt><span style="background:#8DF">7♠</span> <span style="background:#FB5">J♠</span> <span style="background:#8DF">8♠</span> <span style="background:#FB5">Q♠</span> <span style="background:#8DF">9♠</span> <span style="background:#Fb5">K♠</span></tt></div></div>
<!-- END OF DIAGRAM -->
</big>
When you repeatedly perform perfect shuffles on an even-sized deck of unique cards, it will at some point arrive back at its original order. How many shuffles this takes, depends solely on the number of cards in the deck - for example for a deck of eight cards it takes three shuffles:
<big>
<!-- START OF DIAGRAM -->
::::: {| style="border-spacing:0.5em 0;border-collapse:separate;margin:0 1em;text-align:right"
|-
| <small>''original:''</small> ||
<tt style="background:#122CF8;color:#B8C0FD;padding:0 0.3em">1</tt>
<tt style="background:#332AD7;color:#C2C0F3;padding:0 0.3em">2</tt>
<tt style="background:#5428B7;color:#CCBFEA;padding:0 0.3em">3</tt>
<tt style="background:#752696;color:#D6BEE0;padding:0 0.3em">4</tt>
<tt style="background:#962576;color:#E0BED6;padding:0 0.3em">5</tt>
<tt style="background:#B72355;color:#EABDCC;padding:0 0.3em">6</tt>
<tt style="background:#D82135;color:#F3BDC3;padding:0 0.3em">7</tt>
<tt style="background:#F92015;color:#FDBDB9;padding:0 0.3em">8</tt>
|-
| <small>''after 1st shuffle:''</small> ||
<tt style="background:#122CF8;color:#B8C0FD;padding:0 0.3em">1</tt>
<tt style="background:#962576;color:#E0BED6;padding:0 0.3em">5</tt>
<tt style="background:#332AD7;color:#C2C0F3;padding:0 0.3em">2</tt>
<tt style="background:#B72355;color:#EABDCC;padding:0 0.3em">6</tt>
<tt style="background:#5428B7;color:#CCBFEA;padding:0 0.3em">3</tt>
<tt style="background:#D82135;color:#F3BDC3;padding:0 0.3em">7</tt>
<tt style="background:#752696;color:#D6BEE0;padding:0 0.3em">4</tt>
<tt style="background:#F92015;color:#FDBDB9;padding:0 0.3em">8</tt>
|-
| <small>''after 2nd shuffle:''</small> ||
<tt style="background:#122CF8;color:#B8C0FD;padding:0 0.3em">1</tt>
<tt style="background:#5428B7;color:#CCBFEA;padding:0 0.3em">3</tt>
<tt style="background:#962576;color:#E0BED6;padding:0 0.3em">5</tt>
<tt style="background:#D82135;color:#F3BDC3;padding:0 0.3em">7</tt>
<tt style="background:#332AD7;color:#C2C0F3;padding:0 0.3em">2</tt>
<tt style="background:#752696;color:#D6BEE0;padding:0 0.3em">4</tt>
<tt style="background:#B72355;color:#EABDCC;padding:0 0.3em">6</tt>
<tt style="background:#F92015;color:#FDBDB9;padding:0 0.3em">8</tt>
|-
| <small>''after 3rd shuffle:''</small> ||
<tt style="background:#122CF8;color:#B8C0FD;padding:0 0.3em">1</tt>
<tt style="background:#332AD7;color:#C2C0F3;padding:0 0.3em">2</tt>
<tt style="background:#5428B7;color:#CCBFEA;padding:0 0.3em">3</tt>
<tt style="background:#752696;color:#D6BEE0;padding:0 0.3em">4</tt>
<tt style="background:#962576;color:#E0BED6;padding:0 0.3em">5</tt>
<tt style="background:#B72355;color:#EABDCC;padding:0 0.3em">6</tt>
<tt style="background:#D82135;color:#F3BDC3;padding:0 0.3em">7</tt>
<tt style="background:#F92015;color:#FDBDB9;padding:0 0.3em">8</tt>
|}
<!-- END OF DIAGRAM -->
</big>
<p style="font-size:115%; margin:1em 0 0.5em 0">'''''The Task'''''</p>
# Write a function that can perform a perfect shuffle on an even-sized list of values.
# Call this function repeatedly to count how many shuffles are needed to get a deck back to its original order, for each of the deck sizes listed under "Test Cases" below.
#* <small>You can use a list of numbers (or anything else that's convenient) to represent a deck; just make sure that all "cards" are unique within each deck.</small>
#* <small>Print out the resulting shuffle counts, to demonstrate that your program passes the test-cases.</small>
<p style="font-size:115%; margin:1em 0 0.5em 0">'''''Test Cases'''''</p>
::::: {| class="wikitable"
|-
! input ''(deck size)'' !! output ''(number of shuffles required)''
|-
| 8 || 3
|-
| 24 || 11
|-
| 52 || 8
|-
| 100 || 30
|-
| 1020 || 1018
|-
| 1024 || 10
|-
| 10000 || 300
|}
<br><br>

View file

@ -0,0 +1,24 @@
F flatten(lst)
[Int] r
L(sublst) lst
L(i) sublst
r [+]= i
R r
F magic_shuffle(deck)
V half = deck.len I/ 2
R flatten(zip(deck[0 .< half], deck[half ..]))
F after_how_many_is_equal(start, end)
V deck = magic_shuffle(start)
V counter = 1
L deck != end
deck = magic_shuffle(deck)
counter++
R counter
print(Length of the deck of cards | Perfect shuffles needed to obtain the same deck back)
L(length) (8, 24, 52, 100, 1020, 1024, 10000)
V deck = Array(0 .< length)
V shuffles_needed = after_how_many_is_equal(deck, deck)
print(#<5 | #..format(length, shuffles_needed))

View file

@ -0,0 +1,58 @@
# returns an array of the specified length, initialised to an ascending sequence of integers #
OP DECK = ( INT length )[]INT:
BEGIN
[ 1 : length ]INT result;
FOR i TO UPB result DO result[ i ] := i OD;
result
END # DECK # ;
# in-place shuffles the deck as per the task requirements #
# LWB deck is assumed to be 1 #
PROC shuffle = ( REF[]INT deck )VOID:
BEGIN
[ 1 : UPB deck ]INT result;
INT left pos := 1;
INT right pos := ( UPB deck OVER 2 ) + 1;
FOR i FROM 2 BY 2 TO UPB result DO
result[ left pos ] := deck[ i - 1 ];
result[ right pos ] := deck[ i ];
left pos +:= 1;
right pos +:= 1
OD;
FOR i TO UPB deck DO deck[ i ] := result[ i ] OD
END # SHUFFLE # ;
# compares two integer arrays for equality #
OP = = ( []INT a, b )BOOL:
IF LWB a /= LWB b OR UPB a /= UPB b
THEN # the arrays have different bounds #
FALSE
ELSE
BOOL result := TRUE;
FOR i FROM LWB a TO UPB a WHILE result := a[ i ] = b[ i ] DO SKIP OD;
result
FI # = # ;
# compares two integer arrays for inequality #
OP /= = ( []INT a, b )BOOL: NOT ( a = b );
# returns the number of shuffles required to return a deck of the specified length #
# back to its original state #
PROC count shuffles = ( INT length )INT:
BEGIN
[] INT original deck = DECK length;
[ 1 : length ]INT shuffled deck := original deck;
INT count := 1;
WHILE shuffle( shuffled deck );
shuffled deck /= original deck
DO
count +:= 1
OD;
count
END # count shuffles # ;
# test the shuffling #
[]INT lengths = ( 8, 24, 52, 100, 1020, 1024, 10 000 );
FOR l FROM LWB lengths TO UPB lengths DO
print( ( whole( lengths[ l ], -8 ) + ": " + whole( count shuffles( lengths[ l ] ), -6 ), newline ) )
OD

View file

@ -0,0 +1,3 @@
faro (2,2÷)
count { r :1 1+r}
(,[1.5] (faro count )¨) 8 24 52 100 1020 1024 10000

View file

@ -0,0 +1,61 @@
DEFINE MAXDECK="5000"
PROC Order(INT ARRAY deck INT count)
INT i
FOR i=0 TO count-1
DO
deck(i)=i
OD
RETURN
BYTE FUNC IsOrdered(INT ARRAY deck INT count)
INT i
FOR i=0 TO count-1
DO
IF deck(i)#i THEN
RETURN (0)
FI
OD
RETURN (1)
PROC Shuffle(INT ARRAY src,dst INT count)
INT i,i1,i2
i=0 i1=0 i2=count RSH 1
WHILE i<count
DO
dst(i)=src(i1) i==+1 i1==+1
dst(i)=src(i2) i==+1 i2==+1
OD
RETURN
PROC Test(INT ARRAY deck,deck2 INT count)
INT ARRAY tmp
INT n
Order(deck,count)
n=0
DO
Shuffle(deck,deck2,count)
tmp=deck deck=deck2 deck2=tmp
n==+1
Poke(77,0) ;turn off the attract mode
PrintF("%I cards -> %I iterations%E",count,n)
Put(28) ;move cursor up
UNTIL IsOrdered(deck,count)
OD
PutE()
RETURN
PROC Main()
INT ARRAY deck(MAXDECK),deck2(MAXDECK)
INT ARRAY counts=[8 24 52 100 1020 1024 MAXDECK]
INT i
FOR i=0 TO 6
DO
Test(deck,deck2,counts(i))
OD
RETURN

View file

@ -0,0 +1,28 @@
with ada.text_io;use ada.text_io;
procedure perfect_shuffle is
function count_shuffle (half_size : Positive) return Positive is
subtype index is Natural range 0..2 * half_size - 1;
subtype index_that_move is index range index'first+1..index'last-1;
type deck is array (index) of index;
initial, d, next : deck;
count : Natural := 1;
begin
for i in index loop initial (i) := i; end loop;
d := initial;
loop
for i in index_that_move loop
next (i) := (if d (i) mod 2 = 0 then d(i)/2 else d(i)/2 + half_size);
end loop;
exit when next (index_that_move)= initial(index_that_move);
d := next;
count := count + 1;
end loop;
return count;
end count_shuffle;
test : array (Positive range <>) of Positive := (8, 24, 52, 100, 1020, 1024, 10_000);
begin
for size of test loop
put_line ("For" & size'img & " cards, there are "& count_shuffle (size / 2)'img & " shuffles needed.");
end loop;
end perfect_shuffle;

View file

@ -0,0 +1,18 @@
perfectShuffle: function [deckSize][
deck: 1..deckSize
original: new deck
halfDeck: deckSize/2
i: 1
while [true][
deck: flatten couple first.n: halfDeck deck last.n: halfDeck deck
if deck = original -> return i
i: i+1
]
]
loop [8 24 52 100 1020 1024 10000] 's ->
print [
pad.right join @["Perfect shuffles required for deck size " to :string s ":"] 48
perfectShuffle s
]

View file

@ -0,0 +1,6 @@
Shuffle(cards){
n := cards.MaxIndex()/2, res := []
loop % n
res.push(cards[A_Index]), res.push(cards[round(A_Index + n)])
return res
}

View file

@ -0,0 +1,17 @@
test := [8, 24, 52, 100, 1020, 1024, 10000]
for each, val in test
{
cards := [], original:=rep:=""
loop, % val
cards.push(A_Index), original .= (original?", ":"") A_Index
while (res <> original)
{
res := ""
for k, v in (cards := Shuffle(cards))
res .= (res?", ":"") v
rep := A_Index
}
result .= val "`t" rep "`n"
}
MsgBox % result
return

View file

@ -0,0 +1,38 @@
#include <iostream>
#include <algorithm>
#include <vector>
int pShuffle( int t ) {
std::vector<int> v, o, r;
for( int x = 0; x < t; x++ ) {
o.push_back( x + 1 );
}
r = o;
int t2 = t / 2 - 1, c = 1;
while( true ) {
v = r;
r.clear();
for( int x = t2; x > -1; x-- ) {
r.push_back( v[x + t2 + 1] );
r.push_back( v[x] );
}
std::reverse( r.begin(), r.end() );
if( std::equal( o.begin(), o.end(), r.begin() ) ) return c;
c++;
}
}
int main() {
int s[] = { 8, 24, 52, 100, 1020, 1024, 10000 };
for( int x = 0; x < 7; x++ ) {
std::cout << "Cards count: " << s[x] << ", shuffles required: ";
std::cout << pShuffle( s[x] ) << ".\n";
}
return 0;
}

View file

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
public static class PerfectShuffle
{
static void Main()
{
foreach (int input in new [] {8, 24, 52, 100, 1020, 1024, 10000}) {
int[] numbers = Enumerable.Range(1, input).ToArray();
Console.WriteLine($"{input} cards: {ShuffleThrough(numbers).Count()}");
}
IEnumerable<T[]> ShuffleThrough<T>(T[] original) {
T[] copy = (T[])original.Clone();
do {
yield return copy = Shuffle(copy);
} while (!Enumerable.SequenceEqual(original, copy));
}
}
public static T[] Shuffle<T>(T[] array) {
if (array.Length % 2 != 0) throw new ArgumentException("Length must be even.");
int half = array.Length / 2;
T[] result = new T[array.Length];
for (int t = 0, l = 0, r = half; l < half; t+=2, l++, r++) {
result[t] = array[l];
result[t+1] = array[r];
}
return result;
}
}

View file

@ -0,0 +1,110 @@
/* ===> INCLUDES <============================================================*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* ===> CONSTANTS <===========================================================*/
#define N_DECKS 7
const int kDecks[N_DECKS] = { 8, 24, 52, 100, 1020, 1024, 10000 };
/* ===> FUNCTION PROTOTYPES <=================================================*/
int CreateDeck( int **deck, int nCards );
void InitDeck( int *deck, int nCards );
int DuplicateDeck( int **dest, const int *orig, int nCards );
int InitedDeck( int *deck, int nCards );
int ShuffleDeck( int *deck, int nCards );
void FreeDeck( int **deck );
/* ===> FUNCTION DEFINITIONS <================================================*/
int main() {
int i, nCards, nShuffles;
int *deck = NULL;
for( i=0; i<N_DECKS; ++i ) {
nCards = kDecks[i];
if( !CreateDeck(&deck,nCards) ) {
fprintf( stderr, "Error: malloc() failed!\n" );
return 1;
}
InitDeck( deck, nCards );
nShuffles = 0;
do {
ShuffleDeck( deck, nCards );
++nShuffles;
} while( !InitedDeck(deck,nCards) );
printf( "Cards count: %d, shuffles required: %d.\n", nCards, nShuffles );
FreeDeck( &deck );
}
return 0;
}
int CreateDeck( int **deck, int nCards ) {
int *tmp = NULL;
if( deck != NULL )
tmp = malloc( nCards*sizeof(*tmp) );
return tmp!=NULL ? (*deck=tmp)!=NULL : 0; /* (?success) (:failure) */
}
void InitDeck( int *deck, int nCards ) {
if( deck != NULL ) {
int i;
for( i=0; i<nCards; ++i )
deck[i] = i;
}
}
int DuplicateDeck( int **dest, const int *orig, int nCards ) {
if( orig != NULL && CreateDeck(dest,nCards) ) {
memcpy( *dest, orig, nCards*sizeof(*orig) );
return 1; /* success */
}
else {
return 0; /* failure */
}
}
int InitedDeck( int *deck, int nCards ) {
int i;
for( i=0; i<nCards; ++i )
if( deck[i] != i )
return 0; /* not inited */
return 1; /* inited */
}
int ShuffleDeck( int *deck, int nCards ) {
int *copy = NULL;
if( DuplicateDeck(&copy,deck,nCards) ) {
int i, j;
for( i=j=0; i<nCards/2; ++i, j+=2 ) {
deck[j] = copy[i];
deck[j+1] = copy[i+nCards/2];
}
FreeDeck( &copy );
return 1; /* success */
}
else {
return 0; /* failure */
}
}
void FreeDeck( int **deck ) {
if( *deck != NULL ) {
free( *deck );
*deck = NULL;
}
}

View file

@ -0,0 +1,12 @@
(defn perfect-shuffle [deck]
(let [half (split-at (/ (count deck) 2) deck)]
(interleave (first half) (last half))))
(defn solve [deck-size]
(let [original (range deck-size)
trials (drop 1 (iterate perfect-shuffle original))
predicate #(= original %)]
(println (format "%5s: %s" deck-size
(inc (some identity (map-indexed (fn [i x] (when (predicate x) i)) trials)))))))
(map solve [8 24 52 100 1020 1024 10000])

View file

@ -0,0 +1,21 @@
(defun perfect-shuffle (deck)
(let* ((half (floor (length deck) 2))
(left (subseq deck 0 half))
(right (nthcdr half deck)))
(mapcan #'list left right)))
(defun solve (deck-size)
(loop with original = (loop for n from 1 to deck-size collect n)
for trials from 1
for deck = original then shuffled
for shuffled = (perfect-shuffle deck)
until (equal shuffled original)
finally (format t "~5D: ~4D~%" deck-size trials)))
(solve 8)
(solve 24)
(solve 52)
(solve 100)
(solve 1020)
(solve 1024)
(solve 10000)

View file

@ -0,0 +1,31 @@
import std.stdio;
void main() {
auto sizes = [8, 24, 52, 100, 1020, 1024, 10_000];
foreach(s; sizes) {
writefln("%5s : %5s", s, perfectShuffle(s));
}
}
int perfectShuffle(int size) {
import std.exception : enforce;
enforce(size%2==0);
import std.algorithm : copy, equal;
import std.range;
int[] orig = iota(0, size).array;
int[] process;
process.length = size;
copy(orig, process);
for(int count=1; true; count++) {
process = roundRobin(process[0..$/2], process[$/2..$]).array;
if (equal(orig, process)) {
return count;
}
}
assert(false, "How did this get here?");
}

View file

@ -0,0 +1,100 @@
program Perfect_shuffle;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
TDeck = record
Cards: TArray<Integer>;
Len: Integer;
constructor Create(deckSize: Integer); overload;
constructor Create(deck: TDeck); overload;
procedure shuffleDeck();
class operator Equal(a, b: TDeck): boolean;
function ShufflesRequired: Integer;
procedure Assign(a: TDeck);
end;
{ TDeck }
procedure TDeck.Assign(a: TDeck);
begin
Len := a.Len;
Cards := copy(a.Cards, 0, len);
end;
constructor TDeck.Create(deckSize: Integer);
begin
if deckSize < 1 then
raise Exception.Create('Error: Deck size must have above zero');
if Odd(deckSize) then
raise Exception.Create('Error: Deck size must be even');
SetLength(Cards, deckSize);
Len := deckSize;
for var i := 0 to High(Cards) do
Cards[i] := i;
end;
constructor TDeck.Create(deck: TDeck);
begin
Assign(deck);
end;
class operator TDeck.Equal(a, b: TDeck): boolean;
begin
if a.len <> b.len then
raise Exception.Create('Error: Decks aren''t equally sized');
if a.Len = 0 then
exit(True);
for var i := 0 to a.Len - 1 do
if a.Cards[i] <> b.Cards[i] then
exit(False);
Result := True;
end;
procedure TDeck.shuffleDeck;
var
tmp: TArray<Integer>;
begin
SetLength(tmp, len);
for var i := 0 to len div 2 - 1 do
begin
tmp[i * 2] := Cards[i];
tmp[i * 2 + 1] := Cards[len div 2 + i];
end;
Cards := copy(tmp, 0, len);
end;
function TDeck.ShufflesRequired: Integer;
var
ref: TDeck;
begin
Result := 1;
ref := TDeck.Create(self);
shuffleDeck;
while not (self = ref) do
begin
shuffleDeck;
inc(Result);
end;
end;
const
cases: TArray<Integer> = [8, 24, 52, 100, 1020, 1024, 10000];
begin
for var size in cases do
begin
var deck := TDeck.Create(size);
writeln(format('Cards count: %d, shuffles required: %d', [size, deck.ShufflesRequired]));
end;
readln;
end.

View file

@ -0,0 +1,46 @@
func shuffle(arr) {
if arr.Length() % 2 != 0 {
throw @InvalidValue(arr.Length())
}
var half = arr.Length() / 2
var result = Array.Empty(arr.Length())
var (t, l, r) = (0, 0, half)
while l < half {
result[t] = arr[l]
result[t+1] = arr[r]
l += 1
r += 1
t += 2
}
result
}
func arrayEqual(xs, ys) {
if xs.Length() != ys.Length() {
return false
}
for i in xs.Indices() {
if xs[i] != ys[i] {
return false
}
}
return true
}
func shuffleThrough(original) {
var copy = original.Clone()
while true {
copy = shuffle(copy)
yield copy
if arrayEqual(original, copy) {
break
}
}
}
for input in yields { 8, 24, 52, 100, 1020, 1024, 10000} {
var numbers = [1..input]
print("\(input) cards: \(shuffleThrough(numbers).Length())")
}

View file

@ -0,0 +1,19 @@
;; shuffler : a permutation vector which interleaves both halves of deck
(define (make-shuffler n)
(let ((s (make-vector n)))
(for ((i (in-range 0 n 2))) (vector-set! s i (/ i 2)))
(for ((i (in-range 0 n 2))) (vector-set! s (1+ i) (+ (/ n 2) (vector-ref s i))))
s))
;; output : (n . # of shuffles needed to go back)
(define (magic-shuffle n)
(when (odd? n) (error "magic-shuffle:odd input" n))
(let [(deck (list->vector (iota n))) ;; (0 1 ... n-1)
(dock (list->vector (iota n))) ;; keep trace or init deck
(shuffler (make-shuffler n))]
(cons n (1+
(for/sum ((i Infinity)) ; (in-naturals missing in EchoLisp v2.9)
(vector-permute! deck shuffler) ;; permutes in place
#:break (eqv? deck dock) ;; compare to first
1)))))

View file

@ -0,0 +1,12 @@
map magic-shuffle '(8 24 52 100 1020 1024 10000))
→ ((8 . 3) (24 . 11) (52 . 8) (100 . 30) (1020 . 1018) (1024 . 10) (10000 . 300))
;; Let's look in the On-line Encyclopedia of Integer Sequences
;; Given a list of numbers, the (oeis ...) function looks for a sequence
(lib 'web)
Lib: web.lib loaded.
map magic-shuffle (range 2 18 2))
→ ((2 . 1) (4 . 2) (6 . 4) (8 . 3) (10 . 6) (12 . 10) (14 . 12) (16 . 4))
(oeis '(1 2 4 3 6 10 12 4))
→ Sequence A002326 found

View file

@ -0,0 +1,24 @@
defmodule Perfect do
def shuffle(n) do
start = Enum.to_list(1..n)
m = div(n, 2)
shuffle(start, magic_shuffle(start, m), m, 1)
end
defp shuffle(start, start, _, step), do: step
defp shuffle(start, deck, m, step) do
shuffle(start, magic_shuffle(deck, m), m, step+1)
end
defp magic_shuffle(deck, len) do
{left, right} = Enum.split(deck, len)
Enum.zip(left, right)
|> Enum.map(&Tuple.to_list/1)
|> List.flatten
end
end
Enum.each([8, 24, 52, 100, 1020, 1024, 10000], fn n ->
step = Perfect.shuffle(n)
IO.puts "#{n} : #{step}"
end)

View file

@ -0,0 +1,15 @@
let perfectShuffle xs =
let h = (List.length xs) / 2
xs
|> List.mapi (fun i x->(if i<h then i * 2 else ((i-h) * 2) + 1), x)
|> List.sortBy fst
|> List.map snd
let orderCount n =
let xs = [1..n]
let rec spin count ys =
if xs=ys then count
else ys |> perfectShuffle |> spin (count + 1)
xs |> perfectShuffle |> spin 1
[ 8; 24; 52; 100; 1020; 1024; 10000 ] |> List.iter (fun n->n |> orderCount |> printfn "%d %d" n)

View file

@ -0,0 +1,14 @@
USING: arrays formatting kernel math prettyprint sequences
sequences.merged ;
IN: rosetta-code.perfect-shuffle
CONSTANT: test-cases { 8 24 52 100 1020 1024 10000 }
: shuffle ( seq -- seq' ) halves 2merge ;
: shuffle-count ( n -- m )
<iota> >array 0 swap dup [ 2dup = ] [ shuffle [ 1 + ] 2dip ]
do until 2drop ;
"Deck size" "Number of shuffles required" "%-11s %-11s\n" printf
test-cases [ dup shuffle-count "%-11d %-11d\n" printf ] each

View file

@ -0,0 +1,83 @@
MODULE PERFECT_SHUFFLE
IMPLICIT NONE
CONTAINS
! Shuffle the deck/array of integers
FUNCTION SHUFFLE(NUM_ARR)
INTEGER, DIMENSION(:), INTENT(IN) :: NUM_ARR
INTEGER, DIMENSION(SIZE(NUM_ARR)) :: SHUFFLE
INTEGER :: I, IDX
IF (MOD(SIZE(NUM_ARR), 2) .NE. 0) THEN
WRITE(*,*) "ERROR: SIZE OF DECK MUST BE EVEN NUMBER"
CALL EXIT(1)
END IF
IDX = 1
DO I=1, SIZE(NUM_ARR)/2
SHUFFLE(IDX) = NUM_ARR(I)
SHUFFLE(IDX+1) = NUM_ARR(SIZE(NUM_ARR)/2+I)
IDX = IDX + 2
END DO
END FUNCTION SHUFFLE
! Compare two arrays element by element
FUNCTION COMPARE_ARRAYS(ARRAY_1, ARRAY_2)
INTEGER, DIMENSION(:) :: ARRAY_1, ARRAY_2
LOGICAL :: COMPARE_ARRAYS
INTEGER :: I
DO I=1,SIZE(ARRAY_1)
IF (ARRAY_1(I) .NE. ARRAY_2(I)) THEN
COMPARE_ARRAYS = .FALSE.
RETURN
END IF
END DO
COMPARE_ARRAYS = .TRUE.
END FUNCTION COMPARE_ARRAYS
! Generate a deck/array of consecutive integers
FUNCTION GEN_DECK(DECK_SIZE)
INTEGER, INTENT(IN) :: DECK_SIZE
INTEGER, DIMENSION(DECK_SIZE) :: GEN_DECK
INTEGER :: I
GEN_DECK = (/(I, I=1,DECK_SIZE)/)
END FUNCTION GEN_DECK
END MODULE PERFECT_SHUFFLE
! Program to demonstrate the perfect shuffle algorithm
! for various deck sizes
PROGRAM DEMO_PERFECT_SHUFFLE
USE PERFECT_SHUFFLE
IMPLICIT NONE
INTEGER, PARAMETER, DIMENSION(7) :: DECK_SIZES = (/8, 24, 52, 100, 1020, 1024, 10000/)
INTEGER, DIMENSION(:), ALLOCATABLE :: DECK, SHUFFLED
INTEGER :: I, COUNTER
WRITE(*,'(A, A, A)') "input (deck size)", " | ", "output (number of shuffles required)"
WRITE(*,*) REPEAT("-", 55)
DO I=1, SIZE(DECK_SIZES)
IF (I .GT. 1) THEN
DEALLOCATE(DECK)
DEALLOCATE(SHUFFLED)
END IF
ALLOCATE(DECK(DECK_SIZES(I)))
ALLOCATE(SHUFFLED(DECK_SIZES(I)))
DECK = GEN_DECK(DECK_SIZES(I))
SHUFFLED = SHUFFLE(DECK)
COUNTER = 1
DO WHILE (.NOT. COMPARE_ARRAYS(DECK, SHUFFLED))
SHUFFLED = SHUFFLE(SHUFFLED)
COUNTER = COUNTER + 1
END DO
WRITE(*,'(I17, A, I35)') DECK_SIZES(I), " | ", COUNTER
END DO
END PROGRAM DEMO_PERFECT_SHUFFLE

View file

@ -0,0 +1,44 @@
function is_in_order( d() as uinteger ) as boolean
'tests if a deck is in order
for i as uinteger = lbound(d) to ubound(d)-1
if d(i) > d(i+1) then return false
next i
return true
end function
sub init_deck( d() as uinteger )
for i as uinteger = 1 to ubound(d)
d(i) = i
next i
return
end sub
sub shuffle( d() as uinteger )
'does a faro shuffle of the deck
dim as integer n = ubound(d), i
dim as integer b( 1 to n )
for i = 1 to n/2
b(2*i-1) = d(i)
b(2*i) = d(n/2+i)
next i
for i = 1 to n
d(i) = b(i)
next i
return
end sub
function shufs_needed( size as integer ) as uinteger
dim as uinteger d(1 to size), s = 0
init_deck(d())
do
shuffle(d())
s+=1
if is_in_order(d()) then exit do
loop
return s
end function
dim as uinteger tests(1 to 7) = {8, 24, 52, 100, 1020, 1024, 10000}, i
for i = 1 to 7
print tests(i);" cards require "; shufs_needed(tests(i)); " shuffles."
next i

View file

@ -0,0 +1,59 @@
package main
import "fmt"
type Deck struct {
Cards []int
length int
}
func NewDeck(deckSize int) (res *Deck){
if deckSize % 2 != 0{
panic("Deck size must be even")
}
res = new(Deck)
res.Cards = make([]int, deckSize)
res.length = deckSize
for i,_ := range res.Cards{
res.Cards[i] = i
}
return
}
func (d *Deck)shuffleDeck(){
tmp := make([]int,d.length)
for i := 0;i <d.length/2;i++ {
tmp[i*2] = d.Cards[i]
tmp[i*2+1] = d.Cards[d.length / 2 + i]
}
d.Cards = tmp
}
func (d *Deck) isEqualTo(c Deck) (res bool) {
if d.length != c.length {
panic("Decks aren't equally sized")
}
res = true
for i, v := range d.Cards{
if v != c.Cards[i] {
res = false
}
}
return
}
func main(){
for _,v := range []int{8,24,52,100,1020,1024,10000} {
fmt.Printf("Cards count: %d, shuffles required: %d\n",v,ShufflesRequired(v))
}
}
func ShufflesRequired(deckSize int)(res int){
deck := NewDeck(deckSize)
Ref := *deck
deck.shuffleDeck()
res++
for ;!deck.isEqualTo(Ref);deck.shuffleDeck(){
res++
}
return
}

View file

@ -0,0 +1,12 @@
shuffle :: [a] -> [a]
shuffle lst = let (a,b) = splitAt (length lst `div` 2) lst
in foldMap (\(x,y) -> [x,y]) $ zip a b
findCycle :: Eq a => (a -> a) -> a -> [a]
findCycle f x = takeWhile (/= x) $ iterate f (f x)
main = mapM_ report [ 8, 24, 52, 100, 1020, 1024, 10000 ]
where
report n = putStrLn ("deck of " ++ show n ++ " cards: "
++ show (countSuffles n) ++ " shuffles!")
countSuffles n = 1 + length (findCycle shuffle [1..n])

View file

@ -0,0 +1 @@
shuf=: /: $ /:@$ 0 1"_

View file

@ -0,0 +1,2 @@
($ $ 0 1"_) 'abcdef'
0 1 0 1 0 1

View file

@ -0,0 +1,2 @@
/: ($ $ 0 1"_) 'abcdef'
0 2 4 1 3 5

View file

@ -0,0 +1,2 @@
/:/: ($ $ 0 1"_) 'abcdef'
0 3 1 4 2 5

View file

@ -0,0 +1,4 @@
shuf 'abcdef'
adbecf
shuf 'abcdefgh'
aebfcgdh

View file

@ -0,0 +1 @@
shuflen=: [: *./ #@>@C.@shuf@i.

View file

@ -0,0 +1,2 @@
shuflen"0 }.2*i.5000
1 2 4 3 6 10 12 4 8 18 6 11 20 18 28 5 10 12 36 12 20 14 12 23 21 8 52 20 18 ... 4278 816 222 1332 384

View file

@ -0,0 +1,18 @@
('deck size';'required shuffles'),(; shuflen)&> 8 24 52 100 1020 1024 10000
┌─────────┬─────────────────┐
│deck size│required shuffles│
├─────────┼─────────────────┤
│8 │3 │
├─────────┼─────────────────┤
│24 │11 │
├─────────┼─────────────────┤
│52 │8 │
├─────────┼─────────────────┤
│100 │30 │
├─────────┼─────────────────┤
│1020 │1018 │
├─────────┼─────────────────┤
│1024 │10 │
├─────────┼─────────────────┤
│10000 │300 │
└─────────┴─────────────────┘

View file

@ -0,0 +1,33 @@
import java.util.Arrays;
import java.util.stream.IntStream;
public class PerfectShuffle {
public static void main(String[] args) {
int[] sizes = {8, 24, 52, 100, 1020, 1024, 10_000};
for (int size : sizes)
System.out.printf("%5d : %5d%n", size, perfectShuffle(size));
}
static int perfectShuffle(int size) {
if (size % 2 != 0)
throw new IllegalArgumentException("size must be even");
int half = size / 2;
int[] a = IntStream.range(0, size).toArray();
int[] original = a.clone();
int[] aa = new int[size];
for (int count = 1; true; count++) {
System.arraycopy(a, 0, aa, 0, size);
for (int i = 0; i < half; i++) {
a[2 * i] = aa[i];
a[2 * i + 1] = aa[i + half];
}
if (Arrays.equals(a, original))
return count;
}
}
}

View file

@ -0,0 +1,122 @@
(() => {
'use strict';
// shuffleCycleLength :: Int -> Int
const shuffleCycleLength = deckSize =>
firstCycle(shuffle, range(1, deckSize))
.all.length;
// shuffle :: [a] -> [a]
const shuffle = xs =>
concat(zip.apply(null, splitAt(div(length(xs), 2), xs)));
// firstycle :: Eq a => (a -> a) -> a -> [a]
const firstCycle = (f, x) =>
until(
m => EqArray(x, m.current),
m => {
const fx = f(m.current);
return {
current: fx,
all: m.all.concat([fx])
};
}, {
current: f(x),
all: [x]
}
);
// Two arrays equal ?
// EqArray :: [a] -> [b] -> Bool
const EqArray = (xs, ys) => {
const [nx, ny] = [xs.length, ys.length];
return nx === ny ? (
nx > 0 ? (
xs[0] === ys[0] && EqArray(xs.slice(1), ys.slice(1))
) : true
) : false;
};
// GENERIC FUNCTIONS
// zip :: [a] -> [b] -> [(a,b)]
const zip = (xs, ys) =>
xs.slice(0, Math.min(xs.length, ys.length))
.map((x, i) => [x, ys[i]]);
// concat :: [[a]] -> [a]
const concat = xs => [].concat.apply([], xs);
// splitAt :: Int -> [a] -> ([a],[a])
const splitAt = (n, xs) => [xs.slice(0, n), xs.slice(n)];
// div :: Num -> Num -> Int
const div = (x, y) => Math.floor(x / y);
// until :: (a -> Bool) -> (a -> a) -> a -> a
const until = (p, f, x) => {
const go = x => p(x) ? x : go(f(x));
return go(x);
}
// range :: Int -> Int -> [Int]
const range = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
// length :: [a] -> Int
// length :: Text -> Int
const length = xs => xs.length;
// maximumBy :: (a -> a -> Ordering) -> [a] -> a
const maximumBy = (f, xs) =>
xs.reduce((a, x) => a === undefined ? x : (
f(x, a) > 0 ? x : a
), undefined);
// transpose :: [[a]] -> [[a]]
const transpose = xs =>
xs[0].map((_, iCol) => xs.map((row) => row[iCol]));
// show :: a -> String
const show = x => JSON.stringify(x, null, 2);
// replicateS :: Int -> String -> String
const replicateS = (n, s) => {
let v = s,
o = '';
if (n < 1) return o;
while (n > 1) {
if (n & 1) o = o.concat(v);
n >>= 1;
v = v.concat(v);
}
return o.concat(v);
};
// justifyRight :: Int -> Char -> Text -> Text
const justifyRight = (n, cFiller, strText) =>
n > strText.length ? (
(replicateS(n, cFiller) + strText)
.slice(-n)
) : strText;
// TEST
return transpose(transpose([
['Deck', 'Shuffles']
].concat(
[8, 24, 52, 100, 1020, 1024, 10000]
.map(n => [n.toString(), shuffleCycleLength(n)
.toString()
])))
.map(col => { // Right-justified number columns
const width = length(
maximumBy((a, b) => length(a) - length(b), col)
) + 2;
return col.map(x => justifyRight(width, ' ', x));
}))
.map(row => row.join(''))
.join('\n');
})();

View file

@ -0,0 +1,24 @@
def perfect_shuffle:
. as $a
| if (length % 2) == 1 then "cannot perform perfect shuffle on odd-length array" | error
else (length / 2) as $mid
| reduce range(0; $mid) as $i (null;
.[2*$i] = $a[$i]
| .[2*$i + 1] = $a[$mid+$i] )
end;
# How many iterations of f are required to get back to . ?
def recurrence(f):
def r:
# input: [$init, $current, $count]
(.[1]|f) as $next
| if .[0] == $next then .[-1] + 1
else [.[0], $next, .[-1]+1] | r
end;
[., ., 0] | r;
def count_perfect_shuffles:
[range(0;.)] | recurrence(perfect_shuffle);
(8, 24, 52, 100, 1020, 1024, 10000, 100000)
| [., count_perfect_shuffles]

View file

@ -0,0 +1,28 @@
using Printf
function perfect_shuffle(a::Array)::Array
if isodd(length(a)) error("cannot perform perfect shuffle on odd-length array") end
rst = zeros(a)
mid = div(length(a), 2)
for i in 1:mid
rst[2i-1], rst[2i] = a[i], a[mid+i]
end
return rst
end
function count_perfect_shuffles(decksize::Int)::Int
a = collect(1:decksize)
b, c = perfect_shuffle(a), 1
while a != b
b = perfect_shuffle(b)
c += 1
end
return c
end
println(" Deck n.Shuffles")
for i in (8, 24, 52, 100, 1020, 1024, 10000, 100000)
count = count_perfect_shuffles(i)
@printf("%7i%7i\n", i, count)
end

View file

@ -0,0 +1,41 @@
// version 1.1.2
fun areSame(a: IntArray, b: IntArray): Boolean {
for (i in 0 until a.size) if (a[i] != b[i]) return false
return true
}
fun perfectShuffle(a: IntArray): IntArray {
var b = IntArray(a.size)
val hSize = a.size / 2
for (i in 0 until hSize) b[i * 2] = a[i]
var j = 1
for (i in hSize until a.size) {
b[j] = a[i]
j += 2
}
return b
}
fun countShuffles(a: IntArray): Int {
require(a.size >= 2 && a.size % 2 == 0)
var b = a
var count = 0
while (true) {
val c = perfectShuffle(b)
count++
if (areSame(a, c)) return count
b = c
}
}
fun main(args: Array<String>) {
println("Deck size Num shuffles")
println("--------- ------------")
val sizes = intArrayOf(8, 24, 52, 100, 1020, 1024, 10000)
for (size in sizes) {
val a = IntArray(size) { it }
val count = countShuffles(a)
println("${"%-9d".format(size)} $count")
}
}

View file

@ -0,0 +1,36 @@
-- Perform weave shuffle
function shuffle (cards)
local pile1, pile2 = {}, {}
for card = 1, #cards / 2 do table.insert(pile1, cards[card]) end
for card = (#cards / 2) + 1, #cards do table.insert(pile2, cards[card]) end
cards = {}
for card = 1, #pile1 do
table.insert(cards, pile1[card])
table.insert(cards, pile2[card])
end
return cards
end
-- Return boolean indicating whether or not the cards are in order
function inOrder (cards)
for k, v in pairs(cards) do
if k ~= v then return false end
end
return true
end
-- Count the number of shuffles needed before the cards are in order again
function countShuffles (deckSize)
local deck, count = {}, 0
for i = 1, deckSize do deck[i] = i end
repeat
deck = shuffle(deck)
count = count + 1
until inOrder(deck)
return count
end
-- Main procedure
local testCases = {8, 24, 52, 100, 1020, 1024, 10000}
print("Input", "Output")
for _, case in pairs(testCases) do print(case, countShuffles(case)) end

View file

@ -0,0 +1,9 @@
function [New]=PerfectShuffle(Nitems, Nturns)
if mod(Nitems,2)==0 %only if even number
X=1:Nitems; %define deck
for c=1:Nturns %defines one shuffle
X=reshape(X,Nitems/2,2)'; %split the deck in two and stack halves
X=X(:)'; %mix the halves
end
New=X; %result of multiple shufflings
end

View file

@ -0,0 +1,13 @@
Result=[]; %vector to store results
Q=[8, 24, 52, 100, 1020, 1024, 10000]; %queries
for n=Q %for each query
Same=0; %initialize comparison
T=0; %initialize number of shuffles
while ~Same %while the result is not the original query
T=T+1; %one more shuffle
R=PerfectShuffle(n,T); %result of shuffling the query
Same=~(any(R-(1:n))); %same vector as the query
end %when getting the same vector
Result=[Result;T]; %collect results
end
disp([Q', Result])

View file

@ -0,0 +1,3 @@
shuffle[deck_] := Apply[Riffle, TakeDrop[deck, Length[deck]/2]];
shuffleCount[n_] := Block[{count=0}, NestWhile[shuffle, shuffle[Range[n]], (count++; OrderedQ[#] )&];count];
Map[shuffleCount, {8, 24, 52, 100, 1020, 1024, 10000}]

View file

@ -0,0 +1,91 @@
MODULE PerfectShuffle;
FROM FormatString IMPORT FormatString;
FROM Storage IMPORT ALLOCATE,DEALLOCATE;
FROM SYSTEM IMPORT ADDRESS,TSIZE;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
PROCEDURE WriteCard(c : CARDINAL);
VAR buf : ARRAY[0..15] OF CHAR;
BEGIN
FormatString("%c", buf, c);
WriteString(buf)
END WriteCard;
PROCEDURE Init(VAR arr : ARRAY OF INTEGER);
VAR i : CARDINAL;
BEGIN
FOR i:=0 TO HIGH(arr) DO
arr[i] := i + 1
END
END Init;
PROCEDURE PerfectShuffle(VAR arr : ARRAY OF INTEGER);
PROCEDURE Inner(ti : CARDINAL);
VAR
tv : INTEGER;
tp,tn,n : CARDINAL;
BEGIN
n := HIGH(arr);
tn := ti;
tv := arr[ti];
REPEAT
tp := tn;
IF tp MOD 2 = 0 THEN
tn := tp / 2
ELSE
tn := (n+1)/2+tp/2
END;
arr[tp] := arr[tn];
UNTIL tn = ti;
arr[tp] := tv
END Inner;
VAR
done : BOOLEAN;
i,c : CARDINAL;
BEGIN
c := 0;
Init(arr);
REPEAT
i := 1;
WHILE i <= (HIGH(arr)/2) DO
Inner(i);
INC(i,2)
END;
INC(c);
done := TRUE;
FOR i:=0 TO HIGH(arr) DO
IF arr[i] # INT(i+1) THEN
done := FALSE;
BREAK
END
END
UNTIL done;
WriteCard(HIGH(arr)+1);
WriteString(": ");
WriteCard(c);
WriteLn
END PerfectShuffle;
(* Main *)
VAR
v8 : ARRAY[1..8] OF INTEGER;
v24 : ARRAY[1..24] OF INTEGER;
v52 : ARRAY[1..52] OF INTEGER;
v100 : ARRAY[1..100] OF INTEGER;
v1020 : ARRAY[1..1020] OF INTEGER;
v1024 : ARRAY[1..1024] OF INTEGER;
v10000 : ARRAY[1..10000] OF INTEGER;
BEGIN
PerfectShuffle(v8);
PerfectShuffle(v24);
PerfectShuffle(v52);
PerfectShuffle(v100);
PerfectShuffle(v1020);
PerfectShuffle(v1024);
PerfectShuffle(v10000);
ReadChar
END PerfectShuffle.

View file

@ -0,0 +1,26 @@
import sequtils, strutils
proc newValList(size: Positive): seq[int] =
if (size and 1) != 0:
raise newException(ValueError, "size must be even.")
result = toSeq(1..size)
func shuffled(list: seq[int]): seq[int] =
result.setLen(list.len)
let half = list.len div 2
for i in 0..<half:
result[2 * i] = list[i]
result[2 * i + 1] = list[half + i]
for size in [8, 24, 52, 100, 1020, 1024, 10000]:
let initList = newValList(size)
var valList = initList
var count = 0
while true:
inc count
valList = shuffled(valList)
if valList == initList:
break
echo ($size).align(5), ": ", ($count).align(4)

View file

@ -0,0 +1,2 @@
: shuffle(l) l size 2 / dup l left swap l right zip expand ;
: nbShuffles(l) 1 l while( shuffle dup l <> ) [ 1 under+ ] drop ;

View file

@ -0,0 +1,4 @@
magic(v)=vector(#v,i,v[if(i%2,1,#v/2)+i\2]);
shuffles_slow(n)=my(v=[1..n],o=v,s=1);while((v=magic(v))!=o,s++);s;
shuffles(n)=znorder(Mod(2,n-1));
vector(5000,n,shuffles_slow(2*n))

View file

@ -0,0 +1,15 @@
use v5.36;
use List::Util 'all';
sub perfect_shuffle (@deck) {
my $middle = @deck / 2;
map { @deck[$_, $_ + $middle] } 0..$middle-1;
}
for my $size (8, 24, 52, 100, 1020, 1024, 10000) {
my @shuffled = my @deck = 1..$size;
my $n;
do { $n++; @shuffled = perfect_shuffle @shuffled }
until all { $shuffled[$_] == $deck[$_] } 0..$#shuffled;
printf "%5d cards: %4d\n", $size, $n;
}

View file

@ -0,0 +1,24 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">perfect_shuffle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">mp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">mp</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">mp</span><span style="color: #0000FF;">]</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">testsizes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">24</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">52</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1020</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1024</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10000</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">testsizes</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">testsizes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">work</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">perfect_shuffle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">deck</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">work</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">deck</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">work</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">perfect_shuffle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">work</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%5d cards: %4d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">testsizes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">count</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--

View file

@ -0,0 +1,83 @@
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.

View file

@ -0,0 +1,7 @@
main =>
N = 8,
println(1..N),
InOut = in, % in shuffling
Count = show_all_shuffles(N,InOut,true),
println(count=Count),
nl.

View file

@ -0,0 +1,7 @@
main =>
N = 11,
println(1..N),
InOut = out, % in/out shuffling
Count = show_all_shuffles(N,InOut,true),
println(count=Count),
nl.

View file

@ -0,0 +1,10 @@
(de perfectShuffle (Lst)
(mapcan '((B A) (list A B))
(cdr (nth Lst (/ (length Lst) 2)))
Lst ) )
(for N (8 24 52 100 1020 1024 10000)
(let (Lst (range 1 N) L Lst Cnt 1)
(until (= Lst (setq L (perfectShuffle L)))
(inc 'Cnt) )
(tab (5 6) N Cnt) ) )

View file

@ -0,0 +1,44 @@
import doctest
import random
def flatten(lst):
"""
>>> flatten([[3,2],[1,2]])
[3, 2, 1, 2]
"""
return [i for sublst in lst for i in sublst]
def magic_shuffle(deck):
"""
>>> magic_shuffle([1,2,3,4])
[1, 3, 2, 4]
"""
half = len(deck) // 2
return flatten(zip(deck[:half], deck[half:]))
def after_how_many_is_equal(shuffle_type,start,end):
"""
>>> after_how_many_is_equal(magic_shuffle,[1,2,3,4],[1,2,3,4])
2
"""
start = shuffle_type(start)
counter = 1
while start != end:
start = shuffle_type(start)
counter += 1
return counter
def main():
doctest.testmod()
print("Length of the deck of cards | Perfect shuffles needed to obtain the same deck back")
for length in (8, 24, 52, 100, 1020, 1024, 10000):
deck = list(range(length))
shuffles_needed = after_how_many_is_equal(magic_shuffle,deck,deck)
print("{} | {}".format(length,shuffles_needed))
if __name__ == "__main__":
main()

View file

@ -0,0 +1,66 @@
"""
Brute force solution for the Perfect Shuffle problem.
See http://oeis.org/A002326 for possible improvements
"""
from functools import partial
from itertools import chain
from operator import eq
from typing import (Callable,
Iterable,
Iterator,
List,
TypeVar)
T = TypeVar('T')
def main():
print("Deck length | Shuffles ")
for length in (8, 24, 52, 100, 1020, 1024, 10000):
deck = list(range(length))
shuffles_needed = spin_number(deck, shuffle)
print(f"{length:<11} | {shuffles_needed}")
def shuffle(deck: List[T]) -> List[T]:
"""[1, 2, 3, 4] -> [1, 3, 2, 4]"""
half = len(deck) // 2
return list(chain.from_iterable(zip(deck[:half], deck[half:])))
def spin_number(source: T,
function: Callable[[T], T]) -> int:
"""
Applies given function to the source
until the result becomes equal to it,
returns the number of calls
"""
is_equal_source = partial(eq, source)
spins = repeat_call(function, source)
return next_index(is_equal_source,
spins,
start=1)
def repeat_call(function: Callable[[T], T],
value: T) -> Iterator[T]:
"""(f, x) -> f(x), f(f(x)), f(f(f(x))), ..."""
while True:
value = function(value)
yield value
def next_index(predicate: Callable[[T], bool],
iterable: Iterable[T],
start: int = 0) -> int:
"""
Returns index of the first element of the iterable
satisfying given condition
"""
for index, item in enumerate(iterable, start=start):
if predicate(item):
return index
if __name__ == "__main__":
main()

View file

@ -0,0 +1,25 @@
def mul_ord2(n):
# directly calculate how many shuffles are needed to restore
# initial order: 2^o mod(n-1) == 1
if n == 2: return 1
n,t,o = n-1,2,1
while t != 1:
t,o = (t*2)%n,o+1
return o
def shuffles(n):
a,c = list(range(n)), 0
b = a
while True:
# Reverse shuffle; a[i] can be taken as the current
# position of the card with value i. This is faster.
a = a[0:n:2] + a[1:n:2]
c += 1
if b == a: break
return c
for n in range(2, 10000, 2):
#print(n, mul_ord2(n))
print(n, shuffles(n))

View file

@ -0,0 +1,20 @@
[ [] swap
times [ i^ join ] ] is deck ( n --> [ )
[ dup size 2 / split swap
witheach
[ swap i^ 2 * stuff ] ] is weave ( [ --> [ )
[ 0 swap
deck dup
[ rot 1+ unrot
weave 2dup = until ]
2drop ] is shuffles ( n --> n )
' [ 8 24 52 100 1020 1024 10000 ]
witheach
[ say "A deck of "
dup echo say " cards needs "
shuffles echo say " shuffles."
cr ]

View file

@ -0,0 +1,16 @@
wave.shuffle <- function(n) {
deck <- 1:n ## create the original deck
new.deck <- c(matrix(data = deck, ncol = 2, byrow = TRUE)) ## shuffle the deck once
counter <- 1 ## track the number of loops
## defining a loop that shuffles the new deck until identical with the original one
## and in the same time increses the counter with 1 per loop
while (!identical(deck, new.deck)) { ## logical condition
new.deck <- c(matrix(data = new.deck, ncol = 2, byrow = TRUE)) ## shuffle
counter <- counter + 1 ## add 1 to the number of loops
}
return(counter) ## final result - total number of loops until the condition is met
}
test.values <- c(8, 24, 52, 100, 1020, 1024, 10000) ## the set of the test values
test <- sapply(test.values, wave.shuffle) ## apply the wave.shuffle function on each element
names(test) <- test.values ## name the result
test ## print the result out

View file

@ -0,0 +1,26 @@
#A strict reading of the task description says that we need a function that does exactly one shuffle.
pShuffle <- function(deck)
{
n <- length(deck)#Assumed even (as in task description).
shuffled <- array(n)#Maybe not as general as it could be, but the task said to use whatever was convenient.
shuffled[seq(from = 1, to = n, by = 2)] <- deck[seq(from = 1, to = n/2, by = 1)]
shuffled[seq(from = 2, to = n, by = 2)] <- deck[seq(from = 1 + n/2, to = n, by = 1)]
shuffled
}
task2 <- function(deck)
{
shuffled <- deck
count <- 0
repeat
{
shuffled <- pShuffle(shuffled)
count <- count + 1
if(all(shuffled == deck)) break
}
cat("It takes", count, "shuffles of a deck of size", length(deck), "to return to the original deck.","\n")
invisible(count)#For the unit tests. The task wanted this printed so we only return it invisibly.
}
#Tests - All done in one line.
mapply(function(x, y) task2(1:x) == y, c(8, 24, 52, 100, 1020, 1024, 10000), c(3, 11, 8, 30, 1018, 10, 300))

View file

@ -0,0 +1,25 @@
/*REXX program performs a "perfect shuffle" for a number of even numbered decks. */
parse arg X /*optional list of test cases from C.L.*/
if X='' then X=8 24 52 100 1020 1024 10000 /*Not specified? Then use the default.*/
w=length(word(X, words(X))) /*used for right─aligning the numbers. */
do j=1 for words(X); y=word(X,j) /*use numbers in the test suite (list).*/
do k=1 for y; @.k=k; end /*k*/ /*generate a deck to be used (shuffled)*/
do t=1 until eq(); call magic; end /*t*/ /*shuffle until before equals after.*/
say 'deck size:' right(y,w)"," right(t,w) 'perfect shuffles.'
end /*j*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
eq: do ?=1 for y; if @.?\==? then return 0; end; return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
magic: z=0 /*set the Z pointer (used as index).*/
h=y%2 /*get the half─way (midpoint) pointer. */
do s=1 for h; z=z+1; h=h+1 /*traipse through the card deck pips. */
!.z=@.s; z=z+1 /*assign left half; then bump pointer. */
!.z=@.h /* " right " */
end /*s*/ /*perform a perfect shuffle of the deck*/
do r=1 for y; @.r=!.r; end /*re─assign to the original card deck. */
return

View file

@ -0,0 +1,21 @@
/*REXX program does a "perfect shuffle" for a number of even numbered decks. */
parse arg X /*optional list of test cases from C.L.*/
if X='' then X=8 24 52 100 1020 1024 10000 /*Not specified? Use default.*/
w=length(word(X, words(X))) /*used for right─aligning the numbers. */
do j=1 for words(X); y=word(X,j) /*use numbers in the test suite (list).*/
do k=1 for y; @.k=k; end /*generate a deck to be shuffled (used)*/
do t=1 until eq(); call magic; end /*shuffle until before equals after.*/
say 'deck size:' right(y,w)"," right(t,w) 'perfect shuffles.'
end /*j*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
eq: do ?=1 for y; if @.?\==? then return 0; end; return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
magic: z=1; h=y%2 /*H is (half─way) pointer.*/
do L=3 by 2 for h-1; z=z+1; !.L=@.z; end /*assign left half of deck.*/
do R=2 by 2 for h-1; h=h+1; !.R=@.h; end /* " right " " " */
do a=2 for y-2; @.a=!.a; end /*re─assign──►original deck*/
return

View file

@ -0,0 +1,27 @@
#lang racket/base
(require racket/list)
(define (perfect-shuffle l)
(define-values (as bs) (split-at l (/ (length l) 2)))
(foldr (λ (a b d) (list* a b d)) null as bs))
(define (perfect-shuffles-needed n)
(define-values (_ rv)
(for/fold ((d (perfect-shuffle (range n))) (i 1))
((_ (in-naturals))
#:break (apply < d))
(values (perfect-shuffle d) (add1 i))))
rv)
(module+ test
(require rackunit)
(check-equal? (perfect-shuffle '(1 2 3 4)) '(1 3 2 4))
(define (test-perfect-shuffles-needed n e)
(define psn (perfect-shuffles-needed n))
(printf "Deck size:\t~a\tShuffles needed:\t~a\t(~a)~%" n psn e)
(check-equal? psn e))
(for-each test-perfect-shuffles-needed
'(8 24 52 100 1020 1024 10000)
'(3 11 8 30 1018 10 300)))

View file

@ -0,0 +1,5 @@
for 8, 24, 52, 100, 1020, 1024, 10000 -> $size {
my ($n, @deck) = 1, |^$size;
$n++ until [<] @deck = flat [Z] @deck.rotor: @deck/2;
printf "%5d cards: %4d\n", $size, $n;
}

View file

@ -0,0 +1,11 @@
def perfect_shuffle(deck_size = 52)
deck = (1..deck_size).to_a
original = deck.dup
half = deck_size / 2
1.step do |i|
deck = deck.first(half).zip(deck.last(half)).flatten
return i if deck == original
end
end
[8, 24, 52, 100, 1020, 1024, 10000].each {|i| puts "Perfect shuffles required for deck size #{i}: #{perfect_shuffle(i)}"}

View file

@ -0,0 +1,23 @@
extern crate itertools;
fn shuffle<T>(mut deck: Vec<T>) -> Vec<T> {
let index = deck.len() / 2;
let right_half = deck.split_off(index);
itertools::interleave(deck, right_half).collect()
}
fn main() {
for &size in &[8, 24, 52, 100, 1020, 1024, 10_000] {
let original_deck: Vec<_> = (0..size).collect();
let mut deck = original_deck.clone();
let mut iterations = 0;
loop {
deck = shuffle(deck);
iterations += 1;
if deck == original_deck {
break;
}
}
println!("{: >5}: {: >4}", size, iterations);
}
}

View file

@ -0,0 +1,24 @@
object PerfectShuffle extends App {
private def sizes = Seq(8, 24, 52, 100, 1020, 1024, 10000)
private def perfectShuffle(size: Int): Int = {
require(size % 2 == 0, "Card deck must be even")
val (half, a) = (size / 2, Array.range(0, size))
val original = a.clone
var count = 1
while (true) {
val aa = a.clone
for (i <- 0 until half) {
a(2 * i) = aa(i)
a(2 * i + 1) = aa(i + half)
}
if (a.deep == original.deep) return count
count += 1
}
0
}
for (size <- sizes) println(f"$size%5d : ${perfectShuffle(size)}%5d")
}

View file

@ -0,0 +1,28 @@
function New=PerfectShuffle(Nitems,Nturns)
if modulo(Nitems,2)==0 then
X=1:Nitems;
for c=1:Nturns
X=matrix(X,Nitems/2,2)';
X=X(:);
end
New=X';
end
endfunction
Result=[];
Q=[8, 24, 52, 100, 1020, 1024, 10000];
for n=Q
Same=0;
T=0;
Compare=[];
while ~Same
T=T+1;
R=PerfectShuffle(n,T);
Compare = find(R-(1:n));
if Compare == [] then
Same = 1;
end
end
Result=[Result;T];
end
disp([Q', Result])

View file

@ -0,0 +1,14 @@
func perfect_shuffle(deck) {
deck/2 -> zip.flat
}
[8, 24, 52, 100, 1020, 1024, 10000].each { |size|
var deck = @(1..size)
var shuffled = deck
var n = (1..Inf -> lazy.first {
(shuffled = perfect_shuffle(shuffled)) == deck
})
printf("%5d cards: %4d\n", size, n)
}

View file

@ -0,0 +1,37 @@
func perfectShuffle<T>(_ arr: [T]) -> [T]? {
guard arr.count & 1 == 0 else {
return nil
}
let half = arr.count / 2
var res = [T]()
for i in 0..<half {
res.append(arr[i])
res.append(arr[i + half])
}
return res
}
let decks = [
Array(1...8),
Array(1...24),
Array(1...52),
Array(1...100),
Array(1...1020),
Array(1...1024),
Array(1...10000)
]
for deck in decks {
var shuffled = deck
var shuffles = 0
repeat {
shuffled = perfectShuffle(shuffled)!
shuffles += 1
} while shuffled != deck
print("Deck of \(shuffled.count) took \(shuffles) shuffles to get back to original order")
}

View file

@ -0,0 +1,46 @@
namespace eval shuffle {
proc perfect {deck} {
if {[llength $deck]%2} {
return -code error "Deck must be of even length!"
}
set split [expr {[llength $deck]/2}]
set top [lrange $deck 0 $split-1]
set btm [lrange $deck $split end]
foreach a $top b $btm {
lappend res $a $b
}
return $res
}
proc cycle_length {transform deck} {
set d $deck
while 1 {
set d [$transform $d]
incr i
if {$d eq $deck} {return $i}
}
return $i
}
proc range {a {b ""}} {
if {$b eq ""} {
set b $a; set a 0
}
set res {}
while {$a < $b} {
lappend res $a
incr a
}
return $res
}
}
set ::argv {}
package require tcltest
tcltest::test "Test perfect shuffle cycles" {} -body {
lmap size {8 24 52 100 1020 1024 10000} {
shuffle::cycle_length perfect [range $size]
}
} -result {3 11 8 30 1018 10 300}

View file

@ -0,0 +1,33 @@
function faro {
if (( $# % 2 )); then
printf >&2 'Can only shuffle an even number of elements!\n'
return 1
fi
typeset -i half=$(($#/2)) i
typeset argv=("$@")
for (( i=0; i<half; ++i )); do
printf '%s\n%s\n' "${argv[i${ZSH_VERSION:++1}]}" "${argv[i+half${ZSH_VERSION:++1}]}"
done
}
function count_faros {
typeset argv=("$@")
typeset -i count=0
argv=($(faro "${argv[@]}"))
(( count += 1 ))
while [[ "${argv[*]}" != "$*" ]]; do
argv=($(faro "${argv[@]}"))
(( count += 1 ))
done
printf '%d\n' "$count"
}
# Include time taken, which is combined from the three shells in the output below
printf '%s\t%s\t%s\n' Size Shuffles Seconds
for size in 8 24 52 100 1020 1024 10000; do
eval "array=({1..$size})"
start=$(date +%s)
count=$(count_faros "${array[@]}")
taken=$(( $(date +%s) - start ))
printf '%d\t%d\t%d\n' "$size" "$count" "$taken"
done

View file

@ -0,0 +1,62 @@
Option Explicit
Sub Main()
Dim T, Arr, X As Long, C As Long
Arr = Array(8, 24, 52, 100, 1020, 1024, 10000)
For X = LBound(Arr) To UBound(Arr)
C = 0
Call PerfectShuffle(T, CLng(Arr(X)), C)
Debug.Print Right(String(19, " ") & "For " & Arr(X) & " cards => ", 19) & C & " shuffles needed."
Erase T
Next
End Sub
Private Sub PerfectShuffle(tb, NbCards As Long, Count As Long)
Dim arr1, arr2, StrInit As String, StrTest As String
tb = CreateArray(1, NbCards)
StrInit = Join(tb, " ")
Do
Count = Count + 1
Call DivideArr(tb, arr1, arr2)
tb = RemakeArray(arr1, arr2)
StrTest = Join(tb, " ")
Loop While StrTest <> StrInit
End Sub
Private Function CreateArray(First As Long, Length As Long) As String()
Dim i As Long, T() As String, C As Long
If IsEven(Length) Then
ReDim T(Length - 1)
For i = First To First + Length - 1
T(C) = i
C = C + 1
Next i
CreateArray = T
End If
End Function
Private Sub DivideArr(A, B, C)
Dim i As Long
B = A
ReDim Preserve B(UBound(A) \ 2)
ReDim C(UBound(B))
For i = LBound(C) To UBound(C)
C(i) = A(i + UBound(B) + 1)
Next
End Sub
Private Function RemakeArray(A1, A2) As String()
Dim i As Long, T() As String, C As Long
ReDim T((UBound(A2) * 2) + 1)
For i = LBound(T) To UBound(T) - 1 Step 2
T(i) = A1(C)
T(i + 1) = A2(C)
C = C + 1
Next
RemakeArray = T
End Function
Private Function IsEven(Number As Long) As Boolean
IsEven = (Number Mod 2 = 0)
End Function

View file

@ -0,0 +1,42 @@
import "/fmt" for Fmt
var areSame = Fn.new { |a, b|
for (i in 0...a.count) if (a[i] != b[i]) return false
return true
}
var perfectShuffle = Fn.new { |a|
var n = a.count
var b = List.filled(n, 0)
var hSize = (n/2).floor
for (i in 0...hSize) b[i * 2] = a[i]
var j = 1
for (i in hSize...n) {
b[j] = a[i]
j = j + 2
}
return b
}
var countShuffles = Fn.new { |a|
var n = a.count
if (n < 2 || n % 2 == 1) Fiber.abort("Array must be even-sized and non-empty.")
var b = a
var count = 0
while (true) {
var c = perfectShuffle.call(b)
count = count + 1
if (areSame.call(a, c)) return count
b = c
}
}
System.print("Deck size Num shuffles")
System.print("--------- ------------")
var sizes = [8, 24, 52, 100, 1020, 1024, 10000]
for (size in sizes) {
var a = List.filled(size, 0)
for (i in 1...size) a[i] = i
var count = countShuffles.call(a)
Fmt.print("$-9d $d", size, count)
}

View file

@ -0,0 +1,27 @@
int Deck(10000), Deck0(10000);
int Cases, Count, Test, Size, I;
proc Shuffle; \Do perfect shuffle of Deck0 into Deck
int DeckLeft, DeckRight;
int I;
[DeckLeft:= Deck0;
DeckRight:= Deck0 + Size*4/2; \4 bytes per integer
for I:= 0 to Size-1 do
Deck(I):= if I&1 then DeckRight(I/2)
else DeckLeft(I/2);
];
[Cases:= [8, 24, 52, 100, 1020, 1024, 10000];
for Test:= 0 to 7-1 do
[Size:= Cases(Test);
for I:= 0 to Size-1 do Deck(I):= I;
Count:= 0;
repeat for I:= 0 to Size-1 do Deck0(I):= Deck(I);
Shuffle;
Count:= Count+1;
for I:= 0 to Size-1 do
if Deck(I) # I then I:= Size;
until I = Size; \equal starting configuration
IntOut(0, Size); ChOut(0, 9\tab\); IntOut(0, Count); CrLf(0);
];
]

View file

@ -0,0 +1,9 @@
fcn perfectShuffle(numCards){
deck,shuffle,n,N:=numCards.pump(List),deck,0,numCards/2;
do{ shuffle=shuffle[0,N].zip(shuffle[N,*]).flatten(); n+=1 }
while(deck!=shuffle);
n
}
foreach n in (T(8,24,52,100,1020,1024,10000)){
println("%5d : %d".fmt(n,perfectShuffle(n)));
}