Shuffle a deck without local variables
Haskell
Here is a point-free implementation. No variables, formal parameters, or explicit recursion. I used lambdabot's @pl
("pointless") refactoring feature quite a bit.
import Data.List
import Control.Applicative
import Control.Monad
import System.Random
shuffle :: [a] -> IO [a]
shuffle = liftM2 (<$>) ((fst .) . foldl' (uncurry ((. flip splitAt) . (.) .
(`ap` snd) . (. fst) . flip flip tail . (ap .) . flip flip head .
((.) .) . (. (++)) . flip . (((.) . (,)) .) . flip (:))) . (,) [])
(sequence . map (randomRIO . (,) 0 . subtract 1) . reverse .
enumFromTo 1 . length)
main = print =<< shuffle [1..52]
Here's my test procedure to make sure the numbers were uniformly distributed:
main = print . foldl' (zipWith (+)) (replicate 52 0)
=<< replicateM 1000 (shuffle [1..52])
Here is the original algorithm:
shuffle :: [a] -> IO [a]
shuffle xs = shuffleWith xs <$>
sequence [randomRIO (0, i - 1) | i <- reverse [1..length xs]]
shuffleWith :: [a] -> [Int] -> [a]
shuffleWith xs ns = fst $ foldl' f ([], xs) ns where
f (a,b) n = (x:a, xs++ys) where
(xs, x:ys) = splitAt n b
JavaScript
I believe this is the intended form of solution, I use the card in position 0 to keep track of progress, only shuffling the cards that have already been used as counter, this achieves the standard 52! permutations with a perfect equal distribution. The procedure is complicated by XOR swap not allowing that an element is swapped by itself.
Edit: I built in a sorting that sorts each element into place just before it is used, thus allowing this to work with an unsorted array. I also dropped recursive calling in favour of a while loop.
deck=[]
for(a=0;a<52;a++){
deck[a]=a
}
function swap(a,b){
deck[a]=deck[b]^deck[a]
deck[b]=deck[b]^deck[a]
deck[a]=deck[b]^deck[a]
}
function rand(a,b){
return Math.floor(Math.random()*(1+b-a))+a
}
function shuffle(){
while(deck[0]!=0){ //Sort 0 into element 0
swap(0,deck[0])
}
while(deck[0]<51){ //Run 51 times
while(deck[deck[0]+1]!=deck[0]+1){ //Sort element deck[0]+1 into position deck[0]+1
swap(deck[deck[0]+1],deck[0]+1)
}
swap(0,deck[0]+1) //Swap element deck[0]+1 into position 0, thus increasing the value of deck[0] by 1
if(rand(0,deck[0]-1)){ //Swap the element at position deck[0] to a random position in the range 1 to deck[0]
swap(deck[0],rand(1,deck[0]-1))
}
}
if(rand(0,51)){ //Swap the element at position 0 to a random position
swap(0,rand(1,51))
}
}
for(c=0;c<100;c++){
shuffle()
document.write(deck+"<br>")
}
J
Ignoring that deck is a variable, there's the obvious...
52 ? 52
Of course, if you really want a function, there's this, which will work even if you forget to remove the jokers (or try to shuffle something other than cards).
{~ (# ? #)
So that...
shuffle =: {~ (# ? #)
deck =: i. 52
shuffle deck
This is probably outside the intent of the question, which would be to implement the shuffle yourself from rand (?
). I might do that later when I'm not supposed to be working.
Explanation
Explanation of 52 ? 52
:
x ? y
is x random unique items from y.
Explanation of {~ (# ? #)
is harder because of forks and hooks. Basically, it is the same as shuffle =: 3 : '((# y) ? (# y)) { y'
, which has one implicit argument (y
).
# y
gives the length of y- This gives 52 ? 52 like before, which is a random permutation of 0..51
x { y
is the item of y in index x, or (in this case) items in the indexes in x.- This lets you shuffle whatever is passed in, not just integers.
See J Vocabulary for details of operators, though the syntax and semantics are quite a bit tricky because of rank and tacit programming.