Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extern crate regex;
- use std::env;
- use std::process;
- use std::fs::File;
- use std::io::prelude::*;
- use regex::Regex;
- use std::fmt::{ Formatter, Debug };
- use std::fmt;
- fn main() {
- let args = env::args().collect();
- let filename = parse_filename(&args);
- let mut contents = String::new();
- get_contents(&filename, &mut contents);
- //println!("{}", contents);
- let (samples, program) = parse_content(&contents);
- //println!("Samples:\n{:?}\n\nProgram:\n{:?}", samples, program);
- let part1 = has3pos(&samples);
- println!("Part1: {}", part1);
- let opcodes = deduce_opcodes(&samples);
- let part2 = execute(program, opcodes)[0];
- println!("Part2: {}", part2);
- }
- fn execute(program: Program, opcodes: Vec<OpCode>) -> Vec<usize> {
- let mut codes = opcodes.clone();
- codes.sort_by_key(|code| code.num);
- let mut reg = vec![0,0,0,0];
- for line in program.lines.iter() {
- //println!("{:?}", reg);
- let params = line[1..4].to_vec();
- println!("{} {:?}",codes[line[0]].name, params);
- (codes[line[0]].f)(¶ms,&mut reg);
- //println!("");
- }
- reg
- }
- fn deduce_opcodes(samples: &Vec<Sample>) -> Vec<OpCode> {
- let mut opcodes = Vec::new();
- let named_functions = get_named_functions();
- let mut candidates = Vec::new();
- for (name, function) in named_functions.iter() {
- let mut possibilities = Vec::new();
- for num in 0..16 {
- let no_possibility = samples.iter()
- .filter(|sample| sample.code[0] == num)
- .any(|sample| !sample.could_be(function));
- if !no_possibility{
- let opcode = OpCode {name: name.clone(), num: num, f: *function};
- possibilities.push(opcode)
- }
- }
- //println!("Possibilities:\n{:?}", possibilities);
- candidates.push(possibilities);
- }
- //println!("Candidates:\n{:?}", candidates);
- let mut found = Vec::new();
- while found.len() < 16 {
- for possibilities in candidates.iter() {
- let new: Vec<OpCode> = possibilities.iter().cloned().filter(|pos| !found.contains(&pos.num)).collect();
- if new.len() == 1 {
- opcodes.push(new[0].clone());
- found.push(new[0].num)
- }
- }
- }
- opcodes
- }
- fn get_functions() -> Vec<fn(&Vec<usize>, &mut Vec<usize>)> {
- let mut functions: Vec<fn(&Vec<usize>, &mut Vec<usize>)> = Vec::new();
- functions.push(addi); functions.push(addr);
- functions.push(muli); functions.push(mulr);
- functions.push(bani); functions.push(banr);
- functions.push(bori); functions.push(borr);
- functions.push(seti); functions.push(setr);
- functions.push(gtir); functions.push(gtri); functions.push(gtrr);
- functions.push(eqir); functions.push(eqri); functions.push(eqrr);
- functions
- }
- fn get_named_functions() -> Vec<(String, fn(&Vec<usize>, &mut Vec<usize>))> {
- let mut functions: Vec<(String, fn(&Vec<usize>, &mut Vec<usize>))> = Vec::new();
- functions.push(("addi".to_string(),addi)); functions.push(("addr".to_string(), addr));
- functions.push(("muli".to_string(),muli)); functions.push(("mulr".to_string(),mulr));
- functions.push(("bani".to_string(),bani)); functions.push(("banr".to_string(),banr));
- functions.push(("bori".to_string(),bori)); functions.push(("borr".to_string(),borr));
- functions.push(("seti".to_string(),seti)); functions.push(("setr".to_string(),setr));
- functions.push(("gtir".to_string(),gtir)); functions.push(("gtri".to_string(),gtri)); functions.push(("gtrr".to_string(),gtrr));
- functions.push(("eqir".to_string(),eqir)); functions.push(("eqri".to_string(),eqri)); functions.push(("eqrr".to_string(),eqrr));
- functions
- }
- fn has3pos(samples: &Vec<Sample>) -> i64 {
- let functions = get_functions();
- samples.iter().map(|sample| sample.num_candidates(&functions)).filter(|num| *num >= 3).count() as i64
- }
- fn parse_content(contents: &str) -> (Vec<Sample>, Program) {
- let mut samples = Vec::new();
- let mut prog = Vec::new();
- let mut lines = contents.trim_right().lines();
- let re = Regex::new(r"(\d+)").unwrap();
- while let Some(line) = lines.next() {
- if line.starts_with("Before") {
- let mut before = Vec::new();
- for cap in re.captures_iter(line) {
- before.push(cap[1].parse::<usize>().unwrap());
- }
- let mut code = Vec::new();
- let code_line = lines.next().expect("Wrongly formatted sample");
- for cap in re.captures_iter(code_line) {
- code.push(cap[1].parse::<usize>().unwrap());
- }
- let mut after = Vec::new();
- let after_line = lines.next().expect("Wrongly formatted sample");
- for cap in re.captures_iter(after_line) {
- after.push(cap[1].parse::<usize>().unwrap());
- }
- samples.push(Sample {before, code, after} );
- }
- if line != "" {
- let mut source = Vec::new();
- for cap in re.captures_iter(line) {
- source.push(cap[1].parse::<usize>().unwrap());
- }
- prog.push(source);
- }
- }
- (samples, Program {lines: prog})
- }
- #[derive(Clone)]
- struct OpCode {
- name: String,
- num: usize,
- f: fn(&Vec<usize>, &mut Vec<usize>),
- }
- impl Debug for OpCode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "OpCode {{ name: {}, num: {} }}", self.name, self.num)
- }
- }
- #[derive(Debug)]
- struct Sample {
- before: Vec<usize>,
- code: Vec<usize>,
- after: Vec<usize>,
- }
- impl Sample {
- fn could_be(&self, f: impl Fn(&Vec<usize>, &mut Vec<usize>)) -> bool {
- let mut reg = self.before.clone();
- f(&self.code[1..4].to_vec(), &mut reg);
- reg == self.after
- }
- fn num_candidates(&self, functions: &Vec<fn(&Vec<usize>, &mut Vec<usize>)>) -> i64 {
- functions.iter().filter(|f| self.could_be(f)).count() as i64
- }
- }
- #[derive(Debug)]
- struct Program {
- lines: Vec<Vec<usize>>,
- }
- fn parse_filename(args: &Vec<String>) -> &str {
- if args.len() < 2 {
- println!("Too few arguements, please give a filename");
- process::exit(1);
- }
- args.get(1).expect("No filename provided")
- }
- fn get_contents(filename: &str, contents: &mut String) {
- let mut f = File::open(filename).expect("File not found");
- f.read_to_string(contents)
- .expect("Something went wrong reading the file");
- }
- fn addr(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] + reg[b];
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn addi(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] + b;
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn mulr(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] * reg[b];
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn muli(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] * b;
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn banr(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] & reg[b];
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn bani(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] & b;
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn borr(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] | reg[b];
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn bori(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = reg[a] | b;
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn setr(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,_b,c] = params[0..3] {
- reg[c] = reg[a];
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn seti(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,_b,c] = params[0..3] {
- reg[c] = a;
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn gtir(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = if a > reg[b] { 1 } else { 0 }
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn gtri(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = if reg[a] > b { 1 } else { 0 }
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn gtrr(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = if reg[a] > reg[b] { 1 } else { 0 }
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn eqir(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = if a == reg[b] { 1 } else { 0 }
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn eqri(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = if reg[a] == b { 1 } else { 0 }
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- fn eqrr(params: &Vec<usize>, reg: &mut Vec<usize>) {
- if let [a,b,c] = params[0..3] {
- reg[c] = if reg[a] == reg[b] { 1 } else { 0 }
- } else {
- panic!("Wrong amount of paramters to addr")
- }
- }
- #[cfg(test)]
- mod test {
- use super::*;
- #[test]
- fn test_addr() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- addr(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,3])
- }
- #[test]
- fn test_addi() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- addi(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,2])
- }
- #[test]
- fn test_mulr() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- mulr(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,2])
- }
- #[test]
- fn test_muli() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- muli(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,1])
- }
- #[test]
- fn test_banr() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- banr(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,0])
- }
- #[test]
- fn test_bani() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- bani(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,1])
- }
- #[test]
- fn test_borr() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- borr(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,3])
- }
- #[test]
- fn test_bori() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- bori(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,1])
- }
- #[test]
- fn test_setr() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- setr(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,1])
- }
- #[test]
- fn test_seti() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- seti(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,0])
- }
- #[test]
- fn test_gtir() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- gtir(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,0])
- }
- #[test]
- fn test_gtri() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- gtri(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,0])
- }
- #[test]
- fn test_gtrr() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- gtrr(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,0])
- }
- #[test]
- fn test_eqir() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- eqir(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,0])
- }
- #[test]
- fn test_eqri() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- eqri(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,1])
- }
- #[test]
- fn test_eqrr() {
- let mut reg = vec![1,2,3,4];
- let params = vec![0,1,3];
- eqrr(¶ms, &mut reg);
- assert_eq!(reg, vec![1,2,3,0])
- }
- #[test]
- fn test_could_be_mulr() {
- let sample = Sample {before: vec![3,2,1,1], code: vec![9,2,1,2], after: vec![3,2,2,1]};
- assert_eq!(sample.could_be(mulr), true)
- }
- #[test]
- fn test_could_be_addi() {
- let sample = Sample {before: vec![3,2,1,1], code: vec![9,2,1,2], after: vec![3,2,2,1]};
- assert_eq!(sample.could_be(addi), true)
- }
- #[test]
- fn test_could_be_seti() {
- let sample = Sample {before: vec![3,2,1,1], code: vec![9,2,1,2], after: vec![3,2,2,1]};
- assert_eq!(sample.could_be(seti), true)
- }
- #[test]
- fn test_could_not_be_banr() {
- let sample = Sample {before: vec![3,2,1,1], code: vec![9,2,1,2], after: vec![3,2,2,1]};
- assert_eq!(sample.could_be(banr), false)
- }
- #[test]
- fn num_candidates() {
- let sample = Sample {before: vec![3,2,1,1], code: vec![9,2,1,2], after: vec![3,2,2,1]};
- let functions = get_functions();
- assert_eq!(sample.num_candidates(&functions), 3)
- }
- }
Add Comment
Please, Sign In to add comment