aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

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 }