How to resolve the algorithm Mind boggling card trick step by step in the Haskell programming language
How to resolve the algorithm Mind boggling card trick step by step in the Haskell programming language
Table of Contents
Problem Statement
Matt Parker of the "Stand Up Maths channel" has a YouTube video of a card trick that creates a semblance of order from chaos. The task is to simulate the trick in a way that mimics the steps shown in the video.
(Optionally, run this simulation a number of times, gathering more evidence of the truthfulness of the assertion.) Show output on this page.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Mind boggling card trick step by step in the Haskell programming language
The provided Haskell code simulates a card game with a shuffled deck of 52 cards, where the objective is to distribute the cards into "red" and "black" piles while ensuring that the number of red cards in the red pile is equal to the number of black cards in the black pile. A step-by-step explanation of the code:
-
Importing Necessary Modules: The code imports the
System.Random
module to generate random numbers and theData.List
andData.Monoid
modules for utility functions and data structures. -
main
Function: The entry point of the program is themain
function, which performs the following tasks:- Calls
knuthShuffle
to randomly shuffle a deck of numbers from 1 to 52, representing the cards in the deck. - Converts the shuffled list of numbers into a string of characters, where 'R' represents red cards and 'B' represents black cards, using the
rb
function. - Calls
threeStacks
to distribute the shuffled cards into three piles: the red pile (rs_
), the black pile (bs_
), and a discard pile (discards
). - Generates a random number
nSwap
between 1 and the minimum length of the red and black piles to determine how many cards should be swapped between the piles. - Calls
exchange
to swapnSwap
cards between the red and black piles, resulting in the finalrs
andbs
lists. - Checks the validity of the distribution by counting the number of red cards in
rs
(rrs
) and black cards inbs
(bbs
). It prints out various messages, including the discards, the number of cards swapped, the contents of the red and black piles, and whether the number of red cards in the red pile equals the number of black cards in the black pile.
- Calls
-
rb
Function: This function takes an integer representing a card and maps it to 'R' (red) if the number is even and 'B' (black) if it is odd. -
threeStacks
Function: This function takes a string of characters representing the shuffled deck and distributes them into three piles:rs
(red pile),bs
(black pile), andds
(discards). It recursively iterates through the input string, adding cards to the red or black pile based on their color and putting any remaining cards in the discards pile. -
exchange
Function: This function takes an integern
and two lists,xs
andys
, and swaps the firstn
elements between the two lists and returns them as the(xs', ys')
pair. -
knuthShuffle
Function: This function takes a list and generates a randomly shuffled version of the list using the Knuth shuffle algorithm. It iterates through the input list, zips it with a list of indexes, and applies theswapElems
function to each pair to randomly swap elements until the entire list is shuffled. -
randoms
Function: This function generates a list of random integers between 0 andx-1
, wherex
is the length of the input list. -
swapElems
Function: This function takes a pair of indexes(i, j)
and a listxs
and swaps the elements at indexesi
andj
in the list. -
replaceAt
Function: This function takes an indexi
, a valuec
, and a listl
and replaces the element at indexi
in the list with the valuec
, returning a new list.
Source code in the haskell programming language
import System.Random (randomRIO)
import Data.List (partition)
import Data.Monoid ((<>))
main :: IO [Int]
main = do
-- DEALT
ns <- knuthShuffle [1 .. 52]
let (rs_, bs_, discards) = threeStacks (rb <$> ns)
-- SWAPPED
nSwap <- randomRIO (1, min (length rs_) (length bs_))
let (rs, bs) = exchange nSwap rs_ bs_
-- CHECKED
let rrs = filter ('R' ==) rs
let bbs = filter ('B' ==) bs
putStrLn $
unlines
[ "Discarded: " <> discards
, "Swapped: " <> show nSwap
, "Red pile: " <> rs
, "Black pile: " <> bs
, rrs <> " = Red cards in the red pile"
, bbs <> " = Black cards in the black pile"
, show $ length rrs == length bbs
]
return ns
-- RED vs BLACK ----------------------------------------
rb :: Int -> Char
rb n
| even n = 'R'
| otherwise = 'B'
-- THREE STACKS ----------------------------------------
threeStacks :: String -> (String, String, String)
threeStacks = go ([], [], [])
where
go tpl [] = tpl
go (rs, bs, ds) [x] = (rs, bs, x : ds)
go (rs, bs, ds) (x:y:xs)
| 'R' == x = go (y : rs, bs, x : ds) xs
| otherwise = go (rs, y : bs, x : ds) xs
exchange :: Int -> [a] -> [a] -> ([a], [a])
exchange n xs ys =
let [xs_, ys_] = splitAt n <$> [xs, ys]
in (fst ys_ <> snd xs_, fst xs_ <> snd ys_)
-- SHUFFLE -----------------------------------------------
-- (See Knuth Shuffle task)
knuthShuffle :: [a] -> IO [a]
knuthShuffle xs = (foldr swapElems xs . zip [1 ..]) <$> randoms (length xs)
randoms :: Int -> IO [Int]
randoms x = traverse (randomRIO . (,) 0) [1 .. (pred x)]
swapElems :: (Int, Int) -> [a] -> [a]
swapElems (i, j) xs
| i == j = xs
| otherwise = replaceAt j (xs !! i) $ replaceAt i (xs !! j) xs
replaceAt :: Int -> a -> [a] -> [a]
replaceAt i c l =
let (a, b) = splitAt i l
in a ++ c : drop 1 b
You may also check:How to resolve the algorithm Smith numbers step by step in the Maple programming language
You may also check:How to resolve the algorithm Gamma function step by step in the Yabasic programming language
You may also check:How to resolve the algorithm Loops/N plus one half step by step in the AmigaE programming language
You may also check:How to resolve the algorithm Image noise step by step in the Liberty BASIC programming language
You may also check:How to resolve the algorithm Zeckendorf number representation step by step in the Clojure programming language