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
125
126
127
128
129
|
use std::cmp::{min, max};
use std::ops::{Index, IndexMut};
pub struct Map {
cells: Vec<Vec<bool>>,
pub xmin: usize,
pub xmax: usize,
pub ymin: usize,
pub ymax: usize
}
fn line_from_str(s: &str) -> Vec<(usize, usize)> {
let mut line = vec![];
let mut i = 0;
while i < s.len() {
let mut j = s[i..].find(',').unwrap();
let x = s[i..i+j].parse::<usize>().unwrap();
i += j+1;
j = s[i..].find(|c| c == ' ' || c == '\n').unwrap();
let y = s[i..i+j].parse::<usize>().unwrap();
i += j+4;
line.push((x, y));
}
line
}
impl Index<(usize, usize)> for Map {
type Output = bool;
fn index(&self, i: (usize, usize)) -> &bool {
self.validate_index(i);
&self.cells[i.1-self.ymin][i.0-self.xmin]
}
}
impl IndexMut<(usize, usize)> for Map {
fn index_mut(&mut self, i: (usize, usize)) -> &mut bool {
self.validate_index(i);
&mut self.cells[i.1-self.ymin][i.0-self.xmin]
}
}
impl Map {
fn in_bounds(&self, i: (usize, usize)) -> bool {
i.0 >= self.xmin && i.0 <= self.xmax &&
i.1 >= self.ymin && i.1 <= self.ymax
}
fn validate_index(&self, i: (usize, usize)) {
if !self.in_bounds(i) {
panic!("Out of bounds: {} {} outside [{}, {}]x[{}, {}]",
i.0, i.1, self.xmin, self.xmax, self.ymin, self.ymax);
}
}
pub fn at(&self, i: (usize, usize)) -> bool {
self.in_bounds(i) && self[i]
}
fn set_bounds(&mut self, lines: &Vec<Vec<(usize, usize)>>) {
for l in lines {
for p in l {
self.xmin = min(self.xmin, p.0);
self.xmax = max(self.xmax, p.0);
self.ymin = min(self.ymin, p.1);
self.ymax = max(self.ymax, p.1+1);
}
}
// Part 2 requires a larger map
self.xmin = min(self.xmin, 500 - self.ymax - 1);
self.xmax = max(self.xmax, 500 + self.ymax + 1);
self.cells = vec![
vec![false; self.xmax-self.xmin+1]; self.ymax-self.ymin+1
];
}
fn fill_line(&mut self, line: &Vec<(usize, usize)>) {
for i in 0..line.len()-1 {
if line[i].0 == line[i+1].0 {
let y0 = min(line[i].1, line[i+1].1);
let y1 = max(line[i].1, line[i+1].1);
for y in y0..=y1 {
self[(line[i].0, y)] = true;
}
} else {
let x0 = min(line[i].0, line[i+1].0);
let x1 = max(line[i].0, line[i+1].0);
for x in x0..=x1 {
self[(x, line[i].1)] = true;
}
}
}
}
fn from_lines(lines: &Vec<Vec<(usize, usize)>>) -> Map {
let mut map = Map {
cells: vec![],
xmin: 500,
xmax: 500,
ymin: 0,
ymax: 0
};
map.set_bounds(lines);
for l in lines { map.fill_line(l); }
map
}
#[allow(dead_code)]
pub fn print(&self) {
println!("x: {} to {}", self.xmin, self.xmax);
println!("y: {} to {}", self.ymin, self.ymax);
for v in &self.cells {
for b in v {
print!("{}", if *b { '#' } else { '.' });
}
println!();
}
}
}
pub fn read_map_from_stdin() -> Map {
let mut lines = Vec::<Vec<(usize, usize)>>::new();
let mut s = String::new();
while std::io::stdin().read_line(&mut s).unwrap() > 0 {
lines.push(line_from_str(&s));
s.clear();
}
Map::from_lines(&lines)
}
|