-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
123 lines (108 loc) · 3.11 KB
/
main.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
use std::collections::HashSet;
use std::str::FromStr;
#[derive(Debug)]
struct Grid {
size: usize,
on: HashSet<(usize, usize)>,
}
impl FromStr for Grid {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let lines = s.lines().collect::<Vec<&str>>();
let size = lines.len();
let mut on = HashSet::new();
for (x, line) in lines.iter().enumerate() {
for (y, ch) in line.chars().enumerate() {
match ch {
'#' => {
on.insert((x, y));
}
'.' => {
// off
}
_ => {
return Err(());
}
}
}
}
Ok(Grid { on: on, size: size })
}
}
impl Grid {
#[allow(dead_code)]
fn print(&self) {
for x in 0..self.size {
println!(
"{}",
(0..self.size)
.map(|y| if self.on.contains(&(x, y)) { '#' } else { '.' })
.collect::<String>()
);
}
}
fn light_corners(&mut self) {
self.on.insert((0, 0));
self.on.insert((0, self.size - 1));
self.on.insert((self.size - 1, 0));
self.on.insert((self.size - 1, self.size - 1));
}
fn next(&self) -> Grid {
let size = self.size;
let mut next = vec![];
for x in 0..size {
for y in 0..size {
let neighbors = (-1..=1)
.flat_map(|dx| (-1..=1).map(move |dy| (x as isize + dx, y as isize + dy)))
.filter(|(x, y)| *x >= 0 && *y >= 0 && *x < size as isize && *y < size as isize)
.map(|(x, y)| (x as usize, y as usize))
.filter(|(nx, ny)| (nx, ny) != (&x, &y))
.filter(|(x, y)| self.on.contains(&(*x, *y)))
.count();
let on = if self.on.contains(&(x, y)) {
neighbors == 2 || neighbors == 3
} else {
neighbors == 3
};
if on {
next.push((x, y));
}
}
}
Grid {
on: next.iter().cloned().collect::<HashSet<(usize, usize)>>(),
size: size,
}
}
fn on_count(&self) -> usize {
self.on.len()
}
}
fn part1(s: &str, steps: usize) -> usize {
let mut grid: Grid = s.parse().unwrap();
for _ in 0..steps {
grid = grid.next();
}
grid.on_count()
}
fn part2(s: &str, steps: usize) -> usize {
let mut grid: Grid = s.parse().unwrap();
grid.light_corners();
for _ in 0..steps {
grid = grid.next();
grid.light_corners();
}
grid.on_count()
}
fn main() {
println!("Part 1: {}", part1(include_str!("in.txt"), 100));
println!("Part 2: {}", part2(include_str!("in.txt"), 100));
}
#[test]
fn test_part1() {
assert_eq!(part1(include_str!("test.txt"), 4), 4);
}
#[test]
fn test_part2() {
assert_eq!(part2(include_str!("test.txt"), 5), 17);
}