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

@@ -1,6 +1,10 @@
## TODO ## TODO
- [ ] fix "insufficient patterns", wire in M or Either String
- [ ] typeclass dependencies
- need to flag internal functions to not search (or flag functions for search)
- don't search instances that are currently being defined
- [ ] syntax for negative integers - [ ] syntax for negative integers
- [x] Put worker in iframe on safari - [x] Put worker in iframe on safari
- [ ] Warnings or errors for missing definitions - [ ] Warnings or errors for missing definitions

View File

@@ -2,6 +2,10 @@ module Aoc
import Prelude import Prelude
-- `by` is the first argument for use in `map`
nums' : String String List Int
nums' by s = map stringToInt $ filter (_/=_ "") $ split (trim s) by
nums : String List Int nums : String List Int
nums s = map stringToInt $ filter (_/=_ "") $ split (trim s) " " nums s = map stringToInt $ filter (_/=_ "") $ split (trim s) " "
@@ -25,13 +29,3 @@ indexOf? {a} z xs = go Z z xs
go ix z Nil = Nothing go ix z Nil = Nothing
go ix z (x :: xs) = go ix z (x :: xs) =
if z == x then Just ix else go (S ix) z xs if z == x then Just ix else go (S ix) z xs
-- if_then_else shorthand
-- Lean version uses a decidable instead of Bool
ite : a. Bool a a a
ite c t e = if c then t else e
-- probably not super efficient, but it works
qsort : a. (a a Bool) List a List a
qsort lt Nil = Nil
qsort lt (x :: xs) = qsort lt (filter (λ y => not $ lt x y) xs) ++ x :: qsort lt (filter (lt x) xs)

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

View File

