-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday14.rs
119 lines (106 loc) · 3.28 KB
/
day14.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
use std::collections::HashMap;
use aoc_lib::{
answer::Answer,
directions::{Cardinal, Direction},
matrix::Matrix,
solution::Solution,
vec2::Vec2,
};
pub struct Day14;
impl Solution for Day14 {
fn part_a(&self, input: &[String]) -> Answer {
let mut plateform = parse(input);
plateform.tilt(Cardinal::North);
plateform.score().into()
}
fn part_b(&self, input: &[String]) -> Answer {
let mut plateform = parse(input);
const ITERATIONS: usize = 1000000000;
let mut seen = HashMap::new();
for i in 0..ITERATIONS {
if let Some(previous) = seen.get(&plateform) {
if (ITERATIONS - i) % (i - previous) == 0 {
return plateform.score().into();
}
}
seen.insert(plateform.clone(), i);
plateform.tilt_cycle();
}
plateform.score().into()
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
struct Plateform {
plateform: Matrix<char>,
}
impl Plateform {
fn tilt_cycle(&mut self) {
for direction in Cardinal::all_counter_clockwise() {
self.tilt(direction);
}
}
fn tilt(&mut self, direction: Cardinal) {
let offset = direction.to_offset();
loop {
let mut moved = false;
for y in 0..self.plateform.rows {
for x in 0..self.plateform.cols {
let pos = Vec2::new(x, y);
let current = self.plateform[pos];
if current != 'O' {
continue;
}
let new_position = Vec2::<isize>::from(pos) + offset;
let el_at_new_position = self.plateform.get(&new_position);
if let Some(&np) = el_at_new_position {
if np != '.' {
continue;
}
self.plateform[Vec2::<usize>::try_from(&new_position).unwrap()] = 'O';
self.plateform[pos] = '.';
moved = true;
}
}
}
if !moved {
break;
}
}
}
fn score(&self) -> usize {
let mut score = 0;
for y in 0..self.plateform.rows {
for x in 0..self.plateform.cols {
let pos = Vec2::new(x, y);
if self.plateform[pos] == 'O' {
score += self.plateform.rows - y;
}
}
}
score
}
}
fn parse(input: &[String]) -> Plateform {
Plateform {
plateform: Matrix::from_chars(input),
}
}
#[cfg(test)]
mod test {
use aoc_lib::{self, answer::Answer, input, solution::Solution};
use super::Day14;
#[test]
fn test_a() {
let input =
input::read_file(&format!("{}day_14_test.txt", crate::FILES_PREFIX_TEST)).unwrap();
let answer = Day14.part_a(&input);
assert_eq!(<i32 as Into<Answer>>::into(136), answer);
}
#[test]
fn test_b() {
let input =
input::read_file(&format!("{}day_14_test.txt", crate::FILES_PREFIX_TEST)).unwrap();
let answer = Day14.part_b(&input);
assert_eq!(<i32 as Into<Answer>>::into(64), answer);
}
}