Day5, add SortedMap

This commit is contained in:
2024-12-05 16:13:12 -08:00
parent 21b03368d4
commit ccbd617671
11 changed files with 268 additions and 42 deletions

View File

@@ -21,12 +21,8 @@ check prob r c (dr,dc) =
else if (get prob (r + 3 * dr) (c + 3 * dc)) /= 'S' then 0
else 1
tail : a. List a List a
tail Nil = Nil
tail (x :: xs) = xs
dirs : List (Int × Int)
dirs = tail $ _,_ <$> (0 :: 0 - 1 :: 1 :: Nil) <*> (0 :: 0 - 1 :: 1 :: Nil)
dirs = tail $ _,_ <$> 0 :: 0 - 1 :: 1 :: Nil <*> 0 :: 0 - 1 :: 1 :: Nil
part1 : Problem Int
part1 (P size text) = go 0 0 0
@@ -70,7 +66,6 @@ run fn = do
text <- readFile fn
let lines = split (trim text) "\n"
-- I'm going to assume it's square for convenience
-- part2 will probably wrap around.
let size = length lines
printLn $ "part1 " ++ show (part1 $ P (cast size) text)
printLn $ "part2 " ++ show (part2 $ P (cast size) text)

77
aoc2024/Day5.newt Normal file
View File

