day 24: no more manual :)
Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
@@ -31,7 +31,7 @@
|
|||||||
let
|
let
|
||||||
name = n: "day${(if n < 10 then "0" else "" ) + toString n}";
|
name = n: "day${(if n < 10 then "0" else "" ) + toString n}";
|
||||||
in
|
in
|
||||||
with pkgs.lib; genAttrs (map name (range 1 22))
|
with pkgs.lib; genAttrs (map name (range 1 25))
|
||||||
(n: {
|
(n: {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${self'.packages.aoc2024}/bin/${n}";
|
program = "${self'.packages.aoc2024}/bin/${n}";
|
||||||
|
60
src/Day24.hs
60
src/Day24.hs
@@ -5,12 +5,12 @@ import Control.Arrow (Arrow (second))
|
|||||||
import Data.Bits (shiftL, xor, (.|.))
|
import Data.Bits (shiftL, xor, (.|.))
|
||||||
import Data.Char (digitToInt)
|
import Data.Char (digitToInt)
|
||||||
import Data.Either (rights)
|
import Data.Either (rights)
|
||||||
import Data.List (foldl', mapAccumL)
|
import Data.List (foldl', mapAccumL, sort)
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Text.Parsec (char, digit, letter, many1, newline, parse, sepEndBy1, string, try, (<|>))
|
import Text.Parsec (char, digit, letter, many1, newline, parse, sepEndBy1, string, try, (<|>))
|
||||||
import Text.Parsec.String (Parser)
|
import Text.Parsec.String (Parser)
|
||||||
|
|
||||||
type Gate = Bool -> Bool -> Bool
|
data Gate = And | Or | Xor deriving (Eq, Enum)
|
||||||
|
|
||||||
type Connection = (String, Gate, String)
|
type Connection = (String, Gate, String)
|
||||||
|
|
||||||
@@ -27,9 +27,9 @@ parseConnection = do
|
|||||||
a <- many1 (letter <|> digit)
|
a <- many1 (letter <|> digit)
|
||||||
char ' '
|
char ' '
|
||||||
op <-
|
op <-
|
||||||
(try (string "AND") >> return (&&))
|
(try (string "AND") >> return And)
|
||||||
<|> (try (string "OR") >> return (||))
|
<|> (try (string "OR") >> return Or)
|
||||||
<|> (try (string "XOR") >> return xor)
|
<|> (try (string "XOR") >> return Xor)
|
||||||
char ' '
|
char ' '
|
||||||
b <- many1 (letter <|> digit)
|
b <- many1 (letter <|> digit)
|
||||||
string " -> "
|
string " -> "
|
||||||
@@ -51,7 +51,8 @@ simulate s line = case s M.! line of
|
|||||||
Left (lineA, op, lineB) ->
|
Left (lineA, op, lineB) ->
|
||||||
let (s', a) = simulate s lineA
|
let (s', a) = simulate s lineA
|
||||||
(s'', b) = simulate s' lineB
|
(s'', b) = simulate s' lineB
|
||||||
value = a `op` b
|
operator = [(&&), (||), xor] !! fromEnum op
|
||||||
|
value = a `operator` b
|
||||||
in (M.insert line (Right value) s'', value)
|
in (M.insert line (Right value) s'', value)
|
||||||
|
|
||||||
simulateAll :: States -> States
|
simulateAll :: States -> States
|
||||||
@@ -66,6 +67,50 @@ binToDec = foldl' (\num b -> num `shiftL` 1 .|. fromEnum b) 0
|
|||||||
part1 :: States -> Int
|
part1 :: States -> Int
|
||||||
part1 = binToDec . wires 'z' . simulateAll
|
part1 = binToDec . wires 'z' . simulateAll
|
||||||
|
|
||||||
|
fullAdder :: States -> String -> Maybe [String]
|
||||||
|
fullAdder states num =
|
||||||
|
let z = 'z' : num
|
||||||
|
x = 'x' : num
|
||||||
|
y = 'y' : num
|
||||||
|
Left (a, fn1, b) = states M.! z
|
||||||
|
Left (_, fn2, _) = states M.! a
|
||||||
|
Left (_, fn3, _) = states M.! b
|
||||||
|
xor1 = rLookup (x, Xor, y)
|
||||||
|
xor2 = rLookupP (xor1, Xor)
|
||||||
|
in case fn1 of
|
||||||
|
Xor -> case (fn2, fn3) of
|
||||||
|
(And, Or) -> Just [a, xor1]
|
||||||
|
(Or, And) -> Just [b, xor1]
|
||||||
|
_ -> Nothing
|
||||||
|
_ -> Just [z, xor2]
|
||||||
|
where
|
||||||
|
rLookup :: Connection -> String
|
||||||
|
rLookup (a, op, b) =
|
||||||
|
head
|
||||||
|
[ s
|
||||||
|
| (s, c) <- M.assocs states,
|
||||||
|
c `elem` [Left (a, op, b), Left (b, op, a)]
|
||||||
|
]
|
||||||
|
rLookupP :: (String, Gate) -> String
|
||||||
|
rLookupP (a, g) =
|
||||||
|
head
|
||||||
|
[ s
|
||||||
|
| (s, c) <- M.assocs states,
|
||||||
|
Left (x, op, y) <- [c],
|
||||||
|
(a, g) `elem` [(x, op), (y, op)]
|
||||||
|
]
|
||||||
|
|
||||||
|
part2 :: States -> [String]
|
||||||
|
part2 states =
|
||||||
|
let zLength = length (wires 'x' states) + 1
|
||||||
|
in sort
|
||||||
|
[ line
|
||||||
|
| x <- [1 .. zLength - 2],
|
||||||
|
let num = if x < 10 then '0' : show x else show x,
|
||||||
|
Just lines <- [fullAdder states num],
|
||||||
|
line <- lines
|
||||||
|
]
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main =
|
main =
|
||||||
do
|
do
|
||||||
@@ -73,5 +118,4 @@ main =
|
|||||||
let states = A.extract $ parse parseInput "" raw
|
let states = A.extract $ parse parseInput "" raw
|
||||||
|
|
||||||
putStr "Part 1: " >> print (part1 states)
|
putStr "Part 1: " >> print (part1 states)
|
||||||
-- TODO: write code
|
putStr "Part 2: " >> print (part2 states)
|
||||||
putStrLn "Part 2: Done by hand :')"
|
|
||||||
|
Reference in New Issue
Block a user