Skip to content

Commit 5bcdf08

Browse files
committed
finished day 24 part 1
1 parent 1fab2f8 commit 5bcdf08

File tree

4 files changed

+218
-2
lines changed

4 files changed

+218
-2
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Advent of Code 2024
22

33
[![Tests](https://github.com/devries/advent_of_code_2024/actions/workflows/test.yml/badge.svg)](https://github.com/devries/advent_of_code_2024/actions/workflows/test.yml)
4-
[![Stars: 46](https://img.shields.io/badge/⭐_Stars-46-yellow)](https://adventofcode.com/2024)
4+
[![Stars: 47](https://img.shields.io/badge/⭐_Stars-47-yellow)](https://adventofcode.com/2024)
55

66
This year I am going to try to do Advent of Code in [Gleam](https://gleam.run).
77
To run a day's problems use the command
@@ -42,3 +42,4 @@ information.
4242
- [Day 21](https://adventofcode.com/2024/day/21): [⭐ ⭐ solution](src/day21/solution.gleam)
4343
- [Day 22](https://adventofcode.com/2024/day/22): [⭐ ⭐ solution](src/day22/solution.gleam)
4444
- [Day 23](https://adventofcode.com/2024/day/23): [⭐ ⭐ solution](src/day23/solution.gleam)
45+
- [Day 24](https://adventofcode.com/2024/day/24): [⭐ solution](src/day24/solution.gleam)

inputs

src/day24/solution.gleam

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import gleam/dict.{type Dict}
2+
import gleam/int
3+
import gleam/io
4+
import gleam/list
5+
import gleam/result
6+
import gleam/string
7+
import internal/aoc_utils
8+
9+
pub fn main() {
10+
let filename = "inputs/day24.txt"
11+
12+
let lines_result = aoc_utils.read_lines(from: filename)
13+
case lines_result {
14+
Ok(lines) -> {
15+
// If the file was converting into a list of lines
16+
// successfully then run each part of the problem
17+
aoc_utils.run_part_and_print("Part 1", fn() { solve_p1(lines) })
18+
aoc_utils.run_part_and_print("Part 2", fn() { solve_p2(lines) })
19+
}
20+
Error(_) -> io.println("Error reading file")
21+
}
22+
}
23+
24+
// Part 1
25+
pub fn solve_p1(lines: List(String)) -> Result(String, String) {
26+
use #(wires, gates) <- result.map(parse(lines))
27+
28+
find_wire_values(wires, gates)
29+
|> get_number("z")
30+
|> int.to_string
31+
}
32+
33+
// Part 2
34+
pub fn solve_p2(lines: List(String)) -> Result(String, String) {
35+
use #(wires, gates) <- result.map(parse(lines))
36+
37+
get_number(wires, "x")
38+
|> int.to_base2
39+
|> io.debug
40+
41+
get_number(wires, "y")
42+
|> int.to_base2
43+
|> io.debug
44+
45+
find_wire_values(wires, gates)
46+
|> get_number("z")
47+
|> int.to_base2
48+
|> io.debug
49+
todo
50+
}
51+
52+
type Gate {
53+
And(input1: String, input2: String, output: String)
54+
Or(input1: String, input2: String, output: String)
55+
Xor(input1: String, input2: String, output: String)
56+
}
57+
58+
fn parse(
59+
lines: List(String),
60+
) -> Result(#(Dict(String, Int), List(Gate)), String) {
61+
let assert [values, gates] = aoc_utils.chunk_around_empty_strings(lines)
62+
63+
use wire_dict <- result.try(parse_values(values))
64+
65+
use gate_list <- result.map(parse_gates(gates))
66+
67+
#(wire_dict, gate_list)
68+
}
69+
70+
fn parse_values(values: List(String)) -> Result(Dict(String, Int), String) {
71+
use value_list <- result.map({
72+
values
73+
|> list.map(fn(line) {
74+
case string.split(line, ": ") {
75+
[wire, boolstring] ->
76+
case int.parse(boolstring) {
77+
Ok(n) -> Ok(#(wire, n))
78+
Error(Nil) -> Error("Unable to parse wire value")
79+
}
80+
_ -> Error("Unexpected wire value line")
81+
}
82+
})
83+
|> result.all
84+
})
85+
86+
dict.from_list(value_list)
87+
}
88+
89+
fn parse_gates(gates: List(String)) -> Result(List(Gate), String) {
90+
gates
91+
|> list.map(fn(line) {
92+
case string.split(line, " ") {
93+
[i1, name, i2, _, o] -> {
94+
case name {
95+
"AND" -> Ok(And(i1, i2, o))
96+
"OR" -> Ok(Or(i1, i2, o))
97+
"XOR" -> Ok(Xor(i1, i2, o))
98+
_ -> Error("Gate type not recognized")
99+
}
100+
}
101+
_ -> Error("Unexpected gate format")
102+
}
103+
})
104+
|> result.all
105+
}
106+
107+
fn find_wire_values(
108+
wires: Dict(String, Int),
109+
gates: List(Gate),
110+
) -> Dict(String, Int) {
111+
case gates {
112+
[] -> wires
113+
_ -> {
114+
let newdict =
115+
gates
116+
|> list.fold(wires, fn(d, gate) {
117+
case resolve_gate(gate, wires) {
118+
Ok(#(output, value)) -> {
119+
dict.insert(d, output, value)
120+
}
121+
_ -> d
122+
}
123+
})
124+
125+
find_wire_values(
126+
newdict,
127+
gates |> list.filter(fn(g) { !dict.has_key(newdict, g.output) }),
128+
)
129+
}
130+
}
131+
}
132+
133+
fn resolve_gate(
134+
gate: Gate,
135+
wires: Dict(String, Int),
136+
) -> Result(#(String, Int), Nil) {
137+
use v1 <- result.try(dict.get(wires, gate.input1))
138+
use v2 <- result.map(dict.get(wires, gate.input2))
139+
140+
case gate {
141+
And(_, _, o) -> #(o, int.bitwise_and(v1, v2))
142+
Or(_, _, o) -> #(o, int.bitwise_or(v1, v2))
143+
Xor(_, _, o) -> #(o, int.bitwise_exclusive_or(v1, v2))
144+
}
145+
}
146+
147+
fn get_number(wires: Dict(String, Int), prefix: String) -> Int {
148+
dict.to_list(wires)
149+
|> list.filter(fn(tup) { string.starts_with(tup.0, prefix) })
150+
|> list.sort(fn(tupa, tupb) { string.compare(tupb.0, tupa.0) })
151+
|> list.fold(0, fn(value, tup) { { value * 2 } + tup.1 })
152+
}

test/day24_test.gleam

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import day24/solution
2+
import gleam/string
3+
import gleeunit/should
4+
5+
const testinput = "x00: 1
6+
x01: 0
7+
x02: 1
8+
x03: 1
9+
x04: 0
10+
y00: 1
11+
y01: 1
12+
y02: 1
13+
y03: 1
14+
y04: 1
15+
16+
ntg XOR fgs -> mjb
17+
y02 OR x01 -> tnw
18+
kwq OR kpj -> z05
19+
x00 OR x03 -> fst
20+
tgd XOR rvg -> z01
21+
vdt OR tnw -> bfw
22+
bfw AND frj -> z10
23+
ffh OR nrd -> bqk
24+
y00 AND y03 -> djm
25+
y03 OR y00 -> psh
26+
bqk OR frj -> z08
27+
tnw OR fst -> frj
28+
gnj AND tgd -> z11
29+
bfw XOR mjb -> z00
30+
x03 OR x00 -> vdt
31+
gnj AND wpb -> z02
32+
x04 AND y00 -> kjc
33+
djm OR pbm -> qhw
34+
nrd AND vdt -> hwm
35+
kjc AND fst -> rvg
36+
y04 OR y02 -> fgs
37+
y01 AND x02 -> pbm
38+
ntg OR kjc -> kwq
39+
psh XOR fgs -> tgd
40+
qhw XOR tgd -> z09
41+
pbm OR djm -> kpj
42+
x03 XOR y03 -> ffh
43+
x00 XOR y04 -> ntg
44+
bfw OR bqk -> z06
45+
nrd XOR fgs -> wpb
46+
frj XOR qhw -> z04
47+
bqk OR frj -> z07
48+
y03 OR x01 -> nrd
49+
hwm AND bqk -> z03
50+
tgd XOR rvg -> z12
51+
tnw OR pbm -> gnj"
52+
53+
pub fn part1_test() {
54+
let lines = string.split(testinput, "\n")
55+
solution.solve_p1(lines)
56+
|> should.equal(Ok("2024"))
57+
}
58+
59+
pub fn part2_test() {
60+
let lines = string.split(testinput, "\n")
61+
solution.solve_p2(lines)
62+
|> should.equal(Ok("24"))
63+
}

0 commit comments

Comments
 (0)