common.rs (3639B)
1 use std::cmp::{min, max}; 2 use std::ops::{Index, IndexMut}; 3 4 pub struct Map { 5 cells: Vec<Vec<bool>>, 6 pub xmin: usize, 7 pub xmax: usize, 8 pub ymin: usize, 9 pub ymax: usize 10 } 11 12 fn line_from_str(s: &str) -> Vec<(usize, usize)> { 13 let mut line = vec![]; 14 let mut i = 0; 15 while i < s.len() { 16 let mut j = s[i..].find(',').unwrap(); 17 let x = s[i..i+j].parse::<usize>().unwrap(); 18 i += j+1; 19 j = s[i..].find(|c| c == ' ' || c == '\n').unwrap(); 20 let y = s[i..i+j].parse::<usize>().unwrap(); 21 i += j+4; 22 line.push((x, y)); 23 } 24 line 25 } 26 27 impl Index<(usize, usize)> for Map { 28 type Output = bool; 29 fn index(&self, i: (usize, usize)) -> &bool { 30 self.validate_index(i); 31 &self.cells[i.1-self.ymin][i.0-self.xmin] 32 } 33 } 34 35 impl IndexMut<(usize, usize)> for Map { 36 fn index_mut(&mut self, i: (usize, usize)) -> &mut bool { 37 self.validate_index(i); 38 &mut self.cells[i.1-self.ymin][i.0-self.xmin] 39 } 40 } 41 42 impl Map { 43 fn in_bounds(&self, i: (usize, usize)) -> bool { 44 i.0 >= self.xmin && i.0 <= self.xmax && 45 i.1 >= self.ymin && i.1 <= self.ymax 46 } 47 48 fn validate_index(&self, i: (usize, usize)) { 49 if !self.in_bounds(i) { 50 panic!("Out of bounds: {} {} outside [{}, {}]x[{}, {}]", 51 i.0, i.1, self.xmin, self.xmax, self.ymin, self.ymax); 52 } 53 } 54 55 pub fn at(&self, i: (usize, usize)) -> bool { 56 self.in_bounds(i) && self[i] 57 } 58 59 fn set_bounds(&mut self, lines: &Vec<Vec<(usize, usize)>>) { 60 for l in lines { 61 for p in l { 62 self.xmin = min(self.xmin, p.0); 63 self.xmax = max(self.xmax, p.0); 64 self.ymin = min(self.ymin, p.1); 65 self.ymax = max(self.ymax, p.1+1); 66 } 67 } 68 69 // Part 2 requires a larger map 70 self.xmin = min(self.xmin, 500 - self.ymax - 1); 71 self.xmax = max(self.xmax, 500 + self.ymax + 1); 72 self.cells = vec![ 73 vec![false; self.xmax-self.xmin+1]; self.ymax-self.ymin+1 74 ]; 75 } 76 77 fn fill_line(&mut self, line: &Vec<(usize, usize)>) { 78 for i in 0..line.len()-1 { 79 if line[i].0 == line[i+1].0 { 80 let y0 = min(line[i].1, line[i+1].1); 81 let y1 = max(line[i].1, line[i+1].1); 82 for y in y0..=y1 { 83 self[(line[i].0, y)] = true; 84 } 85 } else { 86 let x0 = min(line[i].0, line[i+1].0); 87 let x1 = max(line[i].0, line[i+1].0); 88 for x in x0..=x1 { 89 self[(x, line[i].1)] = true; 90 } 91 } 92 } 93 } 94 95 fn from_lines(lines: &Vec<Vec<(usize, usize)>>) -> Map { 96 let mut map = Map { 97 cells: vec![], 98 xmin: 500, 99 xmax: 500, 100 ymin: 0, 101 ymax: 0 102 }; 103 map.set_bounds(lines); 104 for l in lines { map.fill_line(l); } 105 map 106 } 107 108 #[allow(dead_code)] 109 pub fn print(&self) { 110 println!("x: {} to {}", self.xmin, self.xmax); 111 println!("y: {} to {}", self.ymin, self.ymax); 112 for v in &self.cells { 113 for b in v { 114 print!("{}", if *b { '#' } else { '.' }); 115 } 116 println!(); 117 } 118 } 119 } 120 121 pub fn read_map_from_stdin() -> Map { 122 let mut lines = Vec::<Vec<(usize, usize)>>::new(); 123 let mut s = String::new(); 124 while std::io::stdin().read_line(&mut s).unwrap() > 0 { 125 lines.push(line_from_str(&s)); 126 s.clear(); 127 } 128 Map::from_lines(&lines) 129 }