day 24: no more manual :)
Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
let
|
||||
name = n: "day${(if n < 10 then "0" else "" ) + toString n}";
|
||||
in
|
||||
with pkgs.lib; genAttrs (map name (range 1 22))
|
||||
with pkgs.lib; genAttrs (map name (range 1 25))
|
||||
(n: {
|
||||
type = "app";
|
||||
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.Char (digitToInt)
|
||||
import Data.Either (rights)
|
||||
import Data.List (foldl', mapAccumL)
|
||||
import Data.List (foldl', mapAccumL, sort)
|
||||
import qualified Data.Map as M
|
||||
import Text.Parsec (char, digit, letter, many1, newline, parse, sepEndBy1, string, try, (<|>))
|
||||
import Text.Parsec.String (Parser)
|
||||
|
||||
type Gate = Bool -> Bool -> Bool
|
||||
data Gate = And | Or | Xor deriving (Eq, Enum)
|
||||
|
||||
type Connection = (String, Gate, String)
|
||||
|
||||
@@ -27,9 +27,9 @@ parseConnection = do
|
||||
a <- many1 (letter <|> digit)
|
||||
char ' '
|
||||
op <-
|
||||
(try (string "AND") >> return (&&))
|
||||
<|> (try (string "OR") >> return (||))
|
||||
<|> (try (string "XOR") >> return xor)
|
||||
(try (string "AND") >> return And)
|
||||
<|> (try (string "OR") >> return Or)
|
||||
<|> (try (string "XOR") >> return Xor)
|
||||
char ' '
|
||||
b <- many1 (letter <|> digit)
|
||||
string " -> "
|
||||
@@ -51,7 +51,8 @@ simulate s line = case s M.! line of
|
||||
Left (lineA, op, lineB) ->
|
||||
let (s', a) = simulate s lineA
|
||||
(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)
|
||||
|
||||
simulateAll :: States -> States
|
||||
@@ -66,6 +67,50 @@ binToDec = foldl' (\num b -> num `shiftL` 1 .|. fromEnum b) 0
|
||||
part1 :: States -> Int
|
||||
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 =
|
||||
do
|
||||
@@ -73,5 +118,4 @@ main =
|
||||
let states = A.extract $ parse parseInput "" raw
|
||||
|
||||
putStr "Part 1: " >> print (part1 states)
|
||||
-- TODO: write code
|
||||
putStrLn "Part 2: Done by hand :')"
|
||||
putStr "Part 2: " >> print (part2 states)
|
||||
|
Reference in New Issue
Block a user