Skip to content

Instantly share code, notes, and snippets.

@dhwthompson
Created February 22, 2015 12:44
Show Gist options
  • Save dhwthompson/282f6ddd7765f5606ebd to your computer and use it in GitHub Desktop.
Save dhwthompson/282f6ddd7765f5606ebd to your computer and use it in GitHub Desktop.
Urinal protocol simulation
import Data.Function
import Data.List
import System.Environment
data Urinal = Free | Taken deriving (Show, Eq)
empty n = take n $ repeat Free
place urinals
| all (== Free) urinals = Taken : tail urinals
| otherwise =
let candidates = elemIndices Free urinals
takens = elemIndices Taken urinals
distance a b = abs $ a - b
minDistance c = minimum $ map (distance c) takens
bestPlace = maximumBy (compare `on` minDistance) candidates
(lefts, _:rights) = splitAt bestPlace urinals
in lefts ++ [Taken] ++ rights
awkward :: [Urinal] -> Bool
awkward [] = False
awkward (Taken:Taken:_) = True
awkward (u:us) = awkward us
asciify :: [Urinal] -> String
asciify = map urinalChar
where urinalChar Free = '.'
urinalChar Taken = 'X'
main = do
[countStr] <- getArgs
mapM_ (putStrLn . asciify) $ takeWhile (not . awkward) $ iterate place $ empty $ read countStr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment