This commit is contained in:
2016-12-03 21:42:08 +01:00
parent d419ccf025
commit 82a86b1a04
4 changed files with 615 additions and 0 deletions

202
2015/06/src/main.rs Normal file
View File

@@ -0,0 +1,202 @@
#[macro_use] extern crate lazy_static;
extern crate regex;
use std::io::{self, BufRead};
use std::str::FromStr;
use std::cmp;
use regex::Regex;
macro_rules! coords {
($caps:expr) => {{
(
(
$caps.at(1).unwrap().parse::<usize>().unwrap(),
$caps.at(2).unwrap().parse::<usize>().unwrap()
),
(
$caps.at(3).unwrap().parse::<usize>().unwrap(),
$caps.at(4).unwrap().parse::<usize>().unwrap()
)
)
}};
}
type Coords = ((usize, usize), (usize, usize));
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Instruction {
On(Coords),
Off(Coords),
Toggle(Coords)
}
impl FromStr for Instruction {
type Err = ();
fn from_str(s: &str) -> Result<Instruction, ()> {
lazy_static! {
static ref ON: Regex = Regex::new(r"turn on (\d+),(\d+) through (\d+),(\d+)").unwrap();
static ref OFF: Regex = Regex::new(r"turn off (\d+),(\d+) through (\d+),(\d+)").unwrap();
static ref TOGGLE: Regex = Regex::new(r"toggle (\d+),(\d+) through (\d+),(\d+)").unwrap();
}
if let Some(caps) = ON.captures(s) {
return Ok(Instruction::On(coords!(caps)));
}
else if let Some(caps) = OFF.captures(s) {
return Ok(Instruction::Off(coords!(caps)));
}
else if let Some(caps) = TOGGLE.captures(s) {
return Ok(Instruction::Toggle(coords!(caps)));
}
Err(())
}
}
pub struct Grid {
grid: Vec<Vec<i32>>
}
impl Grid {
pub fn new() -> Self {
Grid {
grid: vec![vec![0; 1000]; 1000]
}
}
pub fn process_lit(&mut self, instruction: Instruction) {
match instruction {
Instruction::On(coords) => self.update(coords, |_| 1),
Instruction::Off(coords) => self.update(coords, |_| 0),
Instruction::Toggle(coords) => self.update(coords, |x| if x > 0 { 0 } else { 1 }),
}
}
pub fn count_lit(&self) -> usize {
self.grid.iter()
.map(|row| row.iter().filter(|x| **x > 0).count())
.sum()
}
pub fn process_brightness(&mut self, instruction: Instruction) {
match instruction {
Instruction::On(coords) => self.update(coords, |x| x + 1),
Instruction::Off(coords) => self.update(coords, |x| cmp::max(x - 1, 0)),
Instruction::Toggle(coords) => self.update(coords, |x| x + 2),
}
}
pub fn count_brightness(&self) -> i32 {
self.grid.iter()
.map(|row| {
let sum: i32 = row.iter().sum();
sum
})
.sum()
}
fn update<F>(&mut self, coords: Coords, func: F)
where F: Fn(i32) -> i32 {
let ((x1, y1), (x2, y2)) = coords;
for y in y1..y2 + 1 {
for x in x1..x2 + 1 {
self.grid[y][x] = func(self.grid[y][x]);
}
}
}
}
fn main() {
let stdin = io::stdin();
let instructions = stdin.lock().lines()
.filter_map(|x| x.ok())
.filter_map(|x| x.parse::<Instruction>().ok());
let mut grid_1 = Grid::new();
let mut grid_2 = Grid::new();
for instruction in instructions {
grid_1.process_lit(instruction);
grid_2.process_brightness(instruction);
}
println!("count={}", grid_1.count_lit());
println!("count={}", grid_2.count_brightness());
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_on_instructions() {
use super::Instruction::On;
assert_eq!(On(((887,9), (959, 629))), "turn on 887,9 through 959,629".parse::<Instruction>().unwrap());
}
#[test]
fn parse_off_instructions() {
use super::Instruction::Off;
assert_eq!(Off(((539,243), (559, 965))), "turn off 539,243 through 559,965".parse::<Instruction>().unwrap());
}
#[test]
fn parse_toggle_instructions() {
use super::Instruction::Toggle;
assert_eq!(Toggle(((720, 196), (897, 994))), "toggle 720,196 through 897,994".parse::<Instruction>().unwrap());
}
#[test]
fn grid_empty() {
let grid = Grid::new();
assert_eq!(0, grid.count_lit());
}
#[test]
fn example_01() {
let mut grid = Grid::new();
let instruction = "turn on 0,0 through 999,999".parse::<Instruction>().unwrap();
grid.process_lit(instruction);
assert_eq!(1_000_000, grid.count_lit());
}
#[test]
fn example_02() {
let mut grid = Grid::new();
let instruction = "turn on 0,0 through 999,0".parse::<Instruction>().unwrap();
grid.process_lit(instruction);
assert_eq!(1_000, grid.count_lit());
}
#[test]
fn example_04() {
let mut grid = Grid::new();
let instruction = "toggle 0,0 through 999,999".parse::<Instruction>().unwrap();
grid.process_brightness(instruction);
assert_eq!(2_000_000, grid.count_brightness());
}
}