This commit is contained in:
2016-12-11 11:02:11 +01:00
parent 73239041c5
commit 1215122512
5 changed files with 551 additions and 0 deletions

201
2016/10/src/main.rs Normal file
View 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);
}