@@ -91,18 +91,6 @@ fst (a,b) = a
snd : a b. a × b b snd : a b. a × b b
snd (a,b) = b snd (a,b) = b
infixl 6 _<_ _<=_
class Ord a where
_<_ : a a Bool
instance Ord Nat where
_ < Z = False
Z < S _ = True
S n < S m = n < m
_<=_ : a. {{Eq a}} {{Ord a}} a a Bool
a <= b = a == b || a < b
-- Monad -- Monad
class Monad (m : U U) where class Monad (m : U U) where
@@ -348,11 +336,6 @@ class HasIO (m : U -> U) where
instance HasIO IO where instance HasIO IO where
liftIO a = a liftIO a = a
pfunc debugLog uses (MkIORes MkUnit) : a. a -> IO Unit := `(_,s) => (w) => {
console.log(s)
return MkIORes(undefined,MkUnit,w)
}`
pfunc primPutStrLn uses (MkIORes MkUnit) : String -> IO Unit := `(s) => (w) => { pfunc primPutStrLn uses (MkIORes MkUnit) : String -> IO Unit := `(s) => (w) => {
console.log(s) console.log(s)
return MkIORes(undefined,MkUnit,w) return MkIORes(undefined,MkUnit,w)
@@ -387,7 +370,6 @@ pfunc pack : List Char → String := `(cs) => {
rval += cs.h1 rval += cs.h1
cs = cs.h2 cs = cs.h2
} }
return rval return rval
} }
` `
@@ -415,6 +397,9 @@ pfunc debugStr uses (natToInt listToArray) : ∀ a. a → String := `(_, obj) =>
return go(obj) return go(obj)
}` }`
debugLog : a. a IO Unit
debugLog a = putStrLn (debugStr a)
pfunc stringToInt : String Int := `(s) => { pfunc stringToInt : String Int := `(s) => {
let rval = Number(s) let rval = Number(s)
if (isNaN(rval)) throw new Error(s + " is NaN") if (isNaN(rval)) throw new Error(s + " is NaN")
@@ -444,9 +429,6 @@ instance Add Int where
instance Sub Int where instance Sub Int where
x - y = subInt x y x - y = subInt x y
instance Ord Int where
x < y = ltInt x y
printLn : {m} {{HasIO m}} {a} {{Show a}} a m Unit printLn : {m} {{HasIO m}} {a} {{Show a}} a m Unit
printLn a = putStrLn (show a) printLn a = putStrLn (show a)
@@ -633,3 +615,63 @@ instance Applicative List where
return a = a :: Nil return a = a :: Nil
Nil <*> _ = Nil Nil <*> _ = Nil
fs <*> ys = join $ map (\ f => map f ys) fs fs <*> ys = join $ map (\ f => map f ys) fs
tail : a. List a List a
tail Nil = Nil
tail (x :: xs) = xs
--
infixl 6 _<_ _<=_
class Ord a where
-- isEq : Eq a
_<_ : a a Bool
_<=_ : a. {{Eq a}} {{Ord a}} a a Bool
a <= b = a == b || a < b
search : cl. {{cl}} -> cl
search {{x}} = x
instance Ord Nat where
-- isEq = search
_ < Z = False
Z < S _ = True
S n < S m = n < m
instance Ord Int where
-- isEq = ?
x < y = ltInt x y
-- foo : ∀ a. {{Ord a}} -> a -> Bool
-- foo a = a == a
flip : a b c. (a b c) (b a c)
flip f b a = f a b
partition : a. (a Bool) List a List a × List a
partition {a} pred xs = go xs Nil Nil
where
go : List a List a List a List a × List a
go Nil as bs = (as, bs)
go (x :: xs) as bs = if pred x
then go xs (x :: as) bs
else go xs as (x :: bs)
-- probably not super efficient, but it works
qsort : a. (a a Bool) List a List a
qsort lt Nil = Nil
qsort lt (x :: xs) = qsort lt (filter (λ y => not $ lt x y) xs) ++ x :: qsort lt (filter (lt x) xs)
ordNub : a. {{Eq a}} {{Ord a}} -> List a -> List a
ordNub {a} {{ordA}} xs = go $ qsort _<_ xs
where
go : List a List a
go (a :: b :: xs) = if a == b then go (a :: xs) else a :: go (b :: xs)
go t = t
ite : a. Bool a a a
ite c t e = if c then t else e

View File

@@ -17,10 +17,6 @@ digits1 (c :: cs) = let x = ord c in
False => digits1 cs False => digits1 cs
False => digits1 cs False => digits1 cs
tail : {a : U} -> List a -> List a
tail Nil = Nil
tail (x :: xs) = xs
-- TODO I used @ patterns in Lean -- TODO I used @ patterns in Lean
digits2 : List Char -> List Int digits2 : List Char -> List Int
digits2 xs = case xs of digits2 xs = case xs of

View File

@@ -96,6 +96,10 @@ solveAutos : Nat -> List MetaEntry -> M ()
solveAutos mstart [] = pure () solveAutos mstart [] = pure ()
solveAutos mstart ((Unsolved fc k ctx ty AutoSolve _) :: es) = do solveAutos mstart ((Unsolved fc k ctx ty AutoSolve _) :: es) = do
debug "AUTO solving \{show k} : \{show ty}" debug "AUTO solving \{show k} : \{show ty}"
-- fill in solved metas in type
x <- quote ctx.lvl ty
ty <- eval ctx.env CBN x
debug "AUTO ---> \{show ty}"
-- we want the context here too. -- we want the context here too.
top <- get top <- get
[(tm, mc)] <- case !(contextMatches ctx ty) of [(tm, mc)] <- case !(contextMatches ctx ty) of
@@ -138,7 +142,11 @@ logMetas mstart = do
mc <- readIORef top.metas mc <- readIORef top.metas
let mlen = length mc.metas `minus` mstart let mlen = length mc.metas `minus` mstart
for_ (reverse $ take mlen mc.metas) $ \case for_ (reverse $ take mlen mc.metas) $ \case
(Solved fc k soln) => info fc "solve \{show k} as \{pprint [] !(quote 0 soln)}" (Solved fc k soln) => do
-- TODO put a flag on this, vscode is getting overwhelmed and
-- dropping errors
--info fc "solve \{show k} as \{pprint [] !(quote 0 soln)}"
pure ()
(Unsolved fc k ctx ty User cons) => do (Unsolved fc k ctx ty User cons) => do
ty' <- quote ctx.lvl ty ty' <- quote ctx.lvl ty
let names = (toList $ map fst ctx.types) let names = (toList $ map fst ctx.types)