Skip to content

Commit fd7f8fb

Browse files
committed
finished day 12
1 parent 4ff4582 commit fd7f8fb

File tree

5 files changed

+160
-6
lines changed

5 files changed

+160
-6
lines changed

README.md

Lines changed: 11 additions & 4 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: 20](https://img.shields.io/badge/⭐_Stars-20-yellow)](https://adventofcode.com/2025)
4+
[![Stars: 23](https://img.shields.io/badge/⭐_Stars-23-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
@@ -58,21 +58,28 @@ information.
5858
Using the new structure, and making a few other changes, the second part of
5959
my [solution](src/day08/solution.gleam) is roughly 3 times faster.
6060

61-
- [Day 9](https://adventmfcode.com/2025/day/9): [⭐ solution](src/day09/solution.gleam)
61+
- [Day 9](https://adventofcode.com/2025/day/9): [⭐ solution](src/day09/solution.gleam)
6262

6363
I ran into an issue doing part 2. I think it is that I am only checking if
6464
the corners are inside the figure. It may be that the corners are inside,
6565
but there is a line going through one of the walls. I ran out of time
6666
this morning to work on this and will pick it up later.
6767

68-
- [Day 10](https://adventmfcode.com/2025/day/10): [⭐ solution](src/day10/solution.gleam)
68+
- [Day 10](https://adventofcode.com/2025/day/10): [⭐ solution](src/day10/solution.gleam)
6969

7070
I tried doing part 2 a naive way with some memoization, but it seems like
7171
I still need to work on it. Code was getting very convoluted anyway, not
7272
pretty like the first several days.
7373

74-
- [Day 11](https://adventmfcode.com/2025/day/11): [⭐ ⭐ solution](src/day11/solution.gleam)
74+
- [Day 11](https://adventofcode.com/2025/day/11): [⭐ ⭐ solution](src/day11/solution.gleam)
7575

7676
Back on track with today's problem. This is a straightforward depth-first
7777
search, but I add memoization so I don't have to keep revisiting paths
7878
I have counted before.
79+
80+
- [Day 12](https://adventofcode.com/2025/day/12): [⭐ solution](src/day12/solution.gleam)
81+
82+
As I was filtering my input for cases that would require rotation and
83+
flipping I realized that none did. There was either enough room for a
84+
3x3 present within the area or not enough room for the total area of
85+
presents provided. Therefore I didn't have to do anything complex.

inputs

src/day11/solution.gleam

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import gleam/deque
21
import gleam/dict
32
import gleam/int
43
import gleam/io

src/day12/solution.gleam

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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+
import internal/point
10+
11+
pub fn main() {
12+
let filename = "inputs/day12.txt"
13+
14+
let lines_result = aoc_utils.read_lines(from: filename)
15+
case lines_result {
16+
Ok(lines) -> {
17+
// If the file was converting into a list of lines
18+
// successfully then run each part of the problem
19+
aoc_utils.run_part_and_print("Part 1", fn() { solve_p1(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 sections = aoc_utils.chunk_around_empty_strings(lines)
28+
29+
let #(present_input, requirements_input) =
30+
list.split(sections, list.length(sections) - 1)
31+
32+
let presents =
33+
present_input
34+
|> list.map(parse_present)
35+
|> dict.from_list
36+
37+
let requirements =
38+
requirements_input
39+
|> list.flatten
40+
|> list.map(parse_requirements)
41+
42+
requirements
43+
|> list.fold_until(Ok(0), fn(fit_count, r) {
44+
case fit_count {
45+
Ok(c) ->
46+
case definite_fit(r), definite_notfit(r, presents) {
47+
True, _ -> list.Continue(Ok(c + 1))
48+
_, True -> list.Continue(Ok(c))
49+
_, _ -> list.Stop(Error("Marginal fitting case detected"))
50+
}
51+
_ -> list.Stop(Error("Marginal fitting case detected"))
52+
}
53+
})
54+
|> result.map(int.to_string)
55+
}
56+
57+
fn parse_present(lines: List(String)) -> #(Int, set.Set(point.Point)) {
58+
let assert [index_line, ..shape_lines] = lines
59+
60+
let assert Ok(present_index) =
61+
string.replace(index_line, ":", "") |> int.parse
62+
63+
let present =
64+
shape_lines
65+
|> list.index_fold(set.new(), fn(acc, line, y) {
66+
string.to_graphemes(line)
67+
|> list.index_fold(acc, fn(acc, character, x) {
68+
case character {
69+
"#" -> set.insert(acc, #(x, y))
70+
_ -> acc
71+
}
72+
})
73+
})
74+
75+
#(present_index, present)
76+
}
77+
78+
fn parse_requirements(line: String) -> #(point.Point, List(Int)) {
79+
let assert Ok(#(dimensions, present_counts)) = string.split_once(line, ": ")
80+
let assert Ok(#(x_string, y_string)) = string.split_once(dimensions, "x")
81+
let counts =
82+
string.split(present_counts, " ") |> list.map(int.parse) |> result.values
83+
84+
let assert Ok(x) = int.parse(x_string)
85+
let assert Ok(y) = int.parse(y_string)
86+
#(#(x, y), counts)
87+
}
88+
89+
fn definite_fit(requirements: #(point.Point, List(Int))) -> Bool {
90+
let area = requirements.0.0 * requirements.0.1
91+
92+
int.sum(requirements.1) * 9 <= area
93+
}
94+
95+
fn definite_notfit(
96+
requirements: #(point.Point, List(Int)),
97+
presents: dict.Dict(Int, set.Set(point.Point)),
98+
) -> Bool {
99+
let area = requirements.0.0 * requirements.0.1
100+
101+
requirements.1
102+
|> list.index_fold(0, fn(present_area, present_count, idx) {
103+
let assert Ok(p) = dict.get(presents, idx)
104+
present_area + { present_count * set.size(p) }
105+
})
106+
> area
107+
}

test/day12_test.gleam

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import day12/solution
2+
import gleam/string
3+
4+
const testinput = "0:
5+
###
6+
##.
7+
##.
8+
9+
1:
10+
###
11+
##.
12+
.##
13+
14+
2:
15+
.##
16+
###
17+
##.
18+
19+
3:
20+
##.
21+
###
22+
##.
23+
24+
4:
25+
###
26+
#..
27+
###
28+
29+
5:
30+
###
31+
.#.
32+
###
33+
34+
4x4: 0 0 0 0 2 0
35+
12x5: 1 0 1 0 2 2
36+
12x5: 1 0 1 0 3 2"
37+
38+
pub fn part1_test() {
39+
let lines = string.split(testinput, "\n")
40+
assert solution.solve_p1(lines) == Error("Marginal fitting case detected")
41+
}

0 commit comments

Comments
 (0)