@@ -0,0 +1,77 @@
module Day5
import Prelude
import Node
import Aoc
import SortedMap
data Prob : U where
MkProb : List (Int × Int) -> List (List Int) Prob
parseRule : String Maybe (Int × Int)
parseRule txt =
let (a :: b :: Nil) = nums' "|" txt | _ => Nothing
in Just (a,b)
parse : String Maybe Prob
parse text = do
let (a :: b :: Nil) = split (trim text) "\n\n" | pts => Nothing
rules <- traverse parseRule $ split a "\n"
let updates = map (nums' ",") $ split b "\n"
Just $ MkProb rules updates
RuleMap : U
RuleMap = SortedMap Int (List Int)
getDisallowed : Int RuleMap List Int
getDisallowed key rmap = fromMaybe Nil (map snd $ lookupMap key rmap)
mkRuleMap : List (Int × Int) -> RuleMap
mkRuleMap rules = foldl go EmptyMap rules
where
go : RuleMap Int × Int RuleMap
go rmap (b,a) = updateMap a (b :: getDisallowed a rmap) rmap
scan : RuleMap List Int -> List Int -> Bool
scan rmap interdit Nil = True
scan rmap interdit (x :: xs) =
if elem x interdit then False
else scan rmap (getDisallowed x rmap ++ interdit) xs
fix : RuleMap List Int List Int
fix rmap Nil = Nil
fix rmap (x :: xs) =
let interdit = getDisallowed x rmap in
let (prefix,rest) = partition (flip elem interdit) xs
in case prefix of
Nil => x :: fix rmap rest
ys => fix rmap (ys ++ x :: rest)
middle : List Int -> Int
middle xs = go xs xs
where
go : List Int List Int Int
go (x :: xs) (_ :: _ :: ys) = go xs ys
go (x :: xs) (_ :: ys) = x
go _ _ = 0
run : String -> IO Unit
run fn = do
putStrLn fn
text <- readFile fn
let (Just prob) = parse text | _ => putStrLn "Parse Error"
let (MkProb rules things) = prob
let rmap = mkRuleMap rules
let good = filter (scan rmap Nil) things
let part1 = foldl _+_ 0 $ map middle good
let bad = filter (not scan rmap Nil) things
putStrLn $ "part1 " ++ show part1
let fixed = map (fix rmap) bad
printLn $ length bad
let part2 = foldl _+_ 0 $ map middle fixed
putStrLn $ "part2 " ++ show part2
main : IO Unit
main = do
run "aoc2024/day5/eg.txt"
run "aoc2024/day5/input.txt"

17
aoc2024/DayXX.newt Normal file
View File

@@ -0,0 +1,17 @@
module DayXX
import Prelude
import Node
import Aoc
run : String -> IO Unit
run fn = do
putStrLn fn
text <- readFile fn
putStrLn text
main : IO Unit
main = do
run "aoc2024/dayXX/eg.txt"
run "aoc2024/dayXX/input.txt"

58
aoc2024/SortedMap.newt Normal file
View File

@@ -0,0 +1,58 @@
module SortedMap
data T23 : Nat -> U -> U -> U where
Leaf : k v. k -> v -> T23 Z k v
Node2 : h k v. T23 h k v -> k -> T23 h k v -> T23 (S h) k v
Node3 : h k v. T23 h k v -> k -> T23 h k v -> k -> T23 h k v -> T23 (S h) k v
lookupT23 : h k v. {{Ord k}} {{Eq k}} -> k -> T23 h k v -> Maybe (k × v)
lookupT23 key (Leaf k v)= if k == key then Just (k,v) else Nothing
lookupT23 key (Node2 t1 k1 t2) =
if key <= k1 then lookupT23 key t1 else lookupT23 key t2
lookupT23 key (Node3 t1 k1 t2 k2 t3) =
if key <= k1 then lookupT23 key t1
else if key <= k2 then lookupT23 key t2
else lookupT23 key t3
insertT23 : h k v. {{Ord k}} {{Eq k}} -> k -> v -> T23 h k v -> Either (T23 h k v) (T23 h k v × k × T23 h k v)
insertT23 key value (Leaf k v) =
if key == k then Left (Leaf key value)
else if key <= k then Right (Leaf key value, key, Leaf k v)
else Right (Leaf k v, k, Leaf key value)
insertT23 key value (Node2 t1 k1 t2) =
if key <= k1 then
case insertT23 key value t1 of
Left t1' => Left (Node2 t1' k1 t2)
Right (a,b,c) => Left (Node3 a b c k1 t2)
else case insertT23 key value t2 of
Left t2' => Left (Node2 t1 k1 t2')
Right (a,b,c) => Left (Node3 t1 k1 a b c)
insertT23 key value (Node3 t1 k1 t2 k2 t3) =
if key <= k1 then
case insertT23 key value t1 of
Left t1' => Left (Node3 t1' k1 t2 k2 t3)
Right (a,b,c) => Right (Node2 a b c, k1, Node2 t2 k2 t3)
else if key <= k2 then
case insertT23 key value t2 of
Left t2' => Left (Node3 t1 k1 t2' k2 t3)
Right (a,b,c) => Right (Node2 t1 k1 a, b, Node2 c k2 t3)
else
case insertT23 key value t3 of
Left t3' => Left (Node3 t1 k1 t2 k2 t3')
Right (a,b,c) => Right (Node2 t1 k1 t2, k2, Node2 a b c)
-- There is no empty tree23?
data SortedMap : U -> U -> U where
EmptyMap : k v. SortedMap k v
MapOf : k v h. T23 h k v -> SortedMap k v
lookupMap : k v. {{Ord k}} {{Eq k}} -> k -> SortedMap k v -> Maybe (k × v)
lookupMap k EmptyMap = Nothing
lookupMap k (MapOf map) = lookupT23 k map
updateMap : k v. {{Ord k}} {{Eq k}} -> k -> v -> SortedMap k v -> SortedMap k v
updateMap k v EmptyMap = MapOf $ Leaf k v
updateMap k v (MapOf map) = case insertT23 k v map of
Left map' => MapOf map'
Right (a, b, c) => MapOf (Node2 a b c)

28
aoc2024/day5/eg.txt Normal file
View File

@@ -0,0 +1,28 @@
47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13
75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47

7
aoc2024/mkday Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/zsh -e
day=$1
if [ ! -d day${day} -a ! -z "$1" ]; then
echo Make Day ${day}
mkdir day${day}
sed "s/XX/$day/g" DayXX.newt > Day$day.newt
fi