From 6967e020b03b9bc57f48578ba36594cb873253dc Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Sat, 16 Dec 2017 10:53:25 +0100 Subject: Day 16 a --- 2017/16.hs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 2017/16.hs (limited to '2017/16.hs') diff --git a/2017/16.hs b/2017/16.hs new file mode 100644 index 0000000..9469d71 --- /dev/null +++ b/2017/16.hs @@ -0,0 +1,48 @@ +import Control.Monad +import Data.Char +import Data.List +import Data.Maybe + + +splitOn :: Eq a => a -> [a] -> [[a]] +splitOn c xs = case break (== c) xs of + (pre, []) -> [pre] + (pre, _ : post) -> pre : splitOn c post + +strip :: String -> String +strip = dropWhile isSpace . reverse . dropWhile isSpace . reverse + +swap :: Int -> Int -> [a] -> [a] +swap i j (hd:tl) = case (i, j) of + (0, _) -> uncurry (:) (go (j-1) hd tl) + (_, 0) -> uncurry (:) (go (i-1) hd tl) + (_, _) -> hd : swap (i-1) (j-1) tl + where + go 0 v (hd:tl) = (hd, v : tl) + go k v (hd:tl) = fmap (hd :) (go (k-1) v tl) + +data Ins = Spin Int | Exch Int Int | Part Int Int + deriving Show + +newtype State = State [Int] + +instance Show State where + show (State ar) = map (chr . (+ ord 'a')) ar + +parse :: String -> Ins +parse ('s' : s) = Spin (read s) +parse ('x' : s) = let [a, b] = splitOn '/' s in Exch (read a) (read b) +parse ['p', a, '/', b] = Part (ord a - ord 'a') (ord b - ord 'a') + +exec :: State -> Ins -> State +exec (State ar) (Spin n) = State $ take 16 (drop (16 - n) (cycle ar)) +exec (State ar) (Exch i j) = State $ swap i j ar +exec (State ar) (Part a b) = + let i = fromMaybe (-1) (findIndex (== a) ar) + j = fromMaybe (-1) (findIndex (== b) ar) + in State $ swap i j ar + +main :: IO () +main = do + input <- liftM (map parse . splitOn ',' . strip) (readFile "16.in") + print (foldl exec (State [0..15]) input) -- cgit v1.2.3-70-g09d2