day24
This commit is contained in:
3
TODO.md
3
TODO.md
@@ -7,7 +7,7 @@ More comments in code! This is getting big enough that I need to re-find my bear
|
|||||||
- [x] Move on to next decl in case of error
|
- [x] Move on to next decl in case of error
|
||||||
- [x] for parse error, seek to col 0 token and process next decl
|
- [x] for parse error, seek to col 0 token and process next decl
|
||||||
- [ ] record initialization sugar, e.g. `{ x := 1, y := 2 }`
|
- [ ] record initialization sugar, e.g. `{ x := 1, y := 2 }`
|
||||||
- [ ] record update sugar
|
- [ ] record update sugar, syntax TBD
|
||||||
- [ ] Change `Ord` to be more like Idris - LT / EQ / GT (and entail equality)
|
- [ ] Change `Ord` to be more like Idris - LT / EQ / GT (and entail equality)
|
||||||
- [ ] Keep a `compare` function on `SortedMap` (like lean)
|
- [ ] Keep a `compare` function on `SortedMap` (like lean)
|
||||||
- [x] keymap for monaco
|
- [x] keymap for monaco
|
||||||
@@ -41,7 +41,6 @@ More comments in code! This is getting big enough that I need to re-find my bear
|
|||||||
- [x] Fix string printing to be js instead of weird Idris strings
|
- [x] Fix string printing to be js instead of weird Idris strings
|
||||||
- [x] make $ special
|
- [x] make $ special
|
||||||
- Makes inference easier, cleaner output, and allows `foo $ \ x => ...`
|
- Makes inference easier, cleaner output, and allows `foo $ \ x => ...`
|
||||||
- remove hack from Elab.infer
|
|
||||||
- [ ] `$` no longer works inside ≡⟨ ⟩ sort out how to support both that and `$ \ x => ...` (or don't bother)
|
- [ ] `$` no longer works inside ≡⟨ ⟩ sort out how to support both that and `$ \ x => ...` (or don't bother)
|
||||||
- We'd either need to blacklist all non-initial mixfix bits at the appropriate spots or always pass around a terminating token.
|
- We'd either need to blacklist all non-initial mixfix bits at the appropriate spots or always pass around a terminating token.
|
||||||
- [ ] **Translate newt to newt**
|
- [ ] **Translate newt to newt**
|
||||||
|
|||||||
206
aoc2024/Day24.newt
Normal file
206
aoc2024/Day24.newt
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
module Day24
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
import Node
|
||||||
|
import Aoc
|
||||||
|
import SortedMap
|
||||||
|
|
||||||
|
data Value : U where
|
||||||
|
One Zero None : Value
|
||||||
|
|
||||||
|
data Op : U where
|
||||||
|
Xor And Or : Op
|
||||||
|
|
||||||
|
instance Eq Op where
|
||||||
|
Xor == Xor = True
|
||||||
|
And == And = True
|
||||||
|
Or == Or = True
|
||||||
|
_ == _ = False
|
||||||
|
|
||||||
|
record Gate where
|
||||||
|
constructor GT
|
||||||
|
in1 : String
|
||||||
|
in2 : String
|
||||||
|
op : Op
|
||||||
|
out : String
|
||||||
|
|
||||||
|
Wire : U
|
||||||
|
Wire = String × Int
|
||||||
|
|
||||||
|
parseFile : String → Either String (List Wire × List Gate)
|
||||||
|
parseFile text = do
|
||||||
|
let (a :: b :: Nil) = split (trim text) "\n\n" | _ => Left "too many parts"
|
||||||
|
wires <- traverse parseWire $ lines a
|
||||||
|
gates <- traverse parseGate $ lines b
|
||||||
|
Right (wires, gates)
|
||||||
|
|
||||||
|
where
|
||||||
|
parseWire : String → Either String (String × Int)
|
||||||
|
parseWire s = let (a :: b :: Nil) = split s ": " | _ => Left $ "bad wire: " ++ s in
|
||||||
|
Right (a, stringToInt b)
|
||||||
|
|
||||||
|
getOp : String → Either String Op
|
||||||
|
getOp "XOR" = Right Xor
|
||||||
|
getOp "AND" = Right And
|
||||||
|
getOp "OR" = Right Or
|
||||||
|
getOp op = Left $ "bad op " ++ op
|
||||||
|
|
||||||
|
parseGate : String → Either String Gate
|
||||||
|
parseGate s = do
|
||||||
|
let (in1 :: op :: in2 :: _ :: out :: Nil) = split s " " | _ => Left $ "bad gate: " ++ s
|
||||||
|
op <- getOp op
|
||||||
|
Right $ GT in1 in2 op out
|
||||||
|
|
||||||
|
|
||||||
|
State : U
|
||||||
|
State = SortedMap String Int
|
||||||
|
|
||||||
|
|
||||||
|
mkFire : List Gate → SortedMap String (List String)
|
||||||
|
mkFire gates = go EmptyMap gates
|
||||||
|
where
|
||||||
|
go : SortedMap String (List String) → List Gate → SortedMap String (List String)
|
||||||
|
go acc Nil = acc
|
||||||
|
go acc (g :: gs) =
|
||||||
|
let acc = updateMap (in1 g) (out g :: fromMaybe Nil (snd <$> lookupMap (in1 g) acc)) acc in
|
||||||
|
let acc = updateMap (in2 g) (out g :: fromMaybe Nil (snd <$> lookupMap (in2 g) acc)) acc in
|
||||||
|
go acc gs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
exec : SortedMap String Gate → SortedMap String (List String) → List String → State → State
|
||||||
|
exec gateMap fireMap todo state = go todo state
|
||||||
|
where
|
||||||
|
combine : Op → Int → Int → Int
|
||||||
|
combine And 1 x = x
|
||||||
|
combine Xor 1 1 = 0
|
||||||
|
combine Xor 1 0 = 1
|
||||||
|
combine Xor 0 1 = 1
|
||||||
|
combine Or 1 _ = 1
|
||||||
|
combine Or _ 1 = 1
|
||||||
|
combine _ _ _ = 0
|
||||||
|
|
||||||
|
go : List String → State → State
|
||||||
|
go Nil st = st
|
||||||
|
go (x :: xs) st = case lookupMap x st of
|
||||||
|
-- already done
|
||||||
|
Just _ => go xs st
|
||||||
|
Nothing => case lookupMap' x gateMap of
|
||||||
|
Nothing => go xs st
|
||||||
|
Just gate => case (lookupMap' (in1 gate) st, lookupMap' (in2 gate) st) of
|
||||||
|
(Just x, Just y) =>
|
||||||
|
let v = combine (op gate) x y
|
||||||
|
st = updateMap (out gate) v st
|
||||||
|
foo = fromMaybe Nil $ lookupMap' (out gate) fireMap
|
||||||
|
xs' = foo ++ xs
|
||||||
|
in go xs' st
|
||||||
|
_ => go xs st
|
||||||
|
|
||||||
|
bitsToInt : Int → List Int → Int
|
||||||
|
bitsToInt _ Nil = 0
|
||||||
|
bitsToInt m (x :: xs) = m * x + bitsToInt (2 * m) xs
|
||||||
|
|
||||||
|
|
||||||
|
-- so I can find the lowest bit that is wrong
|
||||||
|
-- or trace out the circuit?
|
||||||
|
|
||||||
|
infixl 5 _%_
|
||||||
|
pfunc _%_ : Int → Int → Int := `(x,y) => x % y`
|
||||||
|
|
||||||
|
label : Char -> Int -> String
|
||||||
|
label c bit = pack $ c :: chr (bit / 10 + 48) :: chr ((bit % 10) + 48) :: Nil
|
||||||
|
|
||||||
|
range : Int → Int → List Int
|
||||||
|
range a b = if a < b then a :: range (a + 1) b else Nil
|
||||||
|
|
||||||
|
swapPins : String → String → Gate → Gate
|
||||||
|
swapPins a g (GT i1 i2 op out) =
|
||||||
|
if out == a then GT i1 i2 op g
|
||||||
|
else if out == g then GT i1 i2 op a
|
||||||
|
else GT i1 i2 op out
|
||||||
|
|
||||||
|
fail : ∀ a. String -> a
|
||||||
|
fail msg = let x = trace "FAIL" msg in ?
|
||||||
|
|
||||||
|
check : List Gate → List Int → String → Either (String × String) Unit
|
||||||
|
check gates Nil carry = Right MkUnit
|
||||||
|
check gates (bit :: bits) carry = do
|
||||||
|
let xl = label 'x' bit
|
||||||
|
let yl = label 'x' bit
|
||||||
|
let (Just a1) = matchIn xl And | _ => fail $ "no a1 " ++ show bit
|
||||||
|
let (Just x1) = matchIn xl Xor | _ => fail $ "no x1 " ++ show bit
|
||||||
|
-- just peel of the carry for bit0
|
||||||
|
let (False) = bit == 0 | _ => check gates bits (out a1)
|
||||||
|
|
||||||
|
let (Just x2) = matchIn carry Xor
|
||||||
|
| _ => do
|
||||||
|
-- carry is bad
|
||||||
|
let (Just x2) = matchOut (label 'z' bit) Xor | _ => fail $ "no x2 for " ++ show bit
|
||||||
|
if in1 x2 == out x1 then Left (in2 x2, carry) else Left (in1 x2, carry)
|
||||||
|
let (Just a2) = matchIn carry And | _ => fail $ "no a2 " ++ show bit
|
||||||
|
checkPins x2 carry (out x1)
|
||||||
|
checkPins a2 carry (out x1)
|
||||||
|
|
||||||
|
case (matchIn (out a1) Or, matchIn (out a2) Or) of
|
||||||
|
(Nothing, Nothing) => fail "todo2"
|
||||||
|
(Just g, Nothing) => checkPins g (out a1) (out a2)
|
||||||
|
(Nothing, Just g) => checkPins g (out a1) (out a2)
|
||||||
|
(Just g, Just g') =>
|
||||||
|
if out g == out g'
|
||||||
|
then check gates bits (out g)
|
||||||
|
else fail "todo"
|
||||||
|
|
||||||
|
where
|
||||||
|
checkPins : Gate → String → String → Either (String × String) Unit
|
||||||
|
checkPins g a b =
|
||||||
|
if a == in1 g && b == in2 g then pure MkUnit
|
||||||
|
else if a == in2 g && b == in1 g then pure MkUnit
|
||||||
|
else if a == in1 g then Left (b, in2 g)
|
||||||
|
else if a == in2 g then Left (b, in1 g)
|
||||||
|
else if b == in1 g then Left (a, in2 g)
|
||||||
|
else Left (a, in1 g)
|
||||||
|
|
||||||
|
matchOut : String -> Op -> Maybe Gate
|
||||||
|
matchOut l o = find (\ g => out g == l && op g == o) gates
|
||||||
|
|
||||||
|
matchIn : String -> Op -> Maybe Gate
|
||||||
|
matchIn l o = find (\ g => (in1 g == l || in2 g == l) && op g == o) gates
|
||||||
|
|
||||||
|
trampoline : List Gate → List String → IO (List String)
|
||||||
|
trampoline gates acc = do
|
||||||
|
case check gates (range 0 44) "" of
|
||||||
|
Right _ => pure acc
|
||||||
|
Left (a,b) => do
|
||||||
|
putStrLn $ "SWAP " ++ a ++ " and " ++ b
|
||||||
|
trampoline (map (swapPins a b) gates) (a :: b :: acc)
|
||||||
|
|
||||||
|
joinBy : String → List String → String
|
||||||
|
joinBy _ Nil = ""
|
||||||
|
joinBy _ (x :: Nil) = x
|
||||||
|
joinBy s (x :: y :: xs) = joinBy s ((x ++ s ++ y) :: xs)
|
||||||
|
|
||||||
|
run : String -> IO Unit
|
||||||
|
run fn = do
|
||||||
|
putStrLn fn
|
||||||
|
text <- readFile fn
|
||||||
|
putStrLn text
|
||||||
|
let (Right (wires, gates)) = parseFile text | Left msg => putStrLn $ "fail: " ++ msg
|
||||||
|
let state = foldMap const EmptyMap wires
|
||||||
|
let gateMap = foldMap const EmptyMap $ map (\ gate => (out gate, gate)) gates
|
||||||
|
let fireMap = mkFire gates
|
||||||
|
let init = join $ map snd $ mapMaybe (\ wire => lookupMap wire fireMap) $ map fst wires
|
||||||
|
let state' = exec gateMap fireMap init state
|
||||||
|
let bits = map snd $ filter (_<_ "z" ∘ fst) $ toList state'
|
||||||
|
let p1 = bitsToInt 1 bits
|
||||||
|
putStrLn $ "part1 " ++ show p1
|
||||||
|
|
||||||
|
stuff <- trampoline gates Nil
|
||||||
|
putStrLn $ "part2 " ++ (joinBy "," $ qsort _<_ stuff)
|
||||||
|
putStrLn ""
|
||||||
|
|
||||||
|
main : IO Unit
|
||||||
|
main = do
|
||||||
|
-- run "aoc2024/day24/eg.txt"
|
||||||
|
-- run "aoc2024/day24/eg2.txt"
|
||||||
|
-- this is the only adder circuit
|
||||||
|
run "aoc2024/day24/input.txt"
|
||||||
@@ -173,6 +173,11 @@ lookupMap : ∀ k v. {{Ord k}} {{Eq k}} -> k -> SortedMap k v -> Maybe (k × v)
|
|||||||
lookupMap k EmptyMap = Nothing
|
lookupMap k EmptyMap = Nothing
|
||||||
lookupMap k (MapOf map) = lookupT23 k map
|
lookupMap k (MapOf map) = lookupT23 k map
|
||||||
|
|
||||||
|
lookupMap' : ∀ k v. {{Ord k}} {{Eq k}} -> k -> SortedMap k v -> Maybe v
|
||||||
|
lookupMap' k EmptyMap = Nothing
|
||||||
|
lookupMap' k (MapOf map) = snd <$> lookupT23 k map
|
||||||
|
|
||||||
|
|
||||||
updateMap : ∀ k v. {{Ord k}} {{Eq k}} -> k -> v -> SortedMap k v -> SortedMap k v
|
updateMap : ∀ k v. {{Ord k}} {{Eq k}} -> k -> v -> SortedMap k v -> SortedMap k v
|
||||||
updateMap k v EmptyMap = MapOf $ Leaf k v
|
updateMap k v EmptyMap = MapOf $ Leaf k v
|
||||||
updateMap k v (MapOf map) = case insertT23 k v map of
|
updateMap k v (MapOf map) = case insertT23 k v map of
|
||||||
|
|||||||
10
aoc2024/day24/eg.txt
Normal file
10
aoc2024/day24/eg.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
x00: 1
|
||||||
|
x01: 1
|
||||||
|
x02: 1
|
||||||
|
y00: 0
|
||||||
|
y01: 1
|
||||||
|
y02: 0
|
||||||
|
|
||||||
|
x00 AND y00 -> z00
|
||||||
|
x01 XOR y01 -> z01
|
||||||
|
x02 OR y02 -> z02
|
||||||
47
aoc2024/day24/eg2.txt
Normal file
47
aoc2024/day24/eg2.txt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
x00: 1
|
||||||
|
x01: 0
|
||||||
|
x02: 1
|
||||||
|
x03: 1
|
||||||
|
x04: 0
|
||||||
|
y00: 1
|
||||||
|
y01: 1
|
||||||
|
y02: 1
|
||||||
|
y03: 1
|
||||||
|
y04: 1
|
||||||
|
|
||||||
|
ntg XOR fgs -> mjb
|
||||||
|
y02 OR x01 -> tnw
|
||||||
|
kwq OR kpj -> z05
|
||||||
|
x00 OR x03 -> fst
|
||||||
|
tgd XOR rvg -> z01
|
||||||
|
vdt OR tnw -> bfw
|
||||||
|
bfw AND frj -> z10
|
||||||
|
ffh OR nrd -> bqk
|
||||||
|
y00 AND y03 -> djm
|
||||||
|
y03 OR y00 -> psh
|
||||||
|
bqk OR frj -> z08
|
||||||
|
tnw OR fst -> frj
|
||||||
|
gnj AND tgd -> z11
|
||||||
|
bfw XOR mjb -> z00
|
||||||
|
x03 OR x00 -> vdt
|
||||||
|
gnj AND wpb -> z02
|
||||||
|
x04 AND y00 -> kjc
|
||||||
|
djm OR pbm -> qhw
|
||||||
|
nrd AND vdt -> hwm
|
||||||
|
kjc AND fst -> rvg
|
||||||
|
y04 OR y02 -> fgs
|
||||||
|
y01 AND x02 -> pbm
|
||||||
|
ntg OR kjc -> kwq
|
||||||
|
psh XOR fgs -> tgd
|
||||||
|
qhw XOR tgd -> z09
|
||||||
|
pbm OR djm -> kpj
|
||||||
|
x03 XOR y03 -> ffh
|
||||||
|
x00 XOR y04 -> ntg
|
||||||
|
bfw OR bqk -> z06
|
||||||
|
nrd XOR fgs -> wpb
|
||||||
|
frj XOR qhw -> z04
|
||||||
|
bqk OR frj -> z07
|
||||||
|
y03 OR x01 -> nrd
|
||||||
|
hwm AND bqk -> z03
|
||||||
|
tgd XOR rvg -> z12
|
||||||
|
tnw OR pbm -> gnj
|
||||||
19
aoc2024/day24/eg3.txt
Normal file
19
aoc2024/day24/eg3.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
x00: 0
|
||||||
|
x01: 1
|
||||||
|
x02: 0
|
||||||
|
x03: 1
|
||||||
|
x04: 0
|
||||||
|
x05: 1
|
||||||
|
y00: 0
|
||||||
|
y01: 0
|
||||||
|
y02: 1
|
||||||
|
y03: 1
|
||||||
|
y04: 0
|
||||||
|
y05: 1
|
||||||
|
|
||||||
|
x00 AND y00 -> z05
|
||||||
|
x01 AND y01 -> z02
|
||||||
|
x02 AND y02 -> z01
|
||||||
|
x03 AND y03 -> z03
|
||||||
|
x04 AND y04 -> z04
|
||||||
|
x05 AND y05 -> z00
|
||||||
1
playground/samples/aoc2024/Day24.newt
Symbolic link
1
playground/samples/aoc2024/Day24.newt
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../../aoc2024/Day24.newt
|
||||||
1
playground/samples/aoc2024/day24
Symbolic link
1
playground/samples/aoc2024/day24
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../../aoc2024/day24
|
||||||
Reference in New Issue
Block a user