Mind boggling card trick: Difference between revisions
(Added Factor) |
|||
Line 21: | Line 21: | ||
Show output on this page. |
Show output on this page. |
||
=={{header|Factor}}== |
|||
<lang factor>USING: accessors combinators.extras formatting fry |
|||
generalizations io kernel math math.ranges random sequences |
|||
sequences.extras ; |
|||
IN: rosetta-code.mind-boggling-card-trick |
|||
SYMBOLS: R B ; |
|||
TUPLE: piles deck red black discard ; |
|||
: initialize-deck ( -- seq ) |
|||
[ R ] [ B ] [ '[ 26 _ V{ } replicate-as ] call ] bi@ append |
|||
randomize ; |
|||
: <piles> ( -- piles ) |
|||
initialize-deck [ V{ } clone ] thrice piles boa ; |
|||
: deal-step ( piles -- piles' ) |
|||
dup [ deck>> pop dup ] [ discard>> push ] [ deck>> pop ] tri |
|||
B = [ over black>> ] [ over red>> ] if push ; |
|||
: deal ( piles -- piles' ) 26 [ deal-step ] times ; |
|||
: choose-sample-size ( piles -- n ) |
|||
[ red>> ] [ black>> ] bi shorter length [0,b] random ; |
|||
! Partition a sequence into n random samples in one sequence and |
|||
! the leftovers in another. |
|||
: sample-partition ( vec n -- leftovers sample ) |
|||
[ 3 dupn ] dip sample dup |
|||
[ [ swap remove-first! drop ] with each ] dip ; |
|||
: perform-swaps ( piles -- piles' ) |
|||
dup dup choose-sample-size dup "Swapping %d\n" printf |
|||
[ [ red>> ] dip ] [ [ black>> ] dip ] 2bi |
|||
[ sample-partition ] 2bi@ [ append ] dip rot append |
|||
[ >>black ] dip >>red ; |
|||
: test-assertion ( piles -- ) |
|||
[ red>> ] [ black>> ] bi |
|||
[ [ R = ] count ] [ [ B = ] count ] bi* 2dup = |
|||
[ "Assertion correct!" ] |
|||
[ "Assertion incorrect!" ] if print |
|||
"R in red: %d\nB in black: %d\n" printf ; |
|||
: main ( -- ) |
|||
<piles> ! step 1 |
|||
deal ! step 2 |
|||
dup "Post-deal state:\n%u\n" printf |
|||
perform-swaps ! step 3 |
|||
dup "Post-swap state:\n%u\n" printf |
|||
test-assertion ; ! step 4</lang> |
|||
A run: |
|||
{{out}} |
|||
<pre> |
|||
Post-deal state: |
|||
T{ piles |
|||
{ deck V{ } } |
|||
{ red V{ B R B R R B B R R R R } } |
|||
{ black V{ R B R B B R B B R R R R R B B } } |
|||
{ discard |
|||
V{ R B R B R B B B R R R B B B R B R R R R R R B R B R } |
|||
} |
|||
} |
|||
Swapping 11 |
|||
Post-swap state: |
|||
T{ piles |
|||
{ deck V{ } } |
|||
{ red V{ B R B B R R B R R R R } } |
|||
{ black V{ B R R B B R B R R R R B R B B } } |
|||
{ discard |
|||
V{ R B R B R B B B R R R B B B R B R R R R R R B R B R } |
|||
} |
|||
} |
|||
Assertion correct! |
|||
R in red: 7 |
|||
B in black: 7 |
|||
</pre> |
|||
Another run: |
|||
{{out}} |
|||
<pre> |
|||
Post-deal state: |
|||
T{ piles |
|||
{ deck V{ } } |
|||
{ red V{ R R R B B R B R R B } } |
|||
{ black V{ B R B B R B R B R R R R R R B R } } |
|||
{ discard |
|||
V{ R R B R B B R B B R B R R B B R R R R R R R B R R B } |
|||
} |
|||
} |
|||
Swapping 7 |
|||
Post-swap state: |
|||
T{ piles |
|||
{ deck V{ } } |
|||
{ red V{ B R R R B R B B R B } } |
|||
{ black V{ R R B R R B R B B R R R R R B R } } |
|||
{ discard |
|||
V{ R R B R B B R B B R B R R B B R R R R R R R B R R B } |
|||
} |
|||
} |
|||
Assertion correct! |
|||
R in red: 5 |
|||
B in black: 5 |
|||
</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
Revision as of 23:20, 25 August 2018
Matt Parker of the Stand Up Maths channel on you tube has a video of a card trick that creates a semblance of order from chaos.
The task is to simulate the trick in a way that mimicks the steps shown in the video.
- 1. Cards
- Create a
pack
of 52 cards, half red - half black. - Give the pack a good shuffle.
- 2. Deal from the randomised pack into three stacks
- Assemble the cards face down.
- Turn up the top card,
- if it is black then add the next card, unseen, to the
black-stack
. - If it is red then instead add that next card, unseen, to the
red-stack
.
- if it is black then add the next card, unseen, to the
- Add the card you turned over to see what colour it was above, to the
discard-stack
.
(You might optionally show these discard cards to give an idea of the randomness).
- Turn up the top card,
- Repeat the above for the whole of the assembled pack.
- 3. Swap the same, random, number of cards between the two stacks.
- Randomly choose the number of cards to swap.
- Randomly choose that number of cards out of each stack to swap.
(Without knowing those cards - they could be red or black cards from the stacks, we don't know).
- 4. Order from randomness?
- Check the mathematicians assertion that: The number of black cards in the black pile equals the number of red cards in the red pile.
Show output on this page.
Factor
<lang factor>USING: accessors combinators.extras formatting fry generalizations io kernel math math.ranges random sequences sequences.extras ; IN: rosetta-code.mind-boggling-card-trick
SYMBOLS: R B ;
TUPLE: piles deck red black discard ;
- initialize-deck ( -- seq )
[ R ] [ B ] [ '[ 26 _ V{ } replicate-as ] call ] bi@ append randomize ;
- <piles> ( -- piles )
initialize-deck [ V{ } clone ] thrice piles boa ;
- deal-step ( piles -- piles' )
dup [ deck>> pop dup ] [ discard>> push ] [ deck>> pop ] tri B = [ over black>> ] [ over red>> ] if push ;
- deal ( piles -- piles' ) 26 [ deal-step ] times ;
- choose-sample-size ( piles -- n )
[ red>> ] [ black>> ] bi shorter length [0,b] random ;
! Partition a sequence into n random samples in one sequence and ! the leftovers in another.
- sample-partition ( vec n -- leftovers sample )
[ 3 dupn ] dip sample dup [ [ swap remove-first! drop ] with each ] dip ;
- perform-swaps ( piles -- piles' )
dup dup choose-sample-size dup "Swapping %d\n" printf [ [ red>> ] dip ] [ [ black>> ] dip ] 2bi [ sample-partition ] 2bi@ [ append ] dip rot append [ >>black ] dip >>red ;
- test-assertion ( piles -- )
[ red>> ] [ black>> ] bi [ [ R = ] count ] [ [ B = ] count ] bi* 2dup = [ "Assertion correct!" ] [ "Assertion incorrect!" ] if print "R in red: %d\nB in black: %d\n" printf ;
- main ( -- )
<piles> ! step 1 deal ! step 2 dup "Post-deal state:\n%u\n" printf perform-swaps ! step 3 dup "Post-swap state:\n%u\n" printf test-assertion ; ! step 4</lang>
A run:
- Output:
Post-deal state: T{ piles { deck V{ } } { red V{ B R B R R B B R R R R } } { black V{ R B R B B R B B R R R R R B B } } { discard V{ R B R B R B B B R R R B B B R B R R R R R R B R B R } } } Swapping 11 Post-swap state: T{ piles { deck V{ } } { red V{ B R B B R R B R R R R } } { black V{ B R R B B R B R R R R B R B B } } { discard V{ R B R B R B B B R R R B B B R B R R R R R R B R B R } } } Assertion correct! R in red: 7 B in black: 7
Another run:
- Output:
Post-deal state: T{ piles { deck V{ } } { red V{ R R R B B R B R R B } } { black V{ B R B B R B R B R R R R R R B R } } { discard V{ R R B R B B R B B R B R R B B R R R R R R R B R R B } } } Swapping 7 Post-swap state: T{ piles { deck V{ } } { red V{ B R R R B R B B R B } } { black V{ R R B R R B R B B R R R R R B R } } { discard V{ R R B R B B R B B R B R R B B R R R R R R R B R R B } } } Assertion correct! R in red: 5 B in black: 5
Python
The code is layed out to follow the task decription, leading to some deviations from the PEP8 guidelines <lang python>import random
- 1. Cards
n = 52 Black, Red = 'Black', 'Red' blacks = [Black] * (n // 2) reds = [Red] * (n // 2) pack = blacks + reds
- Give the pack a good shuffle.
random.shuffle(pack)
- 2. Deal from the randomised pack into three stacks
black_stack, red_stack, discard = [], [], [] while pack:
top = pack.pop() if top == Black: black_stack.append(pack.pop()) else: red_stack.append(pack.pop()) discard.append(top)
print('(Discards:', ' '.join(d[0] for d in discard), ')\n')
- 3. Swap the same, random, number of cards between the two stacks.
- We can't swap more than the number of cards in a stack.
max_swaps = min(len(black_stack), len(red_stack))
- Randomly choose the number of cards to swap.
swap_count = random.randint(0, max_swaps) print('Swapping', swap_count)
- Randomly choose that number of cards out of each stack to swap.
def random_partition(stack, count):
"Partition the stack into 'count' randomly selected members and the rest" sample = random.sample(stack, count) rest = stack[::] for card in sample: rest.remove(card) return rest, sample
black_stack, black_swap = random_partition(black_stack, swap_count) red_stack, red_swap = random_partition(red_stack, swap_count)
- Perform the swap.
black_stack += red_swap red_stack += black_swap
- 4. Order from randomness?
if black_stack.count(Black) == red_stack.count(Red):
print('Yeha! The mathematicians assertion is correct.')
else:
print('Whoops - The mathematicians (or my card manipulations) are flakey')</lang>
A run.
- Output:
(Discards: R B R R B B R R R B B B B R R R B R R B B B B R B R ) Swapping 11 Yeha! The mathematicians assertion is correct.
A second run:
- Output:
(Discards: R B B R B B R B R R R B R R B B B B R R B R R B B R ) Swapping 2 Yeha! The mathematicians assertion is correct.
zkl
<lang zkl>cards:=[1..52].pump(List,"isEven","toInt").shuffle(); // red==1 stacks:=T(List(),List()); // black stack (0), red stack (1) blkStk,redStk := stacks; foreach card in (cards){ stacks[card].append(__cardWalker.next()) } println("Stacks:\n Black stack: ",blkStk,"\n Red stack: ",redStk);
numSwaps:=(1).random(1000); // do lots of swaps do(numSwaps){ blkStk.append(redStk.pop(0)); redStk.append(blkStk.pop(0)); } println("Post %d swaps:\n Black stack: %s\n Red stack: %s"
.fmt(numSwaps,blkStk,redStk));
numBlack,numRed := blkStk.filter('==(0)).len(), redStk.filter().len(); if(numBlack==numRed)
println("Agreed, black stack has same number of black cards \n " "as red stack has number of red cards: ",numRed);
else println("Boo, differnt stack lenghts");</lang>
- Output:
Stacks: Black stack: L(0,0,1,1,0,0,1,0,0,0,0) Red stack: L(0,1,0,1,0,1,1,1,0,1,0,0,1,1,0) Post 99 swaps: Black stack: L(0,0,1,1,0,0,0,1,1,0,0) Red stack: L(1,0,0,0,0,0,1,0,1,0,1,1,1,0,1) Agreed, black stack has same number of black cards as red stack has number of red cards: 7