summaryrefslogtreecommitdiff
path: root/2017/16.hs
diff options
context:
space:
mode:
Diffstat (limited to '2017/16.hs')
-rw-r--r--2017/16.hs48
1 files changed, 48 insertions, 0 deletions
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)