From 472dc28c3b56b0970a304d4921202953bffba437 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Fri, 10 Jan 2025 14:15:07 -0500 Subject: [PATCH] Year 2015 Day 6 Part 2 --- src/Years/Y2015/Day6.md | 96 ++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/src/Years/Y2015/Day6.md b/src/Years/Y2015/Day6.md index 114e2f5..a41508a 100644 --- a/src/Years/Y2015/Day6.md +++ b/src/Years/Y2015/Day6.md @@ -203,35 +203,77 @@ purify grid = traverse (traverse readIORef) grid ## Solver Functions +### Part 1 Variants + +```idris +namespace Part1 +``` Apply a given command to our `Grid` of `IORef`s. Use our `extractRange` function to extract all the `IORef`s in the grid cells touched by our `Range` and then traverse an appropriate mutating action over them. ```idris -applyCommand : Has IO fs => - {rows, cols : Nat} -> Grid rows cols (IORef Bool) -> Command rows cols -> Eff fs () -applyCommand xs (MkCmd action range) = - let cells = extractRange range xs - in case action of - On => Lazy.traverse_ (`writeIORef` True) cells - Off => Lazy.traverse_ (`writeIORef` False) cells - Toggle => Lazy.traverse_ (`modifyIORef` not) cells + applyCommand : Has IO fs => + {rows, cols : Nat} -> Grid rows cols (IORef Bool) -> Command rows cols -> Eff fs () + applyCommand xs (MkCmd action range) = + let cells = extractRange range xs + in case action of + On => Lazy.traverse_ (`writeIORef` True) cells + Off => Lazy.traverse_ (`writeIORef` False) cells + Toggle => Lazy.traverse_ (`modifyIORef` not) cells ``` Apply a list of commands to our `Grid` of `IORef`s, doing some debug logging along the way. ```idris -applyCommands : Has IO fs => Has Logger fs => - {rows, cols : Nat} -> Grid rows cols (IORef Bool) -> List (Command rows cols) - -> Eff fs () -applyCommands grid xs = applyCommands' 0 (length xs) xs - where - applyCommands' : (idx, len : Nat) -> List (Command rows cols) -> Eff fs () - applyCommands' idx len [] = pure () - applyCommands' idx len (x :: xs) = do - debug "Applying command \{show idx}/\{show len}: \{show x}" - applyCommand grid x - applyCommands' (S idx) len xs + export + applyCommands : Has IO fs => Has Logger fs => + {rows, cols : Nat} -> Grid rows cols (IORef Bool) -> List (Command rows cols) + -> Eff fs () + applyCommands grid xs = applyCommands' 0 (length xs) xs + where + applyCommands' : (idx, len : Nat) -> List (Command rows cols) -> Eff fs () + applyCommands' idx len [] = pure () + applyCommands' idx len (x :: xs) = do + debug "Part 1 - Applying command \{show idx}/\{show len}: \{show x}" + applyCommand grid x + applyCommands' (S idx) len xs +``` + +### Part 2 Variants + +```idris +namespace Part2 +``` + +Much the same as above, but instead we apply the part 2 rules to a `Grid` of `Nat`. + +```idris + applyCommand : Has IO fs => + {rows, cols : Nat} -> Grid rows cols (IORef Nat) -> Command rows cols -> Eff fs () + applyCommand xs (MkCmd action range) = + let cells = extractRange range xs + in case action of + On => Lazy.traverse_ (`modifyIORef` (+ 1)) cells + Off => Lazy.traverse_ (`modifyIORef` (`minus` 1)) cells + Toggle => Lazy.traverse_ (`modifyIORef` (+ 2)) cells +``` + +Identical to above, except for using our part 2 `applyCommand`. We can use the same name here because we have the two variants behind namespaces and Idris can disambiguate via the types. + +```idris + export + applyCommands : Has IO fs => Has Logger fs => + {rows, cols : Nat} -> Grid rows cols (IORef Nat) -> List (Command rows cols) + -> Eff fs () + applyCommands grid xs = applyCommands' 0 (length xs) xs + where + applyCommands' : (idx, len : Nat) -> List (Command rows cols) -> Eff fs () + applyCommands' idx len [] = pure () + applyCommands' idx len (x :: xs) = do + debug "Part 2 - Applying command \{show idx}/\{show len}: \{show x}" + applyCommand grid x + applyCommands' (S idx) len xs ``` ## Day functions @@ -254,8 +296,22 @@ part1 = do pure $ (lights_on, commands) ``` +### Part 2 + +This time, use an initial `Grid` with all brightness values at 0, apply our list of preparsed commands using our part 2 `applyCommands` function (selected via the type signature), and then add up the brightnesses. + +```idris +part2 : List (Command 999 999) -> Eff (PartEff String) Nat +part2 commands = do + grid <- ioGrid 999 999 (the Nat 0) + applyCommands grid commands + grid <- purify grid + let brightness = sum . map sum $ grid + pure brightness +``` +