Skip to content

Commit 967f694

Browse files
committed
feat(2022): refactor days 13-15
Refactored Days 13, 14, and 15 of 2022 to use the common framework. Successfully migrated solutions, integrated them into the runner, and fixed all compilation and performance-related issues.
1 parent f4f5e26 commit 967f694

10 files changed

Lines changed: 914 additions & 0 deletions

File tree

2022/inputs/13/prod.txt

Lines changed: 449 additions & 0 deletions
Large diffs are not rendered by default.

2022/inputs/13/test.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[1,1,3,1,1]
2+
[1,1,5,1,1]
3+
4+
[[1],[2,3,4]]
5+
[[1],4]
6+
7+
[9]
8+
[[8,7,6]]
9+
10+
[[4,4],4,4]
11+
[[4,4],4,4,4]
12+
13+
[7,7,7,7]
14+
[7,7,7]
15+
16+
[]
17+
[3]
18+
19+
[[[]]]
20+
[[]]
21+
22+
[1,[2,[3,[4,[5,6,7]]]],8,9]
23+
[1,[2,[3,[4,[5,6,0]]]],8,9]

2022/inputs/14/prod.txt

Lines changed: 164 additions & 0 deletions
Large diffs are not rendered by default.

2022/inputs/14/test.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
498,4 -> 498,6 -> 496,6
2+
503,4 -> 502,4 -> 502,9 -> 494,9

2022/inputs/15/prod.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Sensor at x=2983166, y=2813277: closest beacon is at x=3152133, y=2932891
2+
Sensor at x=2507490, y=122751: closest beacon is at x=1515109, y=970092
3+
Sensor at x=3273116, y=2510538: closest beacon is at x=3152133, y=2932891
4+
Sensor at x=1429671, y=995389: closest beacon is at x=1515109, y=970092
5+
Sensor at x=2465994, y=2260162: closest beacon is at x=2734551, y=2960647
6+
Sensor at x=2926899, y=3191882: closest beacon is at x=2734551, y=2960647
7+
Sensor at x=1022491, y=1021177: closest beacon is at x=1515109, y=970092
8+
Sensor at x=1353273, y=1130973: closest beacon is at x=1515109, y=970092
9+
Sensor at x=1565476, y=2081049: closest beacon is at x=1597979, y=2000000
10+
Sensor at x=1841125, y=1893566: closest beacon is at x=1597979, y=2000000
11+
Sensor at x=99988, y=71317: closest beacon is at x=86583, y=-1649857
12+
Sensor at x=3080600, y=3984582: closest beacon is at x=3175561, y=4138060
13+
Sensor at x=3942770, y=3002123: closest beacon is at x=3724687, y=3294321
14+
Sensor at x=1572920, y=2031447: closest beacon is at x=1597979, y=2000000
15+
Sensor at x=218329, y=1882777: closest beacon is at x=1597979, y=2000000
16+
Sensor at x=1401723, y=1460526: closest beacon is at x=1515109, y=970092
17+
Sensor at x=2114094, y=985978: closest beacon is at x=1515109, y=970092
18+
Sensor at x=3358586, y=3171857: closest beacon is at x=3152133, y=2932891
19+
Sensor at x=1226284, y=3662922: closest beacon is at x=2514367, y=3218259
20+
Sensor at x=3486366, y=3717867: closest beacon is at x=3724687, y=3294321
21+
Sensor at x=1271873, y=831354: closest beacon is at x=1515109, y=970092
22+
Sensor at x=3568311, y=1566400: closest beacon is at x=3152133, y=2932891
23+
Sensor at x=3831960, y=3146611: closest beacon is at x=3724687, y=3294321
24+
Sensor at x=2505534, y=3196726: closest beacon is at x=2514367, y=3218259
25+
Sensor at x=2736967, y=3632098: closest beacon is at x=2514367, y=3218259
26+
Sensor at x=3963402, y=3944423: closest beacon is at x=3724687, y=3294321
27+
Sensor at x=1483115, y=2119639: closest beacon is at x=1597979, y=2000000

2022/inputs/15/test.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
2+
Sensor at x=9, y=16: closest beacon is at x=10, y=16
3+
Sensor at x=13, y=2: closest beacon is at x=15, y=3
4+
Sensor at x=12, y=14: closest beacon is at x=10, y=16
5+
Sensor at x=10, y=20: closest beacon is at x=10, y=16
6+
Sensor at x=14, y=17: closest beacon is at x=10, y=16
7+
Sensor at x=8, y=7: closest beacon is at x=2, y=10
8+
Sensor at x=2, y=0: closest beacon is at x=2, y=10
9+
Sensor at x=0, y=11: closest beacon is at x=2, y=10
10+
Sensor at x=20, y=14: closest beacon is at x=25, y=17
11+
Sensor at x=17, y=20: closest beacon is at x=21, y=22
12+
Sensor at x=16, y=7: closest beacon is at x=15, y=3
13+
Sensor at x=14, y=3: closest beacon is at x=15, y=3
14+
Sensor at x=20, y=1: closest beacon is at x=15, y=3

2022/src/day13.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use aoc_rust_common::Solution;
2+
use std::fmt::Display;
3+
use nom::{
4+
branch::alt,
5+
bytes::complete::tag,
6+
character::complete::i64 as nom_i64,
7+
multi::separated_list0,
8+
sequence::delimited,
9+
IResult,
10+
Parser,
11+
};
12+
13+
pub struct Day13;
14+
15+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
16+
enum Packet {
17+
Int(i64),
18+
List(Vec<Packet>),
19+
}
20+
21+
fn parse_packet(input: &str) -> IResult<&str, Packet> {
22+
alt((
23+
nom_i64.map(Packet::Int),
24+
delimited(
25+
tag("["),
26+
separated_list0(tag(","), parse_packet),
27+
tag("]"),
28+
).map(Packet::List),
29+
))(input)
30+
}
31+
32+
impl Solution for Day13 {
33+
fn year(&self) -> u32 { 2022 }
34+
fn day(&self) -> u32 { 13 }
35+
36+
fn part1(&self, input: &str) -> Box<dyn Display> {
37+
let mut count = 0;
38+
for (i, pair) in input.split("\n\n").enumerate() {
39+
let mut lines = pair.lines();
40+
let left = parse_packet(lines.next().unwrap()).unwrap().1;
41+
let right = parse_packet(lines.next().unwrap()).unwrap().1;
42+
if left < right { count += i + 1; }
43+
}
44+
Box::new(count)
45+
}
46+
47+
fn part2(&self, input: &str) -> Box<dyn Display> {
48+
let mut packets: Vec<Packet> = input
49+
.lines()
50+
.filter(|l| !l.is_empty())
51+
.map(|l| parse_packet(l).unwrap().1)
52+
.collect();
53+
54+
let div1 = Packet::List(vec![Packet::List(vec![Packet::Int(2)])]);
55+
let div2 = Packet::List(vec![Packet::List(vec![Packet::Int(6)])]);
56+
packets.push(div1.clone());
57+
packets.push(div2.clone());
58+
packets.sort();
59+
60+
let pos1 = packets.iter().position(|e| e == &div1).unwrap() + 1;
61+
let pos2 = packets.iter().position(|e| e == &div2).unwrap() + 1;
62+
Box::new(pos1 * pos2)
63+
}
64+
}

2022/src/day14.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use aoc_rust_common::Solution;
2+
use std::fmt::Display;
3+
4+
pub struct Day14;
5+
6+
#[derive(Clone, Copy)]
7+
enum Tile { Rock, Sand, Air }
8+
9+
impl Solution for Day14 {
10+
fn year(&self) -> u32 { 2022 }
11+
fn day(&self) -> u32 { 14 }
12+
13+
fn part1(&self, input: &str) -> Box<dyn Display> {
14+
let mut grid = parse(input);
15+
let max_y = *grid.keys().map(|p| &p.1).max().unwrap();
16+
let mut sand_count = 0;
17+
'outer: loop {
18+
let mut sand = (500, 0);
19+
loop {
20+
if sand.1 > max_y { break 'outer; }
21+
if !grid.contains_key(&(sand.0, sand.1 + 1)) { sand.1 += 1; }
22+
else if !grid.contains_key(&(sand.0 - 1, sand.1 + 1)) { sand.0 -= 1; sand.1 += 1; }
23+
else if !grid.contains_key(&(sand.0 + 1, sand.1 + 1)) { sand.0 += 1; sand.1 += 1; }
24+
else {
25+
grid.insert(sand, Tile::Sand);
26+
sand_count += 1;
27+
break;
28+
}
29+
}
30+
}
31+
Box::new(sand_count)
32+
}
33+
34+
fn part2(&self, input: &str) -> Box<dyn Display> {
35+
let mut grid = parse(input);
36+
let max_y = *grid.keys().map(|p| &p.1).max().unwrap();
37+
let mut sand_count = 0;
38+
loop {
39+
let mut sand = (500, 0);
40+
loop {
41+
if sand.1 == max_y + 1 {
42+
grid.insert(sand, Tile::Sand);
43+
sand_count += 1;
44+
break;
45+
}
46+
if !grid.contains_key(&(sand.0, sand.1 + 1)) { sand.1 += 1; }
47+
else if !grid.contains_key(&(sand.0 - 1, sand.1 + 1)) { sand.0 -= 1; sand.1 += 1; }
48+
else if !grid.contains_key(&(sand.0 + 1, sand.1 + 1)) { sand.0 += 1; sand.1 += 1; }
49+
else {
50+
grid.insert(sand, Tile::Sand);
51+
sand_count += 1;
52+
if sand == (500, 0) { return Box::new(sand_count); }
53+
break;
54+
}
55+
}
56+
}
57+
}
58+
}
59+
60+
fn parse(input: &str) -> std::collections::HashMap<(i32, i32), Tile> {
61+
let mut grid = std::collections::HashMap::new();
62+
for line in input.lines() {
63+
let coords: Vec<(i32, i32)> = line.split(" -> ").map(|p| {
64+
let mut parts = p.split(',');
65+
(parts.next().unwrap().parse().unwrap(), parts.next().unwrap().parse().unwrap())
66+
}).collect();
67+
for i in 0..coords.len() - 1 {
68+
let (x1, y1) = coords[i];
69+
let (x2, y2) = coords[i+1];
70+
for x in min(x1, x2)..=max(x1, x2) {
71+
for y in min(y1, y2)..=max(y1, y2) {
72+
grid.insert((x, y), Tile::Rock);
73+
}
74+
}
75+
}
76+
}
77+
grid
78+
}
79+
80+
fn min(a: i32, b: i32) -> i32 { if a < b { a } else { b } }
81+
fn max(a: i32, b: i32) -> i32 { if a > b { a } else { b } }

2022/src/day15.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use aoc_rust_common::Solution;
2+
use std::fmt::Display;
3+
use std::collections::{HashMap, HashSet};
4+
use itertools::Itertools;
5+
6+
pub struct Day15;
7+
8+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9+
struct Coord { col: i32, row: i32 }
10+
11+
impl Coord {
12+
fn manhattan(&self, other: &Self) -> i32 {
13+
(self.row - other.row).abs() + (self.col - other.col).abs()
14+
}
15+
}
16+
17+
fn parse(input: &str) -> Vec<[Coord; 2]> {
18+
input.lines().map(|line| {
19+
let (s_str, b_str) = line.split_once(": ").unwrap();
20+
let (sx, sy) = s_str.strip_prefix("Sensor at ").unwrap().split_once(", ").unwrap();
21+
let (bx, by) = b_str.strip_prefix("closest beacon is at ").unwrap().split_once(", ").unwrap();
22+
[
23+
Coord { col: sx.strip_prefix("x=").unwrap().parse().unwrap(), row: sy.strip_prefix("y=").unwrap().parse().unwrap() },
24+
Coord { col: bx.strip_prefix("x=").unwrap().parse().unwrap(), row: by.strip_prefix("y=").unwrap().parse().unwrap() },
25+
]
26+
}).collect()
27+
}
28+
29+
fn get_row_ranges(row: i32, pairs: &[[Coord; 2]]) -> Vec<std::ops::RangeInclusive<i32>> {
30+
let mut ranges: Vec<std::ops::RangeInclusive<i32>> = pairs.iter().filter_map(|p| {
31+
let radius = p[0].manhattan(&p[1]);
32+
let dist_to_row = (p[0].row - row).abs();
33+
if dist_to_row <= radius {
34+
let offset = radius - dist_to_row;
35+
Some(p[0].col - offset..=p[0].col + offset)
36+
} else { None }
37+
}).collect();
38+
ranges.sort_unstable_by_key(|r| *r.start());
39+
40+
let mut merged = Vec::new();
41+
if !ranges.is_empty() {
42+
let mut curr = ranges[0].clone();
43+
for next in ranges.into_iter().skip(1) {
44+
if *next.start() <= *curr.end() + 1 {
45+
curr = *curr.start()..=*curr.end().max(next.end());
46+
} else {
47+
merged.push(curr);
48+
curr = next;
49+
}
50+
}
51+
merged.push(curr);
52+
}
53+
merged
54+
}
55+
56+
impl Solution for Day15 {
57+
fn year(&self) -> u32 { 2022 }
58+
fn day(&self) -> u32 { 15 }
59+
60+
fn part1(&self, input: &str) -> Box<dyn Display> {
61+
let pairs = parse(input);
62+
let row = 2_000_000;
63+
let ranges = get_row_ranges(row, &pairs);
64+
let count: i32 = ranges.iter().map(|r| r.end() - r.start() + 1).sum();
65+
let beacons: HashSet<i32> = pairs.iter().filter(|p| p[1].row == row).map(|p| p[1].col).collect();
66+
Box::new(count as usize - beacons.len())
67+
}
68+
69+
fn part2(&self, input: &str) -> Box<dyn Display> {
70+
let pairs = parse(input);
71+
let max_coord = 4_000_000;
72+
for row in 0..=max_coord {
73+
let ranges = get_row_ranges(row, &pairs);
74+
if ranges.len() > 1 {
75+
let col = ranges[0].end() + 1;
76+
return Box::new(col as i64 * 4_000_000 + row as i64);
77+
}
78+
}
79+
Box::new(0)
80+
}
81+
}

2022/src/main.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ mod day09;
77
mod day10;
88
mod day11;
99
mod day12;
10+
mod day13;
11+
mod day14;
12+
mod day15;
1013
use aoc_rust_common::run_solution;
1114
use day04::Day04;
1215
use day05::Day05;
@@ -17,6 +20,9 @@ use day09::Day09;
1720
use day10::Day10;
1821
use day11::Day11;
1922
use day12::Day12;
23+
use day13::Day13;
24+
use day14::Day14;
25+
use day15::Day15;
2026

2127
fn main() {
2228
run_solution(Day04);
@@ -28,4 +34,7 @@ fn main() {
2834
run_solution(Day10);
2935
run_solution(Day11);
3036
run_solution(Day12);
37+
run_solution(Day13);
38+
run_solution(Day14);
39+
run_solution(Day15);
3140
}

0 commit comments

Comments
 (0)