# Shuffling a deck of cards with Elm

Here’s the problem: given a list of things — cards, numbers, whatever — how can we put them in a random order? This is a nice little computer science problem that we will solve using Elm, a relatively new and, in my opinion, totally awesome programming language.

Elm is a language of pure functions, which means that that the inputs to a function completely determine its outputs, just like in Math. It’s main use is building web apps.

## Cutting the deck

Our solution is going to be built by snapping together some handy-dandy parts, the functional programming equivalent of Legos. The first part we shall use is the function `List.Extra.splitAt`

. It will be used to cut the card deck:

`> List.Extra.splitAt 3 [10, 11, 12, 13, 14, 15]`

([10,11,12],[13,14,15])

The result is a tuple consisting of the two halves of the list. If we glue these two parts back together in the opposite order, we have cut the deck. Let’s package this idea as a function definition:

`cut : `**Int **-> **List a **-> **List a**

cut j list =

**let**

k = modBy (List.length list) j

(a, b) = List.Extra.splitAt k list

**in**

b ++ a

And let’s test the function to make sure it works as expected:

> cut 3 [1,2,3,4,5,6,7,8]

[4,5,6,7,8,1,2,3]> cut 3 ["Red", "Green", "Blue", "Black", "White"]

["Black","White","Red","Green","Blue"]

So far, so good!

## Shuffling the deck

To shuffle the deck, we use the `interleave`

function:

`> List.Extra.interweave [1,2,3] [4,5,6]`

[1,4,2,5,3,6]

To perform a real shuffle, we make up a function that splits the deck into two parts, then interweaves the parts:

`shuffle : `**List a **-> **List a**

shuffle list =

**let**

(a, b) = List.Extra.splitAt ((List.length list)//2) list

**in**

List.Extra.interweave a b

Again, we test:

`> shuffle [1,2,3,4,5,6]`

[1,4,2,5,3,6]

Happily, `shuffle`

works with an odd number of elements as well:

`> shuffle [1,2,3,4,5]`

[1,3,2,4,5]

## Dealer’s move

In real card play, the dealer cuts the cards, then shuffles. We’ll do the same:

`dealersMove : `**Int **-> **List a **-> **List a**

dealersMove k list =

list

|> cut k

|> shuffle

Here is the Dealer’s Move in action:

`> dealersMove 2 [1,2,3,4,5,6]`

[3,6,4,1,5,2]

## Repeating the Dealer’s Move

You may want to repeat the Dealer’s Move several times to really mix things up. To do this, we use the `List.foldl`

function to apply `dealersMove`

again and again:

`randomizeList : (`**List Int**) -> **List a **-> **List a**

randomizeList integerList list =

List.foldl dealersMove list integerList

The `integerList`

parameter holds a list of numbers that will be used in applying the Dealer’s Move. The code in the example below has the same effect as applying `dealersMove`

first with parameter 2, then to the result with parameter 5

`randomizeList [2, 5] [1, 2, 3, 4, 5, 6, 7, 9, 10]`

[10,3,6,7,1,4,2,9,5]

If you use a random number generator to produce `integerList`

, then the result of applying `randomize integerList`

to a list will be a random permutation of the given list. We have reached our destination! Notice how little work we did —mostly combining powerful functions like `splitAt`

and `interweave`

. Our Lego pieces.

NOTE. As @jgrenat on the Elm Slack pointed out to me, there is a library function which does what this article describes. Please see elm-community/random.

## Appendix

Here is the full code:

**module **Cards **exposing **(..)

**import **List.Extra

cut : **Int **-> **List a **-> **List a**

cut j list =

**let**

k = modBy (List.length list) j

(a, b) = List.Extra.splitAt j list

**in**

b ++ a

shuffle : **List a **-> **List a**

shuffle list =

**let**

(a, b) = List.Extra.splitAt ((List.length list)//2) list

**in**

List.Extra.interweave a b

dealersMove : **Int **-> **List a **-> **List a**

dealersMove k list =

list

|> cut k

|> shuffle

{-|

> randomizeList [2, 4, 3] [1,2,3,4,5,6]

[4,5,3,6,1,2]

-}

randomizeList : (**List Int**) -> **List a **-> **List a**

randomizeList integerList list =

List.foldl dealersMove list integerList