chore: complete day 5
parent
c6053d1f89
commit
9012b7b125
@ -1,7 +1,20 @@
|
|||||||
|
{-# language ScopedTypeVariables, GADTs #-}
|
||||||
|
|
||||||
module AOC (
|
module AOC (
|
||||||
module AOC.Types,
|
module AOC.Types,
|
||||||
mkAocClient
|
mkAocClient,
|
||||||
|
showSolution,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import AOC.Types
|
import AOC.Types
|
||||||
import AOC.API
|
import AOC.API
|
||||||
|
import Type.Reflection
|
||||||
|
|
||||||
|
-- TODO find a better way to avoid 'show'ing Stringlike things in
|
||||||
|
-- quotes ("") without resorting to end-users having to wrap Solutions
|
||||||
|
-- with something like data StringOr = StringLike a | NotStringLike b
|
||||||
|
showSolution :: forall a. (Typeable a, Show a) => a -> String
|
||||||
|
showSolution a = case eqTypeRep (typeRep @a) (typeRep @String) of
|
||||||
|
Just HRefl -> a
|
||||||
|
Nothing -> show a
|
||||||
|
|
||||||
|
@ -1,16 +1,62 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module Days.Day05 (day05) where
|
module Days.Day05 (day05) where
|
||||||
|
|
||||||
import AOC (Solution (..))
|
import AOC (Solution (..))
|
||||||
import qualified Data.Text as T
|
import Data.Char
|
||||||
|
import Data.List qualified as L
|
||||||
|
import Data.List.Split qualified as S
|
||||||
|
import Data.Text qualified as T
|
||||||
|
|
||||||
|
-- 1. How many crates to move
|
||||||
|
-- 2. The stack to move crates from
|
||||||
|
-- 3. The stack to move crates to
|
||||||
|
type Instruction = (Int, Int, Int)
|
||||||
|
|
||||||
|
mapTuple :: (a -> b) -> (a, a, a) -> (b, b, b)
|
||||||
|
mapTuple f (a1, a2, a3) = (f a1, f a2, f a3)
|
||||||
|
|
||||||
|
replaceNth :: Int -> a -> [a] -> [a]
|
||||||
|
replaceNth _ _ [] = []
|
||||||
|
replaceNth n newVal (x : xs)
|
||||||
|
| n == 0 = newVal : xs
|
||||||
|
| otherwise = x : replaceNth (n - 1) newVal xs
|
||||||
|
|
||||||
day05 :: Solution
|
day05 :: Solution
|
||||||
day05 = Solution parseInput part1 part2
|
day05 = Solution parseInput part1 part2
|
||||||
|
|
||||||
parseInput :: T.Text -> a
|
parseInput :: T.Text -> ([String], [Instruction])
|
||||||
parseInput = error "parseInput not defined for day 05"
|
parseInput input = (cleanStacks, intInsts)
|
||||||
|
where
|
||||||
|
[crates, insts] = S.splitOn "\n\n" (T.unpack input)
|
||||||
|
inst = filter (not . null) $ map (filter isDigit) (words insts)
|
||||||
|
intInsts = map (\[one, two, three] -> mapTuple read (one, two, three)) (S.chunksOf 3 inst)
|
||||||
|
stacks = init $ lines crates
|
||||||
|
cleanStacks = map concat $ L.transpose $ map (map filtered . S.chunksOf 4) stacks
|
||||||
|
filtered xs = [xs !! 1 | xs !! 1 /= ' ']
|
||||||
|
|
||||||
part1 :: a -> Int
|
part1 :: ([String], [Instruction]) -> String
|
||||||
part1 = error "part1 not defined for day 05"
|
part1 (stacks, instructions) = map head (foldl logic stacks instructions)
|
||||||
|
where
|
||||||
|
logic :: [String] -> Instruction -> [String]
|
||||||
|
logic stacks' (num, from, to) = replacedStacks
|
||||||
|
where
|
||||||
|
to' = to - 1
|
||||||
|
from' = from - 1
|
||||||
|
sFrom = stacks' !! from'
|
||||||
|
sTo = stacks' !! to'
|
||||||
|
taken = replaceNth from' (drop num sFrom) stacks'
|
||||||
|
replacedStacks = replaceNth to' (reverse (take num sFrom) ++ sTo) taken
|
||||||
|
|
||||||
part2 :: a -> Int
|
part2 :: ([String], [Instruction]) -> String
|
||||||
part2 = error "part2 not defined for day 05"
|
part2 (stacks, instructions) = map head (foldl logic stacks instructions)
|
||||||
|
where
|
||||||
|
logic :: [String] -> Instruction -> [String]
|
||||||
|
logic stacks' (num, from, to) = replacedStacks
|
||||||
|
where
|
||||||
|
to' = to - 1
|
||||||
|
from' = from - 1
|
||||||
|
sFrom = stacks' !! from'
|
||||||
|
sTo = stacks' !! to'
|
||||||
|
taken = replaceNth from' (drop num sFrom) stacks'
|
||||||
|
replacedStacks = replaceNth to' (take num sFrom ++ sTo) taken
|
||||||
|
Loading…
Reference in New Issue