Skip to content

Commit 7c8f06f

Browse files
committed
finished day 7
1 parent 40184fa commit 7c8f06f

File tree

4 files changed

+167
-3
lines changed

4 files changed

+167
-3
lines changed

README.md

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

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

66
This year will be my second year doing Advent of Code in [Gleam](https://gleam.run).
77
Last year I was still learning the language, and in the past year I have used it
@@ -40,4 +40,5 @@ information.
4040
- [Day 3](https://adventofcode.com/2025/day/3): [⭐ ⭐ solution](src/day03/solution.gleam)
4141
- [Day 4](https://adventofcode.com/2025/day/4): [⭐ ⭐ solution](src/day04/solution.gleam)
4242
- [Day 5](https://adventofcode.com/2025/day/5): [⭐ ⭐ solution](src/day05/solution.gleam)
43-
- [Day 6](https://adventofcode.com/2026/day/6): [⭐ ⭐ solution](src/day06/solution.gleam)
43+
- [Day 6](https://adventofcode.com/2025/day/6): [⭐ ⭐ solution](src/day06/solution.gleam)
44+
- [Day 7](https://adventofcode.com/2025/day/7): [⭐ ⭐ solution](src/day07/solution.gleam)

inputs

src/day07/solution.gleam

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import gleam/dict
2+
import gleam/int
3+
import gleam/io
4+
import gleam/list
5+
import gleam/result
6+
import gleam/set
7+
import gleam/string
8+
import internal/aoc_utils
9+
10+
pub fn main() {
11+
let filename = "inputs/day07.txt"
12+
13+
let lines_result = aoc_utils.read_lines(from: filename)
14+
case lines_result {
15+
Ok(lines) -> {
16+
// If the file was converting into a list of lines
17+
// successfully then run each part of the problem
18+
aoc_utils.run_part_and_print("Part 1", fn() { solve_p1(lines) })
19+
aoc_utils.run_part_and_print("Part 2", fn() { solve_p2(lines) })
20+
}
21+
Error(_) -> io.println("Error reading file")
22+
}
23+
}
24+
25+
// Part 1
26+
pub fn solve_p1(lines: List(String)) -> Result(String, String) {
27+
let map = parse(lines)
28+
let beams = set.new() |> set.insert(map.start)
29+
30+
count_splits(map.splitters, beams, 0)
31+
|> int.to_string
32+
|> Ok
33+
}
34+
35+
// Part 2
36+
pub fn solve_p2(lines: List(String)) -> Result(String, String) {
37+
let map = parse(lines)
38+
39+
count_timelines(map.splitters, dict.from_list([#(map.start, 1)]))
40+
|> dict.to_list
41+
|> list.fold(0, fn(acc, tuple) { acc + tuple.1 })
42+
|> int.to_string
43+
|> Ok
44+
}
45+
46+
type Map {
47+
Map(start: Int, splitters: List(List(Int)))
48+
}
49+
50+
fn parse(lines: List(String)) -> Map {
51+
// let #(startline, splitlines) = list.split(lines, 1)
52+
53+
let imap =
54+
lines
55+
|> list.fold(Map(0, []), fn(acc, row) {
56+
let row_results =
57+
string.to_graphemes(row)
58+
|> list.index_fold(#(acc.start, []), fn(subacc, char, idx) {
59+
case char {
60+
"." -> subacc
61+
"S" -> #(idx, subacc.1)
62+
"^" -> #(subacc.0, [idx, ..subacc.1])
63+
_ -> panic as "unexpected character in map"
64+
}
65+
})
66+
67+
Map(row_results.0, [row_results.1, ..acc.splitters])
68+
})
69+
70+
Map(imap.start, list.reverse(imap.splitters) |> list.drop(1))
71+
}
72+
73+
fn count_splits(
74+
splitters: List(List(Int)),
75+
beams: set.Set(Int),
76+
split_count: Int,
77+
) -> Int {
78+
case splitters {
79+
[splitter_row, ..rest] -> {
80+
let #(new_beams, new_count) =
81+
splitter_row
82+
|> list.fold(#(beams, split_count), fn(acc, splitter_idx) {
83+
case set.contains(beams, splitter_idx) {
84+
False -> acc
85+
True -> #(
86+
acc.0
87+
|> set.delete(splitter_idx)
88+
|> set.insert(splitter_idx + 1)
89+
|> set.insert(splitter_idx - 1),
90+
acc.1 + 1,
91+
)
92+
}
93+
})
94+
count_splits(rest, new_beams, new_count)
95+
}
96+
[] -> split_count
97+
}
98+
}
99+
100+
// beam timelines is the number of timelines leading to a beam
101+
fn count_timelines(
102+
splitters: List(List(Int)),
103+
beam_timelines: dict.Dict(Int, Int),
104+
) -> dict.Dict(Int, Int) {
105+
case splitters {
106+
[splitter_row, ..rest] -> {
107+
let new_beam_timelines =
108+
splitter_row
109+
|> list.fold(beam_timelines, fn(acc, splitter_idx) {
110+
// Start with the timeline count for each beam, then if a split
111+
// happens all the timelines get added to timelines in adjacent beams
112+
// The current position beam disappears leaving 0 timelines for that
113+
// position
114+
let timeline_count =
115+
dict.get(beam_timelines, splitter_idx) |> result.unwrap(0)
116+
117+
dict.insert(acc, splitter_idx, 0)
118+
|> dict.insert(
119+
splitter_idx - 1,
120+
{ dict.get(acc, splitter_idx - 1) |> result.unwrap(0) }
121+
+ timeline_count,
122+
)
123+
|> dict.insert(
124+
splitter_idx + 1,
125+
{ dict.get(acc, splitter_idx + 1) |> result.unwrap(0) }
126+
+ timeline_count,
127+
)
128+
})
129+
130+
count_timelines(rest, new_beam_timelines)
131+
}
132+
[] -> beam_timelines
133+
}
134+
}

test/day07_test.gleam

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import day07/solution
2+
import gleam/string
3+
4+
const testinput = ".......S.......
5+
...............
6+
.......^.......
7+
...............
8+
......^.^......
9+
...............
10+
.....^.^.^.....
11+
...............
12+
....^.^...^....
13+
...............
14+
...^.^...^.^...
15+
...............
16+
..^...^.....^..
17+
...............
18+
.^.^.^.^.^...^.
19+
..............."
20+
21+
pub fn part1_test() {
22+
let lines = string.split(testinput, "\n")
23+
assert solution.solve_p1(lines) == Ok("21")
24+
}
25+
26+
pub fn part2_test() {
27+
let lines = string.split(testinput, "\n")
28+
assert solution.solve_p2(lines) == Ok("40")
29+
}

0 commit comments

Comments
 (0)