Created
December 24, 2020 11:28
-
-
Save jcinnamond/497f5da12da912f83dcc797b740bce4b to your computer and use it in GitHub Desktop.
aoc23 in haskell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Crabs | |
( Cup, Current, Position | |
, simulate | |
, readCircle | |
) where | |
import Data.Tuple ( swap ) | |
import Data.List (elemIndex ) | |
-- Everything is an int, so create some type aliases to make the argument lists | |
-- more meaningful | |
type Cup = Int | |
type Current = Int | |
type Position = Int | |
{-| | |
simulate takes a starting circle and runs a given number of moves, | |
returning the state of the circle after those moves. | |
-} | |
simulate :: Int -> [Cup] -> [Cup] | |
simulate turns cups = foldl (\xs _ -> move xs) cups [1..turns] | |
{-| | |
`move` simulates a single move by the crab. It takes a list of cups with | |
the current cup at the start and returns a new list of cups shuffled by | |
the crab. The shuffling works as follows: | |
- the list is split into three parts -- the current cup, the cups picked | |
up by the crab, and the remaining cups. E.g., given the list [1,2,3,4,5,6,7,8,9] | |
this is split into the triple (1, [2,3,4], [5,6,7,8,9]) | |
- the destination cup is found in the remaining cups list | |
- the picked up cups as spliced into the list after the destination, and the | |
current cup is added to the end to "rotate" | |
-} | |
move :: [Cup] -> [Cup] | |
move cups = splice rest d held ++ [c] | |
where (c, held, rest) = split cups | |
d = destination (c - 1) rest | |
split :: [Cup] -> (Current, [Cup], [Cup]) | |
split xs = (current, held, rest) | |
where current = head xs | |
held = take 3 $ tail xs | |
rest = drop 3 $ tail xs | |
splice :: [Cup] -> Position -> [Cup] -> [Cup] | |
splice into pos from = head ++ from ++ tail | |
where (head, tail) = splitAt (pos + 1) into | |
destination :: Cup -> [Cup] -> Cup | |
destination c xs = case elemIndex c xs of | |
Just i -> i | |
Nothing -> destination newC xs | |
where newC = if c > 1 then c - 1 else 9 | |
{-| | |
readCircle finds the cup with the value 1 and returns the values of the | |
other cups in the order that they appear in the ciricle. | |
-} | |
readCircle :: [Cup] -> [Cup] | |
readCircle cups = case elemIndex 1 cups of | |
Just x -> tail $ uncurry (++) $ swap $ splitAt x cups |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Crabs ( readCircle, simulate ) | |
import Data.Char (digitToInt) | |
-- this doesn't handle newlines, so use something like "echo -n 123456789 | stack run :aoc23-exe" | |
main :: IO () | |
main = interact $ concatMap show . readCircle . simulate 100 . map digitToInt |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment