This commit is contained in:
2016-12-08 13:56:43 +01:00
parent d0cf610046
commit 2ebe3b0004
5 changed files with 700 additions and 0 deletions

240
2015/07/src/main.rs Normal file
View File

@@ -0,0 +1,240 @@
#[macro_use] extern crate lazy_static;
extern crate regex;
use std::str::FromStr;
use std::io::{self, BufRead};
use std::collections::{VecDeque, HashMap};
use regex::Regex;
type Id = String;
type Value = u16;
#[derive(Debug)]
enum Input {
Value(Value),
Wire(Id)
}
impl FromStr for Input {
type Err = ();
fn from_str(s: &str) -> Result<Input, ()> {
match s.parse::<Value>() {
Ok(value) => Ok(Input::Value(value)),
Err(_) => Ok(Input::Wire(String::from(s))),
}
}
}
#[derive(Debug)]
enum Instruction {
Signal(Input, Id),
And(Input, Input, Id),
Or(Input, Input, Id),
Not(Input, Id),
LShift(Input, Input, Id),
RShift(Input, Input, Id)
}
impl FromStr for Instruction {
type Err = ();
fn from_str(s: &str) -> Result<Instruction, ()> {
lazy_static! {
static ref SIGNAL: Regex = Regex::new(r"^(\d+|[a-z]+) -> ([a-z]+)$").unwrap();
static ref AND: Regex = Regex::new(r"^(\d+|[a-z]+) AND (\d+|[a-z]+) -> ([a-z]+)$").unwrap();
static ref OR: Regex = Regex::new(r"^(\d+|[a-z]+) OR (\d+|[a-z]+) -> ([a-z]+)$").unwrap();
static ref NOT: Regex = Regex::new(r"^NOT (\d+|[a-z]+) -> ([a-z]+)$").unwrap();
static ref LSHIFT: Regex = Regex::new(r"^(\d+|[a-z]+) LSHIFT (\d+|[a-z]+) -> ([a-z]+)$").unwrap();
static ref RSHIFT: Regex = Regex::new(r"^(\d+|[a-z]+) RSHIFT (\d+|[a-z]+) -> ([a-z]+)$").unwrap();
}
if let Some(caps) = SIGNAL.captures(s) {
let x = caps.at(1).unwrap().parse::<Input>().unwrap();
let y = String::from(caps.at(2).unwrap());
return Ok(Instruction::Signal(x, y));
}
if let Some(caps) = AND.captures(s) {
let x = caps.at(1).unwrap().parse::<Input>().unwrap();
let y = caps.at(2).unwrap().parse::<Input>().unwrap();
let z = String::from(caps.at(3).unwrap());
return Ok(Instruction::And(x, y, z));
}
if let Some(caps) = OR.captures(s) {
let x = caps.at(1).unwrap().parse::<Input>().unwrap();
let y = caps.at(2).unwrap().parse::<Input>().unwrap();
let z = String::from(caps.at(3).unwrap());
return Ok(Instruction::Or(x, y, z));
}
if let Some(caps) = NOT.captures(s) {
let x = caps.at(1).unwrap().parse::<Input>().unwrap();
let y = String::from(caps.at(2).unwrap());
return Ok(Instruction::Not(x, y));
}
if let Some(caps) = LSHIFT.captures(s) {
let x = caps.at(1).unwrap().parse::<Input>().unwrap();
let y = caps.at(2).unwrap().parse::<Input>().unwrap();
let z = String::from(caps.at(3).unwrap());
return Ok(Instruction::LShift(x, y, z));
}
if let Some(caps) = RSHIFT.captures(s) {
let x = caps.at(1).unwrap().parse::<Input>().unwrap();
let y = caps.at(2).unwrap().parse::<Input>().unwrap();
let z = String::from(caps.at(3).unwrap());
return Ok(Instruction::RShift(x, y, z));
}
Err(())
}
}
fn main() {
let stdin = io::stdin();
let mut instructions = stdin.lock().lines()
.filter_map(|line| line.ok())
.filter_map(|line| Instruction::from_str(&line).ok())
.collect::<VecDeque<_>>();
// Second answer.
instructions.push_back(Instruction::from_str("46065 -> b").unwrap());
let mut op_map: HashMap<Id, Value> = HashMap::new();
while !instructions.is_empty() {
let instruction = instructions.pop_front().unwrap();
let push = match instruction {
Instruction::Signal(ref x, ref wire) => {
let x = match x {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
if x.is_some() {
op_map.insert(wire.clone(), x.unwrap());
false
} else {
true
}
}
Instruction::And(ref x, ref y, ref wire) => {
let x = match x {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
let y = match y {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
if x.is_some() && y.is_some() {
op_map.insert(wire.clone(), x.unwrap() & y.unwrap());
false
} else {
true
}
}
Instruction::Or(ref x, ref y, ref wire) => {
let x = match x {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
let y = match y {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
if x.is_some() && y.is_some() {
op_map.insert(wire.clone(), x.unwrap() | y.unwrap());
false
} else {
true
}
}
Instruction::Not(ref x, ref wire) => {
let x = match x {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
if x.is_some() {
op_map.insert(wire.clone(), !x.unwrap());
false
} else {
true
}
}
Instruction::LShift(ref x, ref y, ref wire) => {
let x = match x {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
let y = match y {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
if x.is_some() && y.is_some() {
op_map.insert(wire.clone(), x.unwrap() << y.unwrap());
false
} else {
true
}
}
Instruction::RShift(ref x, ref y, ref wire) => {
let x = match x {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
let y = match y {
&Input::Value(value) => Some(value.clone()),
&Input::Wire(ref wire) => if let Some(value) = op_map.get(wire) { Some(*value) } else { None }
};
if x.is_some() && y.is_some() {
op_map.insert(wire.clone(), x.unwrap() >> y.unwrap());
false
} else {
true
}
}
};
if push {
instructions.push_back(instruction);
}
}
println!("{:#?}", op_map);
}