generated from fspoettel/advent-of-code-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path11.rs
124 lines (112 loc) · 2.99 KB
/
11.rs
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
118
119
120
121
122
123
124
advent_of_code::solution!(11);
pub fn part_one(input: &str) -> Option<u128> {
let m = Map::new(input, 2);
m.galaxies
.iter()
.enumerate()
.map(|(i, pos)| {
let mut distance = 0;
for other in &m.galaxies[i..] {
distance += m.distance(pos, other);
}
distance
})
.sum::<u128>()
.into()
}
pub fn part_two(input: &str) -> Option<u128> {
let m = Map::new(input, 1000000);
m.galaxies
.iter()
.enumerate()
.map(|(i, pos)| {
let mut distance = 0;
for other in &m.galaxies[i..] {
distance += m.distance(pos, other);
}
distance
})
.sum::<u128>()
.into()
}
#[derive(Debug)]
struct Map {
galaxies: Vec<Pos>,
y_weights: Vec<u128>,
x_weights: Vec<u128>,
}
#[derive(Debug)]
struct Pos {
x: i32,
y: i32,
}
impl Map {
fn new(input: &str, weight: u128) -> Self {
let mut galaxies = Vec::new();
let mut y_weights = Vec::new();
let mut x_weights = vec![0; input.split_once('\n').unwrap().0.len()];
for (y, line) in input.lines().enumerate() {
if line.contains('#') {
y_weights.push(1);
} else {
y_weights.push(weight);
}
for (x, c) in line.chars().enumerate() {
if c == '#' {
galaxies.push(Pos {
x: x as i32,
y: y as i32,
});
x_weights[x] += 1;
}
}
}
let x_weights = x_weights
.into_iter()
.map(|x| if x == 0 { weight } else { 1 })
.collect();
Self {
galaxies,
y_weights,
x_weights,
}
}
fn distance(&self, pos: &Pos, other: &Pos) -> u128 {
let mut distance = 0;
for x in pos.x.min(other.x)..=pos.x.max(other.x) {
distance += self.x_weights[x as usize];
}
for y in pos.y.min(other.y)..=pos.y.max(other.y) {
distance += self.y_weights[y as usize];
}
distance - 2
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(374));
}
#[test]
fn test_part_two() {
let input = &advent_of_code::template::read_file("examples", DAY);
let m = Map::new(input, 100);
let result: Option<u128> = m
.galaxies
.iter()
.enumerate()
.map(|(i, pos)| {
let mut distance = 0;
for other in &m.galaxies[i..] {
distance += m.distance(pos, other);
}
distance
})
.sum::<u128>()
.into();
assert_eq!(result, Some(8410));
}
}