Skip to content

Instantly share code, notes, and snippets.

@blitzrk
Last active December 10, 2015 18:49
Show Gist options
  • Save blitzrk/3a1f2d07191823af1393 to your computer and use it in GitHub Desktop.
Save blitzrk/3a1f2d07191823af1393 to your computer and use it in GitHub Desktop.
Elm Random Permutation Proposal Raw
-- module Random.Extras (Generator, generate, permutation) where
import Random
import Graphics.Element exposing (show, Element)
import Time exposing (Time)
{-| Must redefine Random.Generator type because Random.Generator(Generator)
is not exposed.
-}
type Generator a =
Generator (Random.Seed -> (a, Random.Seed))
{-| Must also redefine Random.generate to fit new Generator type.
-}
generate : Generator a -> Random.Seed -> (a, Random.Seed)
generate (Generator generate) seed =
generate seed
{-| Generate random permutations of a given list. For example, this can
be used to shuffle a deck of cards or select the starting positions of
tiles in a sliding puzzle.
-}
permutation : List a -> Generator (List a)
permutation list =
let
length = List.length list
{- Knuth shuffle subproblem -}
randomMove n ((output, seed), input) =
let
(rand, newSeed) =
Random.generate (Random.int 0 (n-1)) seed
{- Add the `rand`th element of the remaining list of inputs to the
output permutation. -}
output' =
input
|> List.drop rand
|> List.take 1
|> List.append output
{- Strike the `rand`th element from the list of remaining inputs. -}
input' =
(List.take rand input) ++ (List.drop (rand+1) input)
in
((output', newSeed), input')
in
Generator <| \seed ->
List.foldr randomMove (([], seed), list) [1..length]
|> fst
-- View (example)
every : Time -> Signal Random.Seed
every interval =
Signal.map (Random.initialSeed << floor) (Time.every interval)
main : Signal Element
main =
let
view =
show << fst << (generate <| permutation [1..6])
-- The first digit changes slowly due to Random.int's implementation
in
Signal.map view (every <| 1/4 * Time.second)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment