Skip to content

Commit 43caec6

Browse files
committed
Day 11 puzzle 2
1 parent e70d5b7 commit 43caec6

File tree

3 files changed

+168
-66
lines changed

3 files changed

+168
-66
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
| 7 | [src/solutions/day07.rs](src/solutions/day07.rs) | ⭐️⭐️ |
1919
| 8 | [src/solutions/day08.rs](src/solutions/day08.rs) | ⭐️⭐️ |
2020
| 9 | [src/solutions/day09.rs](src/solutions/day09.rs) | ⭐️⭐️ |
21-
<!-- | 10 | [src/solutions/day10.rs](src/solutions/day10.rs) | ⭐️⭐️ | -->
22-
<!-- | 11 | [src/solutions/day11.rs](src/solutions/day11.rs) | ⭐️⭐️ | -->
21+
| 10 | [src/solutions/day10.rs](src/solutions/day10.rs) | ⭐️ |
22+
| 11 | [src/solutions/day11.rs](src/solutions/day11.rs) | ⭐️⭐️ |
2323
<!-- | 12 | [src/solutions/day12.rs](src/solutions/day12.rs) | ⭐️⭐️ | -->
2424
<!-- | 13 | [src/solutions/day13.rs](src/solutions/day13.rs) | ⭐️⭐️ | -->
2525
<!-- | 14 | [src/solutions/day14.rs](src/solutions/day14.rs) | ⭐️⭐️ | -->

src/solutions/day11.rs

Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,42 @@
11
use crate::data::load;
22
use ndarray::prelude::*;
3-
use thiserror::Error;
4-
5-
#[derive(Error, Debug, PartialEq, Eq)]
6-
pub enum PuzzleErr {
7-
#[error("Unknown pipe character: {}.", .0)]
8-
UnknownPipeChar(String),
9-
}
3+
use std::iter::zip;
104

115
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126
struct Coord {
137
r: usize,
148
c: usize,
159
}
1610

11+
impl Coord {
12+
fn t(&self) -> Self {
13+
Self {
14+
r: self.c,
15+
c: self.r,
16+
}
17+
}
18+
19+
fn dist(&self, other: &Self) -> usize {
20+
self.r.abs_diff(other.r) + self.c.abs_diff(other.c)
21+
}
22+
}
23+
1724
#[derive(Debug, Clone)]
1825
struct CosmicMap {
1926
arr: Array2<u8>,
2027
galaxies: Vec<Coord>,
2128
}
2229

23-
fn parse_map(input: &str) -> Result<CosmicMap, PuzzleErr> {
30+
impl CosmicMap {
31+
fn t(&self) -> Self {
32+
Self {
33+
arr: self.arr.t().to_owned(),
34+
galaxies: self.galaxies.iter().map(|c| c.t()).collect(),
35+
}
36+
}
37+
}
38+
39+
fn parse_map(input: &str) -> CosmicMap {
2440
let lines = input.trim().lines().map(|l| l.trim()).collect::<Vec<_>>();
2541
let width = lines.first().unwrap().len();
2642
let height = lines.len();
@@ -34,63 +50,57 @@ fn parse_map(input: &str) -> Result<CosmicMap, PuzzleErr> {
3450
}
3551
}
3652
}
37-
Ok(CosmicMap { arr, galaxies })
53+
CosmicMap { arr, galaxies }
3854
}
3955

