[2016][rust][8.x]
change nywzyqzltotvrpkvxzsvzskmywpzskuz
commit 8c355890a5cf6a0e0b21231782dde1a34b070103
author Alpha Chen <alpha.chen@gmail.com>
date
parent omktzmxu
diff --git a/2016/rust/src/day_08.rs b/2016/rust/src/day_08.rs
new file mode 100644
index 0000000..06952d3
--- /dev/null
+++ b/2016/rust/src/day_08.rs
@@ -0,0 +1,149 @@
+use std::collections::HashMap;
+use std::fmt;
+
+use regex::Regex;
+
+use errors::*;
+
+pub fn solve(input: &str) -> Result<String> {
+  let rect_re = Regex::new(r"rect (\d+)x(\d+)").unwrap();
+  let rotate_re = Regex::new(r"rotate (column x|row y)=(\d+) by (\d+)").unwrap();
+
+  let mut screen = Screen::new(50, 6);
+  for line in input.lines() {
+    if let Some(caps) = rect_re.captures(line) {
+      screen.rect(caps[1].parse().unwrap(), caps[2].parse().unwrap());
+    } else if let Some(caps) = rotate_re.captures(line) {
+      let index =  caps[2].parse().unwrap();
+      let count = caps[3].parse().unwrap();
+      if &caps[1] == "column x" {
+        screen.rotate_col(index, count);
+      } else if &caps[1] == "row y" {
+        screen.rotate_row(index, count);
+      }
+    } else {
+      return Err(format!("unexpected input: '{}'", line).into());
+    }
+  }
+
+  Ok(format!("{}", screen.pixels.iter().filter(|&(_, &v)| v).count()))
+  // Ok(format!("{}", screen))
+}
+
+#[derive(Eq,Hash,PartialEq)]
+struct Point(usize, usize);
+
+type Pixel = bool;
+
+pub struct Screen {
+  width: usize,
+  height: usize,
+  pixels: HashMap<Point, Pixel>,
+}
+
+impl Screen {
+  fn new(width: usize, height: usize) -> Self {
+    Screen {
+      width: width,
+      height: height,
+      pixels: HashMap::new(),
+    }
+  }
+
+  fn rect(&mut self, x: usize, y: usize) {
+    for x in 0..x {
+      for y in 0..y {
+        self.pixels.insert(Point(x, y), true);
+      }
+    }
+  }
+
+  fn rotate_col(&mut self, index: usize, count: usize) {
+    let count = count % self.height;
+
+    let mut col = (0..self.height)
+      .map(|y| self.pixels.get(&Point(index, y)).cloned().unwrap_or(false))
+      .collect::<Vec<_>>();
+    let col = Self::rotate(&mut col, count);
+
+    for (y, &pixel) in col.iter().enumerate() {
+      self.pixels.insert(Point(index, y), pixel);
+    }
+  }
+
+  fn rotate_row(&mut self, index: usize, count: usize) {
+    let count = count % self.width;
+
+    let mut row = (0..self.width)
+      .map(|x| self.pixels.get(&Point(x, index)).cloned().unwrap_or(false))
+      .collect::<Vec<_>>();
+    let row = Self::rotate(&mut row, count);
+
+    for (x, &pixel) in row.iter().enumerate() {
+      self.pixels.insert(Point(x, index), pixel);
+    }
+  }
+
+  fn rotate<T: Clone>(v: &mut Vec<T>, count: usize) -> Vec<T> {
+    let count = v.len() - count - 1;
+    v[(count + 1)..].iter().chain(v[0...count].iter()).cloned().collect()
+  }
+}
+
+impl fmt::Display for Screen {
+  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    let s = (0..self.height)
+      .map(|y| {
+        (0..self.width)
+          .map(|x| {
+            if self.pixels.get(&Point(x, y)).cloned().unwrap_or(false) {
+              '#'
+            } else {
+              '.'
+            }
+          })
+          .collect::<String>()
+      })
+      .collect::<Vec<_>>()
+      .join("\n");
+    write!(f, "{}", s)
+  }
+}
+
+#[cfg(test)]
+mod tests {
+  use super::*;
+
+  #[test]
+  fn test_screen() {
+    let mut screen = Screen::new(7, 3);
+    assert_eq!(format!("{}", screen),
+               ".......
+.......
+.......");
+
+    screen.rect(3, 2);
+    assert_eq!(format!("{}", screen),
+               "###....
+###....
+.......");
+
+    screen.rotate_col(1, 1);
+    assert_eq!(format!("{}", screen),
+               "#.#....
+###....
+.#.....");
+
+    screen.rotate_row(0, 4);
+    assert_eq!(format!("{}", screen),
+               "....#.#
+###....
+.#.....");
+
+    screen.rotate_col(1, 1);
+    assert_eq!(format!("{}", screen),
+               ".#..#.#
+#.#....
+.#.....");
+  }
+}
diff --git a/2016/rust/src/lib.rs b/2016/rust/src/lib.rs
index 2e9fa82..3ff0012 100644
--- a/2016/rust/src/lib.rs
+++ b/2016/rust/src/lib.rs
@@ -1,3 +1,4 @@
+#![feature(inclusive_range_syntax)]
 #![recursion_limit = "1024"]
 
 #[macro_use]
@@ -13,3 +14,4 @@ pub mod day_04;
 pub mod day_05;
 pub mod day_06;
 pub mod day_07;
+pub mod day_08;
diff --git a/2016/rust/src/main.rs b/2016/rust/src/main.rs
index ab72f40..d984eee 100644
--- a/2016/rust/src/main.rs
+++ b/2016/rust/src/main.rs
@@ -10,7 +10,7 @@ fn main() {
     let mut input = String::new();
     io::stdin().read_to_string(&mut input).ok();
 
-    let solution = day_07::solve(&input)?;
+    let solution = day_08::solve(&input)?;
     println!("{}", solution);
 
     Ok(())