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