40-
fn _expand_arr_rows(arr: Array2<u8>) -> Array2<u8> {
41-
let mut vecs = Vec::new();
42-
43-
let mut nrows = 0;
44-
for r in arr.rows() {
45-
nrows += 1;
46-
vecs.extend_from_slice(r.to_vec().as_slice());
47-
if r.sum() == 0 {
48-
nrows += 1;
49-
vecs.extend_from_slice(r.to_vec().as_slice());
56+
fn calculate_dists(coords: &[Coord]) -> Vec<usize> {
57+
let mut dists = Vec::new();
58+
for (i, a) in coords.iter().enumerate() {
59+
for b in coords[(i + 1)..].iter() {
60+
dists.push(a.dist(b))
5061
}
5162
}
52-
Array2::from_shape_vec((nrows, arr.ncols()), vecs).unwrap()
63+
dists
5364
}
5465

55-
fn _locate_galaxies(arr: &Array2<u8>) -> Vec<Coord> {
56-
let mut galaxies = Vec::new();
57-
for i in 0..arr.nrows() {
58-
for j in 0..arr.ncols() {
59-
if arr.get((i, j)).unwrap() == &1 {
60-
galaxies.push(Coord { r: i, c: j })
61-
}
66+
fn expand_galaxies(map: &CosmicMap, ex_rate: usize) -> Vec<Coord> {
67+
let x = match ex_rate {
68+
0..=1 => ex_rate,
69+
_ => ex_rate - 1,
70+
};
71+
let coords = map.galaxies.clone();
72+
let mut add_rs = (0..coords.len()).map(|_| 0).collect::<Vec<_>>();
73+
74+
for i in 0..map.arr.nrows() {
75+
if map.arr.row(i).sum() == 0 {
76+
add_rs = zip(&coords, add_rs)
77+
.map(|(coord, add_r)| if coord.r > i { add_r + x } else { add_r })
78+
.collect();
6279
}
6380
}
64-
galaxies
65-
}
6681

67-
fn expand_map(map: CosmicMap) -> CosmicMap {
68-
let arr = _expand_arr_rows(map.arr);
69-
let arr = _expand_arr_rows(arr.t().to_owned()).t().to_owned();
70-
let galaxies = _locate_galaxies(&arr);
71-
CosmicMap { arr, galaxies }
82+
zip(coords, add_rs)
83+
.map(|(coord, add_r)| Coord {
84+
r: coord.r + add_r,
85+
c: coord.c,
86+
})
87+
.collect()
7288
}
7389

74-
fn calculate_dists(map: &CosmicMap) -> Vec<usize> {
75-
let mut dists = Vec::new();
76-
for (i, a) in map.galaxies.iter().enumerate() {
77-
for b in map.galaxies[(i + 1)..].iter() {
78-
dists.push(a.r.abs_diff(b.r) + a.c.abs_diff(b.c))
79-
}
80-
}
81-
dists
90+
fn _solve(input: &str, expansion_size: usize) -> usize {
91+
let mut map = parse_map(input);
92+
map.galaxies = expand_galaxies(&map, expansion_size);
93+
map = map.t();
94+
map.galaxies = expand_galaxies(&map, expansion_size);
95+
calculate_dists(&map.galaxies).iter().sum()
8296
}
8397

84-
pub fn puzzle_1(input: &str) -> Result<usize, PuzzleErr> {
85-
let map = parse_map(input)?;
86-
log::info!("STARTING MAP:\n{:?}", map.arr);
87-
log::info!("Galaxy locations: {:?}", map.galaxies);
88-
89-
let map = expand_map(map);
90-
log::info!("EXPANDED MAP:\n{:?}", map.arr);
91-
log::info!("Galaxy locations: {:?}", map.galaxies);
98+
pub fn puzzle_1(input: &str) -> usize {
99+
_solve(input, 1)
100+
}
92101

93-
Ok(calculate_dists(&map).iter().sum())
102+
pub fn puzzle_2(input: &str, expansion_size: usize) -> usize {
103+
_solve(input, expansion_size)
94104
}
95105

96106
pub fn main(data_dir: &str) {
@@ -99,17 +109,11 @@ pub fn main(data_dir: &str) {
99109

100110
// Puzzle 1.
101111
let answer_1 = puzzle_1(&data);
102-
match answer_1 {
103-
Ok(x) => println!(" Puzzle 1: {}", x),
104-
Err(e) => panic!("No solution to puzzle 1: {}.", e),
105-
}
106-
assert_eq!(answer_1, Ok(9724940));
112+
println!(" Puzzle 1: {}", answer_1);
113+
assert_eq!(answer_1, 9724940);
107114

108115
// Puzzle 2.
109-
// let answer_2 = puzzle_2(&data);
110-
// match answer_2 {
111-
// Ok(x) => println!(" Puzzle 2: {}", x),
112-
// Err(e) => panic!("No solution to puzzle 2: {}", e),
113-
// }
114-
// assert_eq!(answer_2, Ok(933))
116+
let answer_2 = puzzle_2(&data, 1000000);
117+
println!(" Puzzle 1: {}", answer_2);
118+
assert_eq!(answer_2, 569052586852);
115119
}

tests/test_day11.rs

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use aoc_2023::solutions::day11::puzzle_1;
1+
use aoc_2023::solutions::day11::{puzzle_1, puzzle_2};
22

33
const EXAMPLE_INPUT_1: &str = "
44
...#......
@@ -16,5 +16,103 @@ const EXAMPLE_INPUT_1: &str = "
1616
#[test]
1717
fn puzzle_1_example_1() {
1818
let _ = env_logger::try_init();
19-
assert_eq!(puzzle_1(self::EXAMPLE_INPUT_1), Ok(374));
19+
assert_eq!(puzzle_1(self::EXAMPLE_INPUT_1), 374);
20+
}
21+
22+
#[test]
23+
fn puzzle_2_example_1() {
24+
let _ = env_logger::try_init();
25+
assert_eq!(puzzle_2(self::EXAMPLE_INPUT_1, 1), 374);
26+
}
27+
28+
// const EXAMPLE_INPUT_2: &str = "
29+
// .....
30+
// .#...
31+
// .....
32+
// ....#
33+
// ";
34+
35+
// #[test]
36+
// fn puzzle_2_example_2() {
37+
// let _ = env_logger::try_init();
38+
// assert_eq!(puzzle_2(self::EXAMPLE_INPUT_2, 0), 5);
39+
// assert_eq!(puzzle_2(self::EXAMPLE_INPUT_2, 1), 8);
40+
// assert_eq!(puzzle_2(self::EXAMPLE_INPUT_2, 2), 11);
41+
// assert_eq!(puzzle_2(self::EXAMPLE_INPUT_2, 10), 3 * 10 + 5);
42+
// }
43+
44+
#[test]
45+
fn puzzle_2_example_3() {
46+
let _ = env_logger::try_init();
47+
assert_eq!(puzzle_2(self::EXAMPLE_INPUT_1, 10), 1030);
48+
}
49+
50+
#[test]
51+
fn puzzle_2_example_4() {
52+
let _ = env_logger::try_init();
53+
assert_eq!(puzzle_2(self::EXAMPLE_INPUT_1, 100), 8410);
54+
}
55+
56+
const EX1_EXPECTED_OUT_X1: &str = "
57+
....#........
58+
.........#...
59+
#............
60+
.............
61+
.............
62+
........#....
63+
.#...........
64+
............#
65+
.............
66+
.............
67+
.........#...
68+
#....#.......
69+
";
70+
71+
#[test]
72+
fn puzzle_2_example_5() {
73+
let _ = env_logger::try_init();
74+
assert_eq!(
75+
puzzle_2(self::EXAMPLE_INPUT_1, 1),
76+
puzzle_2(self::EX1_EXPECTED_OUT_X1, 0)
77+
);
78+
}
79+
80+
const EX1_EXPECTED_OUT_X10: &str = "
81+
............#........................
82+
.........................#...........
83+
#....................................
84+
.....................................
85+
.....................................
86+
.....................................
87+
.....................................
88+
.....................................
89+
.....................................
90+
.....................................
91+
.....................................
92+
.....................................
93+
.....................................
94+
........................#............
95+
.#...................................
96+
....................................#
97+
.....................................
98+
.....................................
99+
.....................................
100+
.....................................
101+
.....................................
102+
.....................................
103+
.....................................
104+
.....................................
105+
.....................................
106+
.....................................
107+
.........................#...........
108+
#............#.......................
109+
";
110+
111+
#[test]
112+
fn puzzle_2_example_6() {
113+
let _ = env_logger::try_init();
114+
assert_eq!(
115+
puzzle_2(self::EXAMPLE_INPUT_1, 10),
116+
puzzle_2(self::EX1_EXPECTED_OUT_X10, 0),
117+
);
20118
}

0 commit comments

Comments
 (0)