2025: day09: part 1 and 2
This commit is contained in:
parent
22350a3c68
commit
8c9d675964
6 changed files with 673 additions and 0 deletions
|
|
@ -8,6 +8,7 @@ use aoc2025::day05;
|
|||
use aoc2025::day06;
|
||||
use aoc2025::day07;
|
||||
use aoc2025::day08;
|
||||
use aoc2025::day09;
|
||||
|
||||
fn aoc2025_all(c: &mut Criterion) {
|
||||
c.bench_function("day01", |b| b.iter(|| day01::run().unwrap()));
|
||||
|
|
@ -18,6 +19,7 @@ fn aoc2025_all(c: &mut Criterion) {
|
|||
c.bench_function("day06", |b| b.iter(|| day06::run().unwrap()));
|
||||
c.bench_function("day07", |b| b.iter(|| day07::run().unwrap()));
|
||||
c.bench_function("day08", |b| b.iter(|| day08::run().unwrap()));
|
||||
c.bench_function("day09", |b| b.iter(|| day09::run().unwrap()));
|
||||
}
|
||||
|
||||
criterion_group! {
|
||||
|
|
|
|||
496
aoc2025/input/day09.txt
Normal file
496
aoc2025/input/day09.txt
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
97997,50117
|
||||
97997,51346
|
||||
98453,51346
|
||||
98453,52549
|
||||
97943,52549
|
||||
97943,53788
|
||||
98190,53788
|
||||
98190,54948
|
||||
97502,54948
|
||||
97502,56154
|
||||
97395,56154
|
||||
97395,57433
|
||||
97739,57433
|
||||
97739,58596
|
||||
97292,58596
|
||||
97292,59837
|
||||
97281,59837
|
||||
97281,61017
|
||||
96953,61017
|
||||
96953,62054
|
||||
96089,62054
|
||||
96089,63409
|
||||
96430,63409
|
||||
96430,64384
|
||||
95454,64384
|
||||
95454,65751
|
||||
95714,65751
|
||||
95714,66804
|
||||
95033,66804
|
||||
95033,67976
|
||||
94684,67976
|
||||
94684,69011
|
||||
94003,69011
|
||||
94003,70198
|
||||
93676,70198
|
||||
93676,71390
|
||||
93338,71390
|
||||
93338,72348
|
||||
92529,72348
|
||||
92529,73408
|
||||
91931,73408
|
||||
91931,74257
|
||||
90977,74257
|
||||
90977,75371
|
||||
90482,75371
|
||||
90482,76290
|
||||
89678,76290
|
||||
89678,77659
|
||||
89532,77659
|
||||
89532,78647
|
||||
88813,78647
|
||||
88813,79559
|
||||
87993,79559
|
||||
87993,80678
|
||||
87436,80678
|
||||
87436,81480
|
||||
86488,81480
|
||||
86488,82509
|
||||
85805,82509
|
||||
85805,83363
|
||||
84926,83363
|
||||
84926,84016
|
||||
83849,84016
|
||||
83849,84837
|
||||
82952,84837
|
||||
82952,85751
|
||||
82141,85751
|
||||
82141,86148
|
||||
80878,86148
|
||||
80878,86955
|
||||
79982,86955
|
||||
79982,87912
|
||||
79198,87912
|
||||
79198,88620
|
||||
78213,88620
|
||||
78213,89781
|
||||
77544,89781
|
||||
77544,90134
|
||||
76309,90134
|
||||
76309,90879
|
||||
75341,90879
|
||||
75341,91649
|
||||
74380,91649
|
||||
74380,92207
|
||||
73291,92207
|
||||
73291,92361
|
||||
71995,92361
|
||||
71995,93245
|
||||
71081,93245
|
||||
71081,93967
|
||||
70071,93967
|
||||
70071,94524
|
||||
68977,94524
|
||||
68977,94943
|
||||
67824,94943
|
||||
67824,95146
|
||||
66594,95146
|
||||
66594,95498
|
||||
65427,95498
|
||||
65427,95782
|
||||
64240,95782
|
||||
64240,95918
|
||||
63017,95918
|
||||
63017,96932
|
||||
62028,96932
|
||||
62028,96751
|
||||
60727,96751
|
||||
60727,96832
|
||||
59504,96832
|
||||
59504,97447
|
||||
58383,97447
|
||||
58383,97339
|
||||
57133,97339
|
||||
57133,97862
|
||||
55976,97862
|
||||
55976,97522
|
||||
54714,97522
|
||||
54714,98341
|
||||
53561,98341
|
||||
53561,98159
|
||||
52323,98159
|
||||
52323,97865
|
||||
51095,97865
|
||||
51095,98319
|
||||
49881,98319
|
||||
49881,97497
|
||||
48679,97497
|
||||
48679,97646
|
||||
47466,97646
|
||||
47466,97937
|
||||
46230,97937
|
||||
46230,97396
|
||||
45062,97396
|
||||
45062,97403
|
||||
43844,97403
|
||||
43844,97029
|
||||
42677,97029
|
||||
42677,97668
|
||||
41335,97668
|
||||
41335,96999
|
||||
40221,96999
|
||||
40221,96413
|
||||
39109,96413
|
||||
39109,96133
|
||||
37934,96133
|
||||
37934,95950
|
||||
36729,95950
|
||||
36729,95917
|
||||
35469,95917
|
||||
35469,94917
|
||||
34523,94917
|
||||
34523,95102
|
||||
33169,95102
|
||||
33169,94246
|
||||
32199,94246
|
||||
32199,94503
|
||||
30772,94503
|
||||
30772,93436
|
||||
29912,93436
|
||||
29912,92610
|
||||
28968,92610
|
||||
28968,92121
|
||||
27865,92121
|
||||
27865,92036
|
||||
26532,92036
|
||||
26532,91010
|
||||
25722,91010
|
||||
25722,90374
|
||||
24696,90374
|
||||
24696,90327
|
||||
23279,90327
|
||||
23279,88941
|
||||
22753,88941
|
||||
22753,88221
|
||||
21788,88221
|
||||
21788,87580
|
||||
20762,87580
|
||||
20762,87110
|
||||
19588,87110
|
||||
19588,86306
|
||||
18676,86306
|
||||
18676,85743
|
||||
17547,85743
|
||||
17547,84602
|
||||
16945,84602
|
||||
16945,83641
|
||||
16193,83641
|
||||
16193,83283
|
||||
14813,83283
|
||||
14813,81918
|
||||
14496,81918
|
||||
14496,80918
|
||||
13804,80918
|
||||
13804,80292
|
||||
12662,80292
|
||||
12662,79115
|
||||
12195,79115
|
||||
12195,78440
|
||||
11068,78440
|
||||
11068,77149
|
||||
10787,77149
|
||||
10787,76199
|
||||
10033,76199
|
||||
10033,75155
|
||||
9420,75155
|
||||
9420,74315
|
||||
8460,74315
|
||||
8460,73226
|
||||
7910,73226
|
||||
7910,72194
|
||||
7255,72194
|
||||
7255,71018
|
||||
6882,71018
|
||||
6882,69749
|
||||
6736,69749
|
||||
6736,68882
|
||||
5698,68882
|
||||
5698,67727
|
||||
5301,67727
|
||||
5301,66585
|
||||
4877,66585
|
||||
4877,65281
|
||||
4930,65281
|
||||
4930,64395
|
||||
3722,64395
|
||||
3722,63224
|
||||
3347,63224
|
||||
3347,61827
|
||||
3853,61827
|
||||
3853,60651
|
||||
3581,60651
|
||||
3581,59463
|
||||
3371,59463
|
||||
3371,58378
|
||||
2585,58378
|
||||
2585,57101
|
||||
2870,57101
|
||||
2870,55946
|
||||
2377,55946
|
||||
2377,54727
|
||||
2352,54727
|
||||
2352,53560
|
||||
1681,53560
|
||||
1681,52313
|
||||
2044,52313
|
||||
2044,51094
|
||||
2172,51094
|
||||
2172,50110
|
||||
94865,50110
|
||||
94865,48656
|
||||
1652,48656
|
||||
1652,47426
|
||||
1613,47426
|
||||
1613,46276
|
||||
2643,46276
|
||||
2643,44990
|
||||
1915,44990
|
||||
1915,43812
|
||||
2348,43812
|
||||
2348,42565
|
||||
2253,42565
|
||||
2253,41451
|
||||
2971,41451
|
||||
2971,40208
|
||||
2941,40208
|
||||
2941,39037
|
||||
3278,39037
|
||||
3278,37906
|
||||
3762,37906
|
||||
3762,36793
|
||||
4270,36793
|
||||
4270,35611
|
||||
4530,35611
|
||||
4530,34328
|
||||
4516,34328
|
||||
4516,33171
|
||||
4901,33171
|
||||
4901,32169
|
||||
5679,32169
|
||||
5679,31086
|
||||
6224,31086
|
||||
6224,29900
|
||||
6537,29900
|
||||
6537,28819
|
||||
7087,28819
|
||||
7087,27837
|
||||
7824,27837
|
||||
7824,26571
|
||||
8032,26571
|
||||
8032,25560
|
||||
8716,25560
|
||||
8716,24305
|
||||
9002,24305
|
||||
9002,23228
|
||||
9595,23228
|
||||
9595,22755
|
||||
11060,22755
|
||||
11060,21499
|
||||
11387,21499
|
||||
11387,20615
|
||||
12230,20615
|
||||
12230,19629
|
||||
12940,19629
|
||||
12940,18363
|
||||
13330,18363
|
||||
13330,17822
|
||||
14559,17822
|
||||
14559,16593
|
||||
15028,16593
|
||||
15028,16138
|
||||
16304,16138
|
||||
16304,15078
|
||||
16967,15078
|
||||
16967,14567
|
||||
18145,14567
|
||||
18145,13691
|
||||
18985,13691
|
||||
18985,12725
|
||||
19758,12725
|
||||
19758,11618
|
||||
20440,11618
|
||||
20440,11285
|
||||
21717,11285
|
||||
21717,10537
|
||||
22677,10537
|
||||
22677,9996
|
||||
23776,9996
|
||||
23776,9085
|
||||
24636,9085
|
||||
24636,8807
|
||||
25887,8807
|
||||
25887,7954
|
||||
26797,7954
|
||||
26797,7299
|
||||
27828,7299
|
||||
27828,6560
|
||||
28824,6560
|
||||
28824,6675
|
||||
30222,6675
|
||||
30222,6188
|
||||
31326,6188
|
||||
31326,5665
|
||||
32416,5665
|
||||
32416,5269
|
||||
33558,5269
|
||||
33558,4558
|
||||
34592,4558
|
||||
34592,4297
|
||||
35783,4297
|
||||
35783,4096
|
||||
36987,4096
|
||||
36987,3676
|
||||
38127,3676
|
||||
38127,3093
|
||||
39236,3093
|
||||
39236,2965
|
||||
40454,2965
|
||||
40454,2678
|
||||
41638,2678
|
||||
41638,2319
|
||||
42815,2319
|
||||
42815,2781
|
||||
44104,2781
|
||||
44104,2245
|
||||
45262,2245
|
||||
45262,2218
|
||||
46479,2218
|
||||
46479,1829
|
||||
47675,1829
|
||||
47675,1732
|
||||
48895,1732
|
||||
48895,1948
|
||||
50118,1948
|
||||
50118,2255
|
||||
51327,2255
|
||||
51327,1730
|
||||
52566,1730
|
||||
52566,1670
|
||||
53799,1670
|
||||
53799,2521
|
||||
54945,2521
|
||||
54945,1990
|
||||
56234,1990
|
||||
56234,2955
|
||||
57325,2955
|
||||
57325,2820
|
||||
58575,2820
|
||||
58575,3321
|
||||
59712,3321
|
||||
59712,3024
|
||||
61022,3024
|
||||
61022,3906
|
||||
62055,3906
|
||||
62055,3723
|
||||
63364,3723
|
||||
63364,4203
|
||||
64492,4203
|
||||
64492,4440
|
||||
65697,4440
|
||||
65697,4855
|
||||
66845,4855
|
||||
66845,5402
|
||||
67941,5402
|
||||
67941,5922
|
||||
69043,5922
|
||||
69043,6713
|
||||
70017,6713
|
||||
70017,7102
|
||||
71172,7102
|
||||
71172,7317
|
||||
72429,7317
|
||||
72429,7869
|
||||
73519,7869
|
||||
73519,8752
|
||||
74417,8752
|
||||
74417,9149
|
||||
75601,9149
|
||||
75601,10303
|
||||
76301,10303
|
||||
76301,10274
|
||||
77794,10274
|
||||
77794,11384
|
||||
78502,11384
|
||||
78502,12252
|
||||
79367,12252
|
||||
79367,12863
|
||||
80432,12863
|
||||
80432,14015
|
||||
81045,14015
|
||||
81045,14153
|
||||
82546,14153
|
||||
82546,15277
|
||||
83169,15277
|
||||
83169,16371
|
||||
83794,16371
|
||||
83794,17100
|
||||
84780,17100
|
||||
84780,18019
|
||||
85572,18019
|
||||
85572,18602
|
||||
86755,18602
|
||||
86755,19867
|
||||
87140,19867
|
||||
87140,20414
|
||||
88416,20414
|
||||
88416,21566
|
||||
88920,21566
|
||||
88920,22438
|
||||
89807,22438
|
||||
89807,23692
|
||||
90131,23692
|
||||
90131,24638
|
||||
90912,24638
|
||||
90912,25875
|
||||
91212,25875
|
||||
91212,26672
|
||||
92272,26672
|
||||
92272,28023
|
||||
92324,28023
|
||||
92324,29101
|
||||
92870,29101
|
||||
92870,30144
|
||||
93494,30144
|
||||
93494,31085
|
||||
94375,31085
|
||||
94375,32167
|
||||
94962,32167
|
||||
94962,33582
|
||||
94664,33582
|
||||
94664,34550
|
||||
95563,34550
|
||||
95563,35684
|
||||
96022,35684
|
||||
96022,36879
|
||||
96285,36879
|
||||
96285,38051
|
||||
96621,38051
|
||||
96621,39161
|
||||
97232,39161
|
||||
97232,40476
|
||||
96926,40476
|
||||
96926,41698
|
||||
96982,41698
|
||||
96982,42794
|
||||
97820,42794
|
||||
97820,44053
|
||||
97627,44053
|
||||
97627,45302
|
||||
97346,45302
|
||||
97346,46459
|
||||
98049,46459
|
||||
98049,47710
|
||||
97453,47710
|
||||
97453,48890
|
||||
98462,48890
|
||||
98462,50117
|
||||
8
aoc2025/input/day09_provided.txt
Normal file
8
aoc2025/input/day09_provided.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
7,1
|
||||
11,1
|
||||
11,7
|
||||
9,7
|
||||
9,5
|
||||
2,5
|
||||
2,3
|
||||
7,3
|
||||
164
aoc2025/src/day09.rs
Normal file
164
aoc2025/src/day09.rs
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
use anyhow::{Context, Result, anyhow};
|
||||
use std::{fmt::Write, str::FromStr};
|
||||
|
||||
const INPUT: &str = include_str!("../input/day09.txt");
|
||||
|
||||
pub fn run() -> Result<String> {
|
||||
let mut res = String::with_capacity(128);
|
||||
writeln!(res, "part 1: {}", part1(INPUT)?)?;
|
||||
writeln!(res, "part 2: {}", part2(INPUT)?)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
struct Point {
|
||||
x: usize,
|
||||
y: usize,
|
||||
}
|
||||
|
||||
impl FromStr for Point {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let (x, y) = s
|
||||
.split_once(',')
|
||||
.with_context(|| format!("couldn't parse point `{}'", s))?;
|
||||
let (x, y) = (x.parse()?, y.parse()?);
|
||||
|
||||
Ok(Self { x, y })
|
||||
}
|
||||
}
|
||||
|
||||
fn rectangle_area(p1: &Point, p2: &Point) -> usize {
|
||||
(p1.x.max(p2.x) - p1.x.min(p2.x) + 1) * (p1.y.max(p2.y) - p1.y.min(p2.y) + 1)
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> Result<usize> {
|
||||
let points = input
|
||||
.lines()
|
||||
.map(|line| line.parse::<Point>())
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let mut max = None;
|
||||
for (idx, p1) in points.iter().enumerate() {
|
||||
for p2 in points.iter().skip(idx + 1) {
|
||||
let area = rectangle_area(p1, p2);
|
||||
match max {
|
||||
Some(m) => max = Some(area.max(m)),
|
||||
None => max = Some(area),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
max.ok_or_else(|| anyhow!("input was empty"))
|
||||
}
|
||||
|
||||
// Computes whether a segment crosses through our rectangle.
|
||||
//
|
||||
// Since edges are always parallel to axes, this is easier than in the general case
|
||||
fn edge_intersects(&(e1, e2): &(Point, Point), (r1, r2): (&Point, &Point)) -> bool {
|
||||
let (rect_xmin, rect_xmax) = (r1.x.min(r2.x), r1.x.max(r2.x));
|
||||
let (rect_ymin, rect_ymax) = (r1.y.min(r2.y), r1.y.max(r2.y));
|
||||
|
||||
#[allow(clippy::nonminimal_bool)]
|
||||
if e1.x == e2.x {
|
||||
// segment is vertical
|
||||
let edge_ymin = e1.y.min(e2.y);
|
||||
let edge_ymax = e1.y.max(e2.y);
|
||||
(rect_xmin < e1.x && e1.x < rect_xmax ) // we're in the right X range to cross
|
||||
&& ((edge_ymin <= rect_ymin && edge_ymax >= rect_ymax) // segment crosses through both sides
|
||||
|| (edge_ymin <= rect_ymin && rect_ymin < edge_ymax) // segment crosses through bottom edge
|
||||
|| (edge_ymin < rect_ymax && edge_ymax >= rect_ymax) // segment crosses through top edge
|
||||
)
|
||||
} else {
|
||||
// segment is horizontal
|
||||
let edge_xmin = e1.x.min(e2.x);
|
||||
let edge_xmax = e1.x.max(e2.x);
|
||||
(rect_ymin < e1.y && e1.y < rect_ymax ) // we're in the right X range to cross
|
||||
&& ((edge_xmin <= rect_xmin && edge_xmax >= rect_xmax) // segment crosses through both sides
|
||||
|| (edge_xmin <= rect_xmin && rect_xmin < edge_xmax) // segment crosses through bottom edge
|
||||
|| (edge_xmin < rect_xmax && edge_xmax >= rect_xmax) // segment crosses through top edge
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn part2(input: &str) -> Result<usize> {
|
||||
let points = input
|
||||
.lines()
|
||||
.map(|line| line.parse::<Point>())
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let mut edges = points.windows(2).map(|w| (w[0], w[1])).collect::<Vec<_>>();
|
||||
edges.push((
|
||||
*points.last().context("input was empty")?,
|
||||
*points.first().context("input was empty")?,
|
||||
));
|
||||
|
||||
let mut max = None;
|
||||
for (idx, p1) in points.iter().enumerate() {
|
||||
for p2 in points.iter().skip(idx + 1) {
|
||||
if edges.iter().any(|e| edge_intersects(e, (p1, p2))) {
|
||||
// If an edge crosses through our rectangle then one side of the edge is obviously
|
||||
// outside our polygon.
|
||||
//
|
||||
// Generally, this isn't sufficient to guarantee that a rectangle is "valid".
|
||||
// Consider the following polygon:
|
||||
//
|
||||
// ..........
|
||||
// .#X1..#X#.
|
||||
// .XXX..XXX.
|
||||
// .XX#XX2XX.
|
||||
// .#XXXXXX#.
|
||||
// ..........
|
||||
//
|
||||
// The rectangle between 1 and 2 isn't crossed by any edge, yet it is outside the
|
||||
// polygon. However looking at the shape of my input (which more or less looks like
|
||||
// a rasterized circle), it's obvious that this kind of edge case will never happen
|
||||
// for rectangles large enough to be of maximal area.
|
||||
continue;
|
||||
}
|
||||
let area = rectangle_area(p1, p2);
|
||||
match max {
|
||||
Some(m) => max = Some(area.max(m)),
|
||||
None => max = Some(area),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
max.ok_or_else(|| anyhow!("input was empty"))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const PROVIDED: &str = include_str!("../input/day09_provided.txt");
|
||||
|
||||
#[test]
|
||||
fn part1_provided() {
|
||||
assert_eq!(part1(PROVIDED).unwrap(), 50);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_real() {
|
||||
assert_eq!(part1(INPUT).unwrap(), 4758121828);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_provided() {
|
||||
assert!(edge_intersects(
|
||||
&(Point { x: 7, y: 3 }, Point { x: 7, y: 1 }),
|
||||
(&Point { x: 2, y: 5 }, &Point { x: 11, y: 1 })
|
||||
));
|
||||
assert!(edge_intersects(
|
||||
&(Point { x: 9, y: 5 }, Point { x: 2, y: 5 }),
|
||||
(&Point { x: 9, y: 7 }, &Point { x: 2, y: 3 })
|
||||
));
|
||||
assert_eq!(part2(PROVIDED).unwrap(), 24);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_real() {
|
||||
assert_eq!(part2(INPUT).unwrap(), 1577956170);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,3 +6,4 @@ pub mod day05;
|
|||
pub mod day06;
|
||||
pub mod day07;
|
||||
pub mod day08;
|
||||
pub mod day09;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use aoc2025::day05;
|
|||
use aoc2025::day06;
|
||||
use aoc2025::day07;
|
||||
use aoc2025::day08;
|
||||
use aoc2025::day09;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let days: &[DayFunc] = &[
|
||||
|
|
@ -21,6 +22,7 @@ fn main() -> Result<()> {
|
|||
day06::run,
|
||||
day07::run,
|
||||
day08::run,
|
||||
day09::run,
|
||||
];
|
||||
|
||||
aoc::run(days)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue