Skip to content

Commit e30abb5

Browse files
authored
day 25 article (#811)
1 parent df0a59c commit e30abb5

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

docs/2024/puzzles/day25.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,84 @@ import Solver from "../../../../../website/src/components/Solver.js"
22

33
# Day 25: Code Chronicle
44

5+
by [@merlinorg](https://github.com/merlinorg)
6+
57
## Puzzle description
68

79
https://adventofcode.com/2024/day/25
810

11+
## Solution summary
12+
13+
1. Parse and partition the locks and keys.
14+
2. Find all lock and key combinations that could fit.
15+
3. Return the count of potential matches.
16+
17+
## Parsing
18+
19+
It's the last day of Advent of Code so we'll keep it simple. The input consists
20+
of a sequence of grids, separated by blank lines. Each grid is a sequence of lines
21+
consisting of the `#` and `.` characters. Locks have `#` characters in the first
22+
row, where keys have `.` characters. To parse this we'll just use simple string
23+
splitting.
24+
25+
First, we split the input into grids by matching on the blank lines. This gives us
26+
an array of strings, each grid represented by a single string. Then we partition
27+
this into two arrays; one the keys, and the other locks. For this, we use the
28+
`partition` method that takes a predicate; every grid that matches this predicate
29+
will be placed in the first array of the resulting tuple, the rest in the second.
30+
31+
```scala 3
32+
val (locks, keys) = input.split("\n\n").partition(_.startsWith("#"))
33+
```
34+
35+
In general, arrays are not the most ergonomic data structures to use, but for
36+
this final puzzle they are more than sufficient.
37+
38+
## Matching
39+
40+
To find all potential matches we will use a for comprehension to loop through
41+
all the locks, and then for each lock, through all the keys. For each pair of
42+
a lock and key, we want to determine whether there is any overlap that would
43+
prevent the key fitting the lock.
44+
We can perform this test by simply zipping the key and the lock strings; this
45+
gives us a collection of every corresponding character from each string. The
46+
key can fit the lock if there is no location containing a `#` character in
47+
both grids.
48+
49+
```scala 3
50+
val matches = for
51+
lock <- locks
52+
key <- keys
53+
if lock.zip(key).forall: (lockChar, keyChar) =>
54+
lockChar != '#' || keyChar != '#'
55+
yield lock -> key
56+
```
57+
58+
This returns all of the matching lock and key combinations; the solution to
59+
the puzzle is the size of this array.
60+
61+
## Final code
62+
63+
```scala 3
64+
def part1(input: String): Int =
65+
val (locks, keys) = input.split("\n\n").partition(_.startsWith("#"))
66+
67+
val matches = for
68+
lock <- locks
69+
key <- keys
70+
if lock.zip(key).forall: (lockChar, keyChar) =>
71+
lockChar != '#' || keyChar != '#'
72+
yield lock -> key
73+
74+
matches.length
75+
```
76+
77+
### Run it in the browser
78+
79+
#### Part 1
80+
81+
<Solver puzzle="day25-part1" year="2024"/>
82+
983
## Solutions from the community
1084

1185
- [Solution](https://github.com/Philippus/adventofcode/blob/main/src/main/scala/adventofcode2024/Day25.scala) by [Philippus Baalman](https://github.com/philippus)

solver/src/main/scala/adventofcode/Solver.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ object Solver:
1515
"day21-part2" -> day21.part2,
1616
"day22-part1" -> day22.part1,
1717
"day22-part2" -> day22.part2,
18+
"day25-part1" -> day25.part1,
1819
)
1920

2021
private val solutions2023: Map[String, String => Any] =

0 commit comments

Comments
 (0)