Compare commits
No commits in common. "3826a1324466ce7f8fc4858173b453652695d5a7" and "b40650cd6bde21d781d0737d654f0d3aaa85f6d8" have entirely different histories.
3826a13244
...
b40650cd6b
|
@ -13,3 +13,10 @@ depends = contrib
|
||||||
|
|
||||||
executable = advent-of-code-2024
|
executable = advent-of-code-2024
|
||||||
main = Main
|
main = Main
|
||||||
|
modules = Main, Utils, AllDays,
|
||||||
|
Data.Problem,
|
||||||
|
Day1.Part1, Day1.Part2,
|
||||||
|
Day2.Part1, Day2.Part2,
|
||||||
|
Day3.Part1, Day3.Part2,
|
||||||
|
Day4.Part1, Day4.Part2,
|
||||||
|
Day5.Part1, Day5.Part2
|
||||||
|
|
|
@ -10,7 +10,3 @@ import public Day4.Part1
|
||||||
import public Day4.Part2
|
import public Day4.Part2
|
||||||
import public Day5.Part1
|
import public Day5.Part1
|
||||||
import public Day5.Part2
|
import public Day5.Part2
|
||||||
import public Day6.Part1
|
|
||||||
import public Day6.Part2
|
|
||||||
import public Day7.Part1
|
|
||||||
import public Day7.Part2
|
|
||||||
|
|
|
@ -3,15 +3,17 @@ module Day4.Part1
|
||||||
import Data.String
|
import Data.String
|
||||||
import Data.Vect
|
import Data.Vect
|
||||||
|
|
||||||
import Utils
|
|
||||||
|
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
--- TYPES
|
--- TYPES
|
||||||
|
|
||||||
public export
|
public export
|
||||||
Board : Nat -> Nat -> Type
|
Board : Nat -> Nat -> Type
|
||||||
Board h w = Grid h w Char
|
Board h w = Vect h (Vect w Char)
|
||||||
|
|
||||||
|
public export
|
||||||
|
Pos : Nat -> Nat -> Type
|
||||||
|
Pos h w = (Fin h, Fin w)
|
||||||
|
|
||||||
|
|
||||||
public export
|
public export
|
||||||
|
@ -25,10 +27,19 @@ directions = [U, UR, R, DR, D, DL, L, UL]
|
||||||
|
|
||||||
export
|
export
|
||||||
parseInput : String -> Maybe (h ** w ** Board h w)
|
parseInput : String -> Maybe (h ** w ** Board h w)
|
||||||
parseInput = parseGrid
|
parseInput inp =
|
||||||
|
let ls@(row :: _) = unpack <$> lines inp
|
||||||
|
| [] => Just (0 ** 0 ** [])
|
||||||
|
width = length row
|
||||||
|
in map (\l => (length l ** width ** fromList l))
|
||||||
|
(traverse (toVect width) ls)
|
||||||
|
|
||||||
--- DATA
|
--- DATA
|
||||||
|
|
||||||
|
export
|
||||||
|
index : Pos h w -> Board h w -> Char
|
||||||
|
index (i, j) = index j . index i
|
||||||
|
|
||||||
predFin : Fin n -> Maybe (Fin n)
|
predFin : Fin n -> Maybe (Fin n)
|
||||||
predFin FZ = Nothing
|
predFin FZ = Nothing
|
||||||
predFin (FS x) = Just $ weaken x
|
predFin (FS x) = Just $ weaken x
|
||||||
|
|
|
@ -4,7 +4,6 @@ import Data.String
|
||||||
import Data.Vect
|
import Data.Vect
|
||||||
|
|
||||||
import Day4.Part1
|
import Day4.Part1
|
||||||
import Utils
|
|
||||||
|
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
module Day6.Part1
|
|
||||||
|
|
||||||
import Data.Colist
|
|
||||||
import Data.List
|
|
||||||
import Data.Maybe
|
|
||||||
import Data.Vect
|
|
||||||
import Data.Vect.Quantifiers
|
|
||||||
|
|
||||||
import Utils
|
|
||||||
|
|
||||||
%default total
|
|
||||||
|
|
||||||
--- TYPES
|
|
||||||
|
|
||||||
public export
|
|
||||||
data Direction = U | R | D | L
|
|
||||||
|
|
||||||
export
|
|
||||||
Eq Direction where
|
|
||||||
U == U = True
|
|
||||||
D == D = True
|
|
||||||
L == L = True
|
|
||||||
R == R = True
|
|
||||||
_ == _ = False
|
|
||||||
|
|
||||||
-- True if there is an obstacle
|
|
||||||
public export
|
|
||||||
Map : Nat -> Nat -> Type
|
|
||||||
Map h w = Grid h w Bool
|
|
||||||
|
|
||||||
--- PARSING
|
|
||||||
|
|
||||||
parseDir : Char -> Maybe Direction
|
|
||||||
parseDir '^' = Just U
|
|
||||||
parseDir '>' = Just R
|
|
||||||
parseDir 'v' = Just D
|
|
||||||
parseDir '<' = Just L
|
|
||||||
parseDir _ = Nothing
|
|
||||||
|
|
||||||
export
|
|
||||||
parseInput : String -> Maybe (h ** w ** (Map h w, Pos h w, Direction))
|
|
||||||
parseInput inp = do
|
|
||||||
(h ** w ** grid) <- parseGrid inp
|
|
||||||
g <- findGuard grid
|
|
||||||
pure (h ** w ** ((map . map) (=='#') grid, g))
|
|
||||||
where
|
|
||||||
findGuard : Vect h (Vect w Char) -> Maybe (Pos h w, Direction)
|
|
||||||
findGuard [] = Nothing
|
|
||||||
findGuard (row :: vs) =
|
|
||||||
case any (\c => isItJust (parseDir c)) row of
|
|
||||||
Yes p => Just ((FZ, cast $ anyToFin p), fromJust _ @{anyToFinCorrect p})
|
|
||||||
No _ => map (mapFst (mapFst FS)) $ findGuard vs
|
|
||||||
|
|
||||||
--- DATA
|
|
||||||
|
|
||||||
predFin : Fin n -> Maybe (Fin n)
|
|
||||||
predFin FZ = Nothing
|
|
||||||
predFin (FS x) = Just $ weaken x
|
|
||||||
|
|
||||||
export
|
|
||||||
moveDir : {h, w : _} -> Direction -> Pos h w -> Maybe (Pos h w)
|
|
||||||
moveDir U (i, j) = (,j) <$> predFin i
|
|
||||||
moveDir R (i, j) = (i,) <$> strengthen (FS j)
|
|
||||||
moveDir D (i, j) = (,j) <$> strengthen (FS i)
|
|
||||||
moveDir L (i, j) = (i,) <$> predFin j
|
|
||||||
|
|
||||||
export
|
|
||||||
rotate : Direction -> Direction
|
|
||||||
rotate U = R
|
|
||||||
rotate R = D
|
|
||||||
rotate D = L
|
|
||||||
rotate L = U
|
|
||||||
|
|
||||||
getRoute : {h, w : _} -> (Pos h w, Direction) -> Map h w
|
|
||||||
-> Colist (Pos h w, Direction)
|
|
||||||
getRoute (pos, dir) mp =
|
|
||||||
let Just next = moveDir dir pos
|
|
||||||
| Nothing => [(pos, dir)]
|
|
||||||
in (pos, dir) ::
|
|
||||||
if index next mp
|
|
||||||
then getRoute (pos, rotate dir) mp
|
|
||||||
else getRoute (next, dir) mp
|
|
||||||
|
|
||||||
--- SOLUTION
|
|
||||||
|
|
||||||
covering
|
|
||||||
forceList : Colist a -> List a
|
|
||||||
forceList [] = []
|
|
||||||
forceList (x :: xs) = x :: forceList xs
|
|
||||||
|
|
||||||
export covering
|
|
||||||
solution : String -> Maybe Nat
|
|
||||||
solution inp = do
|
|
||||||
(h ** w ** (mp, g)) <- parseInput inp
|
|
||||||
pure $ length $ nub $ map fst $ forceList $ getRoute g mp
|
|
|
@ -1,64 +0,0 @@
|
||||||
module Day6.Part2
|
|
||||||
|
|
||||||
import Data.Colist
|
|
||||||
import Data.List
|
|
||||||
import Data.Maybe
|
|
||||||
import Data.Vect
|
|
||||||
|
|
||||||
import Day6.Part1
|
|
||||||
import Utils
|
|
||||||
|
|
||||||
%default total
|
|
||||||
|
|
||||||
--- DATA
|
|
||||||
|
|
||||||
getCollisions : {h, w : _} -> (Pos h w, Direction) -> Map h w
|
|
||||||
-> Colist (Pos h w, Direction)
|
|
||||||
getCollisions (pos, dir) mp =
|
|
||||||
let Just next = moveDir dir pos
|
|
||||||
| Nothing => []
|
|
||||||
in if index next mp
|
|
||||||
then (next, dir) :: getCollisions (pos, rotate dir) mp
|
|
||||||
else assert_total $ getCollisions (next, dir) mp
|
|
||||||
|
|
||||||
insertObs : Pos h w -> Map h w -> Map h w
|
|
||||||
insertObs (i, j) = updateAt i (replaceAt j True)
|
|
||||||
|
|
||||||
-- Must be total, as element type is finite
|
|
||||||
checkRepeated : Colist (Pos h w, Direction) -> Bool
|
|
||||||
checkRepeated = assert_total $ go []
|
|
||||||
where
|
|
||||||
covering
|
|
||||||
go : Eq a => List a -> Colist a -> Bool
|
|
||||||
go _ [] = False
|
|
||||||
go seen (x :: xs) =
|
|
||||||
(x `elem` seen) || go (x :: seen) xs
|
|
||||||
|
|
||||||
covering
|
|
||||||
loopPos : {h, w : _} -> (Pos h w, Direction) -> Map h w
|
|
||||||
-> List (Pos h w)
|
|
||||||
loopPos g mp = do
|
|
||||||
i <- toList $ range {len=h}
|
|
||||||
j <- toList $ range {len=w}
|
|
||||||
let obs = (i,j)
|
|
||||||
guard (obs /= fst g && not (index obs mp)) -- must be empty space
|
|
||||||
let cols = getCollisions g $ insertObs obs mp
|
|
||||||
guard (collides obs cols) -- guard must collide with obstacle
|
|
||||||
guard (checkRepeated cols) -- must cause a loop
|
|
||||||
pure obs
|
|
||||||
where
|
|
||||||
-- Total in practice because routes that don't hit the new obstacle should
|
|
||||||
-- be finite, but we can't assume that from user input, so mark as covering
|
|
||||||
covering
|
|
||||||
collides : Pos h w -> Colist (Pos h w, Direction) -> Bool
|
|
||||||
collides _ [] = False
|
|
||||||
collides obs ((pos, _) :: cols) =
|
|
||||||
pos == obs || collides obs cols
|
|
||||||
|
|
||||||
--- SOLUTION
|
|
||||||
|
|
||||||
export covering
|
|
||||||
solution : String -> Maybe Nat
|
|
||||||
solution inp = do
|
|
||||||
(h ** w ** (mp, g)) <- parseInput inp
|
|
||||||
pure $ length $ loopPos g mp
|
|
|
@ -1,43 +0,0 @@
|
||||||
module Day7.Part1
|
|
||||||
|
|
||||||
import Data.List1
|
|
||||||
import Data.String
|
|
||||||
|
|
||||||
import Utils
|
|
||||||
|
|
||||||
%default total
|
|
||||||
|
|
||||||
--- TYPES
|
|
||||||
|
|
||||||
public export
|
|
||||||
Op : Type
|
|
||||||
Op = Nat -> Nat -> Nat
|
|
||||||
|
|
||||||
--- PARSING
|
|
||||||
|
|
||||||
parseLine : String -> Maybe (Nat, List1 Nat)
|
|
||||||
parseLine inp =
|
|
||||||
let (part1 ::: [part2]) = split (==':') inp
|
|
||||||
| _ => Nothing
|
|
||||||
in (,) <$> parseNat part1
|
|
||||||
<*> (traverse parseNat =<< fromList (words part2))
|
|
||||||
|
|
||||||
export
|
|
||||||
parseInput : String -> Maybe (List (Nat, List1 Nat))
|
|
||||||
parseInput = traverse parseLine . lines
|
|
||||||
|
|
||||||
--- DATA
|
|
||||||
|
|
||||||
export
|
|
||||||
search : List Op -> (tg, tot : Nat) -> List Nat -> Bool
|
|
||||||
search _ tg tot [] = tg == tot
|
|
||||||
search ops tg tot (x :: xs) =
|
|
||||||
-- heuristic: abandon if running total is larger than target
|
|
||||||
tot <= tg && any (\op => search ops tg (op tot x) xs) ops
|
|
||||||
|
|
||||||
--- SOLUTION
|
|
||||||
|
|
||||||
export
|
|
||||||
solution : String -> Maybe Nat
|
|
||||||
solution = map (sum . map fst . filter (\(tg,x:::xs) => search [(+),(*)] tg x xs))
|
|
||||||
. parseInput
|
|
|
@ -1,21 +0,0 @@
|
||||||
module Day7.Part2
|
|
||||||
|
|
||||||
import Data.List1
|
|
||||||
|
|
||||||
import Day7.Part1
|
|
||||||
import Utils
|
|
||||||
|
|
||||||
%default total
|
|
||||||
|
|
||||||
--- DATA
|
|
||||||
|
|
||||||
concat : Nat -> Nat -> Nat
|
|
||||||
concat x y = cast $ show x ++ show y
|
|
||||||
|
|
||||||
--- SOLUTION
|
|
||||||
|
|
||||||
export
|
|
||||||
solution : String -> Maybe Nat
|
|
||||||
solution = map (sum . map fst
|
|
||||||
. filter (\(tg,x:::xs) => search [(+),(*),concat] tg x xs))
|
|
||||||
. parseInput
|
|
|
@ -13,7 +13,7 @@ import AllDays
|
||||||
||| The latest problem that has been solved.
|
||| The latest problem that has been solved.
|
||||||
-- NOTE: UPDATE AFTER EACH SOLUTION
|
-- NOTE: UPDATE AFTER EACH SOLUTION
|
||||||
latest : Problem
|
latest : Problem
|
||||||
latest = Pr 7 Part2
|
latest = Pr 5 Part2
|
||||||
|
|
||||||
|
|
||||||
solMap : SortedMap Problem (String -> String)
|
solMap : SortedMap Problem (String -> String)
|
||||||
|
|
|
@ -3,7 +3,6 @@ module Utils
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.String
|
import Data.String
|
||||||
import Data.String.Parser
|
import Data.String.Parser
|
||||||
import Data.Vect
|
|
||||||
|
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
|
@ -29,25 +28,3 @@ scan p = until p *> p
|
||||||
export covering
|
export covering
|
||||||
scanWhile : Monad m => ParseT m a -> ParseT m b -> ParseT m b
|
scanWhile : Monad m => ParseT m a -> ParseT m b -> ParseT m b
|
||||||
scanWhile w p = many (lookahead w *> requireFailure p *> skip (satisfy (const True))) *> p
|
scanWhile w p = many (lookahead w *> requireFailure p *> skip (satisfy (const True))) *> p
|
||||||
|
|
||||||
|
|
||||||
public export
|
|
||||||
Grid : (h, w : Nat) -> Type -> Type
|
|
||||||
Grid h w a = Vect h (Vect w a)
|
|
||||||
|
|
||||||
public export
|
|
||||||
Pos : (h, w : Nat) -> Type
|
|
||||||
Pos h w = (Fin h, Fin w)
|
|
||||||
|
|
||||||
export
|
|
||||||
parseGrid : String -> Maybe (h ** w ** Grid h w Char)
|
|
||||||
parseGrid str =
|
|
||||||
let ls@(row :: _) = unpack <$> lines str
|
|
||||||
| [] => Just (0 ** 0 ** [])
|
|
||||||
width = length row
|
|
||||||
in map (\l => (length l ** width ** fromList l))
|
|
||||||
(traverse (toVect width) ls)
|
|
||||||
|
|
||||||
export
|
|
||||||
index : Pos h w -> Grid h w a -> a
|
|
||||||
index (i, j) = index j . index i
|
|
||||||
|
|
Loading…
Reference in a new issue