1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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
112
113
114
115
116
117
|
static DAY: u8 = 11;
fn main() {
let input = advent::read_lines(DAY);
println!("{DAY}a: {}", sum_path_lengths(&input));
println!("{DAY}b: {}", 0);
}
#[derive(PartialEq, Eq)]
struct Position {
x: isize,
y: isize,
}
struct GalaxyMap {
galaxies: Vec<Position>,
width: isize,
height: isize,
}
impl GalaxyMap {
fn new(input: &[String]) -> GalaxyMap {
let mut galaxies = Vec::new();
for (y, line) in input.iter().enumerate() {
for (x, c) in line.chars().enumerate() {
let pos = Position { x: x as isize, y: y as isize };
if c == '#' {
galaxies.push(pos);
}
}
}
let width = input[0].len() as isize;
let height = input.len() as isize;
GalaxyMap { galaxies, width, height }
}
fn expand_space(&mut self) {
let mut columns = Vec::new();
for x in 0 .. self.width {
if !self.galaxies.iter().any(|pos| pos.x == x) {
columns.push(x);
}
}
let mut rows = Vec::new();
for y in 0 .. self.height {
if !self.galaxies.iter().any(|pos| pos.y == y) {
rows.push(y);
}
}
for x in columns.iter().rev() {
for galaxy in self.galaxies.iter_mut().filter(|pos| pos.x > *x) {
galaxy.x += 1;
}
self.width += 1;
}
for y in rows.iter().rev() {
for galaxy in self.galaxies.iter_mut().filter(|pos| pos.y > *y) {
galaxy.y += 1;
}
self.height += 1;
}
}
fn _print_map(&self) {
for y in 0 .. self.height {
for x in 0 .. self.width {
if self.galaxies.iter().any(|pos| *pos == Position { x, y }) {
print!("#");
} else {
print!(".");
}
}
println!();
}
}
fn calculate_distances(&self) -> Vec<isize> {
let mut distances = Vec::new();
for (i, pos1) in self.galaxies.iter().enumerate() {
for pos2 in self.galaxies.iter().skip(i+1) {
let distance = pos1.x.abs_diff(pos2.x) + pos1.y.abs_diff(pos2.y);
distances.push(distance as isize);
}
}
distances
}
}
fn sum_path_lengths(input: &[String]) -> isize {
let mut galaxymap = GalaxyMap::new(input);
galaxymap.expand_space();
galaxymap.calculate_distances()
.iter()
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let input = [
"...#......",
".......#..",
"#.........",
"..........",
"......#...",
".#........",
".........#",
"..........",
".......#..",
"#...#.....",
].iter().map(|&x| String::from(x)).collect::<Vec<_>>();
assert_eq!(sum_path_lengths(&input), 374);
}
}
|