2016/10
This commit is contained in:
201
2016/10/src/main.rs
Normal file
201
2016/10/src/main.rs
Normal file
@@ -0,0 +1,201 @@
|
||||
#[macro_use] extern crate lazy_static;
|
||||
extern crate regex;
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::str::FromStr;
|
||||
use std::io::{self, BufRead};
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
|
||||
type Microchip = u32;
|
||||
type Id = u32;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Output {
|
||||
Bot(Id),
|
||||
Bin(Id)
|
||||
}
|
||||
|
||||
impl FromStr for Output {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Output, ()> {
|
||||
lazy_static! {
|
||||
static ref BOT: Regex = Regex::new(r"^bot (\d+)$").unwrap();
|
||||
static ref BIN: Regex = Regex::new(r"^output (\d+)$").unwrap();
|
||||
}
|
||||
|
||||
if let Some(caps) = BOT.captures(s) {
|
||||
let id = caps.at(1).unwrap().parse::<Id>().unwrap();
|
||||
|
||||
return Ok(Output::Bot(id));
|
||||
}
|
||||
|
||||
if let Some(caps) = BIN.captures(s) {
|
||||
let id = caps.at(1).unwrap().parse::<Id>().unwrap();
|
||||
|
||||
return Ok(Output::Bin(id));
|
||||
}
|
||||
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Instruction {
|
||||
Value(Microchip, Id),
|
||||
Bot(Id, Output, Output)
|
||||
}
|
||||
|
||||
impl FromStr for Instruction {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Instruction, ()> {
|
||||
lazy_static! {
|
||||
static ref VALUE: Regex = Regex::new(r"^value (\d+) goes to bot (\d+)$").unwrap();
|
||||
static ref BOT: Regex = Regex::new(r"^bot (\d+) gives low to (.*?) and high to (.*?)$").unwrap();
|
||||
}
|
||||
|
||||
if let Some(caps) = VALUE.captures(s) {
|
||||
let microchip = caps.at(1).unwrap().parse::<Microchip>().unwrap();
|
||||
let id = caps.at(2).unwrap().parse::<Id>().unwrap();
|
||||
|
||||
return Ok(Instruction::Value(microchip, id));
|
||||
}
|
||||
|
||||
if let Some(caps) = BOT.captures(s) {
|
||||
let id = caps.at(1).unwrap().parse::<Id>().unwrap();
|
||||
let low = caps.at(2).unwrap().parse::<Output>().unwrap();
|
||||
let high = caps.at(3).unwrap().parse::<Output>().unwrap();
|
||||
|
||||
return Ok(Instruction::Bot(id, low, high));
|
||||
}
|
||||
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Bot {
|
||||
microchips: Vec<Microchip>
|
||||
}
|
||||
|
||||
impl Bot {
|
||||
fn new() -> Self {
|
||||
Bot {
|
||||
microchips: Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Factory {
|
||||
bots: HashMap<Id, Bot>,
|
||||
output: HashMap<Id, Microchip>,
|
||||
log: HashMap<Id, Vec<(Microchip, Microchip)>>
|
||||
}
|
||||
|
||||
impl Factory {
|
||||
pub fn new() -> Self {
|
||||
Factory {
|
||||
bots: HashMap::new(),
|
||||
output: HashMap::new(),
|
||||
log: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(&mut self, instruction: &Instruction) -> Result<(), ()> {
|
||||
match instruction {
|
||||
&Instruction::Value(microchip, id) => {
|
||||
let mut bot = self.bots.entry(id).or_insert(Bot::new());
|
||||
|
||||
bot.microchips.push(microchip);
|
||||
|
||||
if bot.microchips.len() == 2 {
|
||||
bot.microchips.sort();
|
||||
|
||||
self.log.entry(id).or_insert(Vec::new())
|
||||
.push((bot.microchips[0], bot.microchips[1]));
|
||||
}
|
||||
}
|
||||
&Instruction::Bot(id, ref low, ref high) => {
|
||||
let microchips = {
|
||||
let mut bot = self.bots.entry(id).or_insert(Bot::new());
|
||||
|
||||
if bot.microchips.len() != 2 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
bot.microchips.sort();
|
||||
|
||||
(bot.microchips.remove(0), bot.microchips.pop().unwrap())
|
||||
};
|
||||
|
||||
match low {
|
||||
&Output::Bot(id) => {
|
||||
let mut bot = self.bots.entry(id).or_insert(Bot::new());
|
||||
|
||||
bot.microchips.push(microchips.0);
|
||||
|
||||
if bot.microchips.len() == 2 {
|
||||
bot.microchips.sort();
|
||||
|
||||
self.log.entry(id).or_insert(Vec::new())
|
||||
.push((bot.microchips[0], bot.microchips[1]));
|
||||
}
|
||||
}
|
||||
&Output::Bin(id) => {
|
||||
self.output.insert(id, microchips.0);
|
||||
}
|
||||
}
|
||||
|
||||
match high {
|
||||
&Output::Bot(id) => {
|
||||
let mut bot = self.bots.entry(id).or_insert(Bot::new());
|
||||
|
||||
bot.microchips.push(microchips.1);
|
||||
|
||||
if bot.microchips.len() == 2 {
|
||||
bot.microchips.sort();
|
||||
|
||||
self.log.entry(id).or_insert(Vec::new())
|
||||
.push((bot.microchips[0], bot.microchips[1]));
|
||||
}
|
||||
}
|
||||
&Output::Bin(id) => {
|
||||
self.output.insert(id, microchips.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let stdin = io::stdin();
|
||||
|
||||
let mut instructions = stdin.lock().lines()
|
||||
.filter_map(|raw| raw.ok())
|
||||
.filter_map(|line| Instruction::from_str(&line).ok())
|
||||
.collect::<VecDeque<_>>();
|
||||
|
||||
let mut factory = Factory::new();
|
||||
|
||||
while !instructions.is_empty() {
|
||||
let instruction = instructions.pop_front().unwrap();
|
||||
|
||||
if factory.execute(&instruction).is_err() {
|
||||
instructions.push_back(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
println!("{:#?}", factory);
|
||||
}
|
||||
Reference in New Issue
Block a user