my solutions to advent of code
aoc advent-of-code
at main 3.0 kB view raw
1import gleam/dict.{type Dict} 2import gleam/int.{to_string} 3import gleam/io.{println} 4import gleam/list.{fold} 5import gleam/result.{unwrap} 6import gleam/string.{split, trim} 7import simplifile.{read} 8 9pub type Circuit = 10 Dict(String, Operation) 11 12pub type CircuitCache = 13 Dict(String, Int) 14 15pub type Operation { 16 Set(n: String) 17 Not(var: String) 18 And(var1: String, var2: String) 19 Or(var1: String, var2: String) 20 Rshift(var1: String, var2: String) 21 Lshift(var1: String, var2: String) 22} 23 24pub type GetRes { 25 GetRes(value: Int, cache: CircuitCache) 26} 27 28pub fn get_circuit_var( 29 circuit: Circuit, 30 name: String, 31 cache: CircuitCache, 32) -> GetRes { 33 let get = fn(name, cache) { get_circuit_var(circuit, name, cache) } 34 35 let parsed_name = int.base_parse(name, 10) 36 case result.is_ok(parsed_name) { 37 True -> GetRes(parsed_name |> unwrap(0), cache) 38 False -> { 39 case dict.get(cache, name) { 40 Ok(value) -> GetRes(value, cache) 41 Error(Nil) -> { 42 // will crash if it gets bad data 43 let assert Ok(op) = dict.get(circuit, name) 44 45 let #(value1, value2, cache) = case op { 46 Not(v) | Set(v) -> { 47 let GetRes(value, cache) = get(v, cache) 48 #(value, 0, cache) 49 } 50 And(v1, v2) | Or(v1, v2) | Rshift(v1, v2) | Lshift(v1, v2) -> { 51 let GetRes(value1, cache) = get(v1, cache) 52 let GetRes(value2, cache) = get(v2, cache) 53 #(value1, value2, cache) 54 } 55 } 56 57 let res = case op { 58 Set(_) -> value1 59 Not(_) -> int.bitwise_not(value1) 60 And(_, _) -> int.bitwise_and(value1, value2) 61 Or(_, _) -> int.bitwise_or(value1, value2) 62 Rshift(_, _) -> int.bitwise_shift_right(value1, value2) 63 Lshift(_, _) -> int.bitwise_shift_left(value1, value2) 64 } 65 GetRes(res, dict.insert(cache, name, res)) 66 } 67 } 68 } 69 } 70} 71 72pub fn main() { 73 let input: Circuit = 74 read(from: "../input.txt") 75 |> unwrap("") 76 |> trim() 77 |> split("\n") 78 |> fold(dict.new(), fn(circ, v) { 79 case split(v, " ") { 80 ["NOT", var, "->", target] -> dict.insert(circ, target, Not(var)) 81 [var1, "AND", var2, "->", target] -> 82 dict.insert(circ, target, And(var1, var2)) 83 [var1, "OR", var2, "->", target] -> 84 dict.insert(circ, target, Or(var1, var2)) 85 [var1, "RSHIFT", var2, "->", target] -> 86 dict.insert(circ, target, Rshift(var1, var2)) 87 [var1, "LSHIFT", var2, "->", target] -> 88 dict.insert(circ, target, Lshift(var1, var2)) 89 [v, "->", target] -> dict.insert(circ, target, Set(v)) 90 91 _ -> circ 92 } 93 }) 94 95 let result_part_1 = get_circuit_var(input, "a", dict.new()).value 96 println(result_part_1 |> to_string) 97 98 let input_part_2 = dict.insert(input, "b", Set(int.to_string(result_part_1))) 99 let result_part_2 = get_circuit_var(input_part_2, "a", dict.new()).value 100 println(result_part_2 |> to_string) 101}