2015/06
This commit is contained in:
202
2015/06/src/main.rs
Normal file
202
2015/06/src/main.rs
Normal 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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user