diff --git a/Aoc2024/Day03/Main.lean b/Aoc2024/Day03/Main.lean index 2d03a06..1c4b75c 100644 --- a/Aoc2024/Day03/Main.lean +++ b/Aoc2024/Day03/Main.lean @@ -5,7 +5,7 @@ def solve (name: String) (inputPath: String) : IO Unit := do IO.println name let input <- IO.FS.readFile inputPath IO.println s!"Part 1: {solvePart1 input}" - -- IO.println s!"Part 2: {<- parseAndSolvePart2 input}" + IO.println s!"Part 2: {solvePart2 input}" def main : IO Unit := do IO.println "Day 03" diff --git a/Aoc2024/Day03/Solve.lean b/Aoc2024/Day03/Solve.lean index 0118599..99434d0 100644 --- a/Aoc2024/Day03/Solve.lean +++ b/Aoc2024/Day03/Solve.lean @@ -6,40 +6,58 @@ open Regex (Match Captures) inductive Instruction where | mul (n m : Nat) : Instruction - -- | do : Instruction - -- | dont: Instruction + | do : Instruction + | dont: Instruction deriving instance BEq, Hashable, Repr for Instruction -def mulRegex: Regex := regex% r"mul\((\d+),(\d+)\)" +def instructionRegex: Regex := regex% r"mul\((\d+),(\d+)\)|do\(\)|don't\(\)" def matchToNat (m : Match) : Option Nat := m.toNat? def optMatchToNat (m : Option Match) : Option Nat := m >>= matchToNat -def matchesToNatPair (ms : Array (Option Match)): Option Instruction := +def matchesToInstruction (ms : Array (Option Match)): Option Instruction := match ms.toList with | [some m1, some m2] => Instruction.mul <$> matchToNat m1 <*> matchToNat m2 | _ => none -def capturesToNatPair (captures: Captures) : Option Instruction := - matchesToNatPair captures.groups +def capturesToInstruction (captures: Captures) : Option Instruction := + if captures.fullMatch == "do()" then some Instruction.do + else if captures.fullMatch == "don't()" then some Instruction.dont + else matchesToInstruction captures.groups -def findMatches (s : String) : List Instruction := - Regex.all_captures s mulRegex |>.toList |>.bind (fun captures => captures |> capturesToNatPair |> Option.toList) +def findInstructions (s : String) : List Instruction := + Regex.all_captures s instructionRegex |>.toList |>.bind (fun captures => captures |> capturesToInstruction |> Option.toList) -#guard findMatches "mul(1,2) mul(3,4)" == [Instruction.mul 1 2, Instruction.mul 3 4] +#guard findInstructions "mul(1,2) mul(3,4)" == [Instruction.mul 1 2, Instruction.mul 3 4] +#guard findInstructions "do()" == [Instruction.do] +#guard findInstructions "don't()" == [Instruction.dont] -def solvePart1 (s : String) : Int := findMatches s |>.sumBy (fun +def solvePart1 (s : String) : Int := findInstructions s |>.sumBy (fun | Instruction.mul n m => n * m + | _ => 1 ) #guard solvePart1 exampleInput = 161 -private def solvePart2 (things : List Int) : Int := sorry +private def filterInstructions (enabled : Bool) : List Instruction -> List Instruction + | List.nil => [] + | List.cons (Instruction.mul m n) rest => + if enabled then List.cons (Instruction.mul m n) (filterInstructions enabled rest) + else filterInstructions enabled rest + | List.cons Instruction.do rest => filterInstructions true rest + | List.cons Instruction.dont rest => filterInstructions false rest -def instrRegex := regex% r"mul\((\d+),(\d+)\)|do()\)" -#eval Regex.all_captures "mul(1,2) do()" instrRegex +#eval findInstructions "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))" |> filterInstructions true + +def solvePart2 (s : String) : Int := s |> findInstructions |> filterInstructions true |> List.sumBy (fun + | Instruction.mul n m => n * m + | _ => 1 +) + +#eval solvePart2 "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))" + +#guard solvePart2 "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))" == 48 -def parseAndSolvePart2 (s : String): Except String Int := parseThings s |>.map solvePart2 -- #guard parseAndSolvePart2 exampleInput == Except.ok 4