Created
December 8, 2017 12:41
-
-
Save jtdowney/34b71906a89a323b17357a8674a8b43f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate error_chain; | |
mod errors { | |
error_chain!{ | |
foreign_links { | |
Io(::std::io::Error); | |
ParseInt(::std::num::ParseIntError); | |
} | |
} | |
} | |
use errors::*; | |
use std::collections::HashMap; | |
use std::env; | |
use std::fs::File; | |
use std::io::{BufRead, BufReader}; | |
use std::result; | |
use std::str; | |
#[derive(Debug, Copy, Clone)] | |
enum Operation { | |
Increase, | |
Decrease, | |
} | |
impl str::FromStr for Operation { | |
type Err = Error; | |
fn from_str(op: &str) -> Result<Operation> { | |
let result = match op { | |
"inc" => Operation::Increase, | |
"dec" => Operation::Decrease, | |
_ => bail!("invalid operation {}", op), | |
}; | |
Ok(result) | |
} | |
} | |
#[derive(Debug, Copy, Clone)] | |
enum Comparison { | |
Equal, | |
GreaterThan, | |
GreaterThanOrEqual, | |
LessThan, | |
LessThanOrEqual, | |
NotEqual, | |
} | |
impl str::FromStr for Comparison { | |
type Err = Error; | |
fn from_str(op: &str) -> Result<Comparison> { | |
let result = match op { | |
"==" => Comparison::Equal, | |
">" => Comparison::GreaterThan, | |
">=" => Comparison::GreaterThanOrEqual, | |
"<" => Comparison::LessThan, | |
"<=" => Comparison::LessThanOrEqual, | |
"!=" => Comparison::NotEqual, | |
_ => bail!("invalid comparison {}", op), | |
}; | |
Ok(result) | |
} | |
} | |
#[derive(Debug, Clone)] | |
struct Instruction { | |
register: String, | |
operation: Operation, | |
value: i32, | |
comparison_register: String, | |
comparison: Comparison, | |
comparison_value: i32, | |
} | |
impl str::FromStr for Instruction { | |
type Err = Error; | |
fn from_str(line: &str) -> Result<Instruction> { | |
let parts: Vec<&str> = line.split_whitespace().collect(); | |
let register = parts[0].to_string(); | |
let operation = parts[1].parse()?; | |
let value = parts[2].parse()?; | |
if parts[3] != "if" { | |
bail!("invalid instruction"); | |
} | |
let comparison_register = parts[4].to_string(); | |
let comparison = parts[5].parse()?; | |
let comparison_value = parts[6].parse()?; | |
Ok(Instruction { | |
register, | |
operation, | |
value, | |
comparison_register, | |
comparison, | |
comparison_value, | |
}) | |
} | |
} | |
fn run() -> Result<()> { | |
let filename = env::args().nth(1).expect("filename"); | |
let file = File::open(filename)?; | |
let reader = BufReader::new(file); | |
let instructions = reader | |
.lines() | |
.filter_map(result::Result::ok) | |
.map(|line| line.parse()) | |
.collect::<Result<Vec<Instruction>>>()?; | |
let mut environment = HashMap::new(); | |
let mut max = 0; | |
for instruction in instructions { | |
let lhs = *environment | |
.get(&instruction.comparison_register) | |
.unwrap_or(&0); | |
let rhs = instruction.comparison_value; | |
let result = match instruction.comparison { | |
Comparison::Equal => lhs == rhs, | |
Comparison::GreaterThan => lhs > rhs, | |
Comparison::GreaterThanOrEqual => lhs >= rhs, | |
Comparison::LessThan => lhs < rhs, | |
Comparison::LessThanOrEqual => lhs <= rhs, | |
Comparison::NotEqual => lhs != rhs, | |
}; | |
if result { | |
let value = *environment.get(&instruction.register).unwrap_or(&0); | |
let value = match instruction.operation { | |
Operation::Increase => value + instruction.value, | |
Operation::Decrease => value - instruction.value, | |
}; | |
if value > max { | |
max = value; | |
} | |
environment.insert(instruction.register.clone(), value); | |
} | |
} | |
let (key, value) = environment.iter().max_by_key(|&(_, &v)| v).unwrap(); | |
println!("part 1: {}={}", key, value); | |
println!("part 2: {}", max); | |
Ok(()) | |
} | |
quick_main!(run); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment