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
|
extern crate advent_of_code_2018;
use advent_of_code_2018::*;
extern crate arrayvec;
use arrayvec::ArrayVec;
use std::error::Error;
use std::path::PathBuf;
use std::collections::HashMap;
// cargo watch -cs "cargo run --release --bin day_18"
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum State {
Open,
Trees,
Lumber
}
fn main() -> Result<(), Box<Error>> {
let input = read_file(&PathBuf::from("inputs/18.txt"))?;
// println!("Input: {:?}", input);
let map = input.iter().map(|line| {
line.chars().map(|c| match c {
'.' => State::Open,
'|' => State::Trees,
'#' => State::Lumber,
_ => panic!("Unknown character {}", c)
}).collect::<Vec<_>>()
}).collect::<Vec<_>>();
// debug!(map);
let after_10 = simulate(&map, 10);
let trees_count_10: usize = after_10.iter().map(|row| row.iter().filter(|&&x| x == State::Trees).count()).sum();
let lumber_count_10: usize = after_10.iter().map(|row| row.iter().filter(|&&x| x == State::Lumber).count()).sum();
debug!(trees_count_10);
debug!(lumber_count_10);
debug!(trees_count_10 * lumber_count_10);
let after_many = simulate(&map, 1000000000);
let trees_count_many: usize = after_many.iter().map(|row| row.iter().filter(|&&x| x == State::Trees).count()).sum();
let lumber_count_many: usize = after_many.iter().map(|row| row.iter().filter(|&&x| x == State::Lumber).count()).sum();
debug!(trees_count_many);
debug!(lumber_count_many);
debug!(trees_count_many * lumber_count_many);
Ok(())
}
fn simulate(start_map: &Vec<Vec<State>>, duration: u32) -> Vec<Vec<State>> {
let mut previous_maps = HashMap::new();
let mut map = start_map.clone();
let mut t = 0;
while t < duration {
let map0 = map.clone();
for y in 0..map.len() {
for x in 0..map[y].len() {
let adjacent = [
(x.wrapping_sub(1), y.wrapping_sub(1)),
(x, y.wrapping_sub(1)),
(x+1, y.wrapping_sub(1)),
(x.wrapping_sub(1), y),
(x+1, y),
(x.wrapping_sub(1), y+1),
(x, y+1),
(x+1, y+1)
].iter().map(|&(other_x,other_y)| {
if other_y >= map0.len() || other_x >= map0[other_y].len() {
State::Open
} else {
map0[other_y][other_x]
}
}).collect::<ArrayVec<[State; 8]>>();
let adjacent_trees = adjacent.iter().filter(|&&x| x == State::Trees).count();
let adjacent_lumber = adjacent.iter().filter(|&&x| x == State::Lumber).count();
map[y][x] = match (map0[y][x], adjacent_trees, adjacent_lumber) {
(State::Open, trees, _) if trees >= 3 => State::Trees,
(State::Open, _, _) => State::Open,
(State::Trees, _, lumber) if lumber >= 3 => State::Lumber,
(State::Trees, _, _) => State::Trees,
(State::Lumber, trees, lumber) if trees >= 1 && lumber >= 1 => State::Lumber,
(State::Lumber, _, _) => State::Open
}
}
}
t += match previous_maps.get(&map) {
Some(previous_t) => {
let period = t + 1 - previous_t;
let whole_periods = (duration - t - 1) / period;
(period * whole_periods) + 1
},
None => 1
};
previous_maps.insert(map.clone(), t);
}
map
}
fn debug_print(map: &Vec<Vec<State>>) {
for row in map {
for c in row {
print!("{}", match c {
State::Open => '.',
State::Trees => '|',
State::Lumber => '#'
});
}
println!();
}
println!();
println!();
}
|