Skip to content

Instantly share code, notes, and snippets.

@salty-horse
Created December 12, 2015 18:35
Show Gist options
  • Save salty-horse/7f132a6573465e3cea32 to your computer and use it in GitHub Desktop.
Save salty-horse/7f132a6573465e3cea32 to your computer and use it in GitHub Desktop.
Advent of Code day 7 http://adventofcode.com/
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use std::collections::HashMap;
#[derive(Debug)]
struct Wire {
source: WireSource,
target: String,
}
#[derive(Debug)]
enum WireSource {
Direct(String),
Signal(u16),
Not(String),
And(String, String),
AndVal(u16, String),
Or(String, String),
LShift(String, u8),
RShift(String, u8),
}
fn parse_wire(s: &String) -> Wire {
let v: Vec<&str> = s.splitn(2, " -> ").collect();
let source = v[0];
let target = v[1];
let wire_source: WireSource = {
if let Some(ix) = source.find("NOT ") {
WireSource::Not(source[ix+4..].to_string())
} else if let Some(ix) = source.find(" AND ") {
if source.chars().nth(0).unwrap().is_digit(10) {
let n = source[0..ix].parse::<u16>().unwrap();
WireSource::AndVal(n, source[ix+5..].to_string())
} else {
WireSource::And(source[0..ix].to_string(), source[ix+5..].to_string())
}
} else if let Some(ix) = source.find(" OR ") {
WireSource::Or(source[0..ix].to_string(), source[ix+4..].to_string())
} else if let Some(ix) = source.find(" LSHIFT ") {
let n = source[ix+8..].parse::<u8>().unwrap();
WireSource::LShift(source[0..ix].to_string(), n)
} else if let Some(ix) = source.find(" RSHIFT ") {
let n = source[ix+8..].parse::<u8>().unwrap();
WireSource::RShift(source[0..ix].to_string(), n)
} else if let Ok(n) = source.parse::<u16>() {
WireSource::Signal(n)
} else {
WireSource::Direct(source.to_string())
}
};
Wire {source: wire_source, target: target.to_string()}
}
fn calc_signal(wires: &HashMap<String, WireSource>, mem: &mut HashMap<String, u16>, wire: &str) -> u16 {
match mem.get(wire) {
Some(x) => return *x,
None => {},
};
let entry = wires.get(wire);
let result = match entry {
None => panic!("Unknown wire ".to_string() + wire),
Some(source) => match *source {
WireSource::Direct(ref s) => calc_signal(wires, mem, &s),
WireSource::Signal(n) => n,
WireSource::Not(ref s) => !calc_signal(wires, mem, &s),
WireSource::And(ref s1, ref s2) => calc_signal(wires, mem, &s1) & calc_signal(wires, mem, &s2),
WireSource::AndVal(n, ref s) => n & calc_signal(wires, mem, &s),
WireSource::Or(ref s1, ref s2) => calc_signal(wires, mem, &s1) | calc_signal(wires, mem, &s2),
WireSource::LShift(ref s, shift) => calc_signal(wires, mem, &s) << shift,
WireSource::RShift(ref s, shift) => calc_signal(wires, mem, &s) >> shift,
}
};
mem.insert(wire.to_string(), result);
result
}
fn main() {
let input_fname = "day7_input.txt";
let f = File::open(input_fname).unwrap();
let mut wires: HashMap<String, WireSource> = HashMap::new();
let mut mem: HashMap<String, u16> = HashMap::new();
let reader = BufReader::new(f);
for line in reader.lines() {
let line = line.unwrap();
let wire = parse_wire(&line);
wires.insert(wire.target, wire.source);
// (*wires.entry(wire.target).or_insert(Vec::new())).push(wire.source);
}
// println!("{:?}", wires);
let signal_for_a = calc_signal(&wires, &mut mem, "a");
println!("Signal for 'a': {}", signal_for_a);
// Reset stuff for part 2
wires.insert("b".to_string(), WireSource::Signal(signal_for_a));
mem.clear();
let new_signal_for_a = calc_signal(&wires, &mut mem, "a");
println!("New signal for 'a': {}", new_signal_for_a);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment