From 2ec8dddb66d1450565d1e2176ca3fca5b30e049e Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Fri, 30 Nov 2018 13:59:53 +0100 Subject: [PATCH] Reimplement day 21. --- 2016/day-21/Cargo.toml | 6 - 2016/day-21/sample.txt | 8 -- 2016/day-21/src/main.rs | 166 ----------------------- 2016/{day-21/input.txt => inputs/21.txt} | 0 2016/src/day21.rs | 164 ++++++++++++++++++++++ 2016/src/main.rs | 2 + 6 files changed, 166 insertions(+), 180 deletions(-) delete mode 100644 2016/day-21/Cargo.toml delete mode 100644 2016/day-21/sample.txt delete mode 100644 2016/day-21/src/main.rs rename 2016/{day-21/input.txt => inputs/21.txt} (100%) create mode 100644 2016/src/day21.rs diff --git a/2016/day-21/Cargo.toml b/2016/day-21/Cargo.toml deleted file mode 100644 index 16c171d..0000000 --- a/2016/day-21/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "day-21" -version = "0.1.0" -authors = ["Bert Peters "] - -[dependencies] diff --git a/2016/day-21/sample.txt b/2016/day-21/sample.txt deleted file mode 100644 index 865c052..0000000 --- a/2016/day-21/sample.txt +++ /dev/null @@ -1,8 +0,0 @@ -swap position 4 with position 0 -swap letter d with letter b -reverse positions 0 through 4 -rotate left 1 step -move position 1 to position 4 -move position 3 to position 0 -rotate based on position of letter b -rotate based on position of letter d diff --git a/2016/day-21/src/main.rs b/2016/day-21/src/main.rs deleted file mode 100644 index 5559584..0000000 --- a/2016/day-21/src/main.rs +++ /dev/null @@ -1,166 +0,0 @@ -use std::env; -use std::io::prelude::*; -use std::io::BufReader; -use std::fs::File; - -fn vec_str(vec: &[char]) -> String -{ - return vec.iter().cloned().collect(); -} - -fn find(password: &[char], search: &str) -> usize -{ - let c = search.chars().next().unwrap(); - for (index, b) in password.iter().enumerate() { - if c == *b { - return index; - } - } - panic!("{} not found in {}", c, vec_str(password)); -} - -fn rotate_left(password: &[char], amount: usize) -> Vec -{ - let mut new_passwd = Vec::with_capacity(password.len()); - - new_passwd.extend_from_slice(&password[amount..]); - new_passwd.extend_from_slice(&password[..amount]); - - return new_passwd; -} - -fn reverse_range(password: &mut[char], pos_1: usize, pos_2: usize) -{ - password[pos_1..pos_2 + 1].reverse(); -} - -fn swap(password: &mut[char], by: &str, id_1: &str, id_2: &str) -{ - let pos_1: usize; - let pos_2: usize; - match by { - "position" => { - pos_1 = id_1.parse().unwrap(); - pos_2 = id_2.parse().unwrap(); - }, - "letter" => { - pos_1 = find(password, id_1); - pos_2 = find(password, id_2); - }, - _ => panic!("Can't swap {}", by), - } - - password.swap(pos_1, pos_2); -} - -fn main() { - let args: Vec = env::args().collect(); - let f = File::open(&args[1]).expect("Could not open file"); - let reader = BufReader::new(f); - - let mut password: Vec = "abcdefgh".chars().collect(); - let mut rules = Vec::new(); - - for line in reader.lines() { - let contents = line.unwrap(); - let parts: Vec<&str> = contents.split(" ").collect(); - rules.push(contents.clone()); - - match parts[0] { - "swap" => { - swap(&mut password, &parts[1], &parts[2], &parts[5]); - }, - "rotate" => { - let amount = match parts[1] { - "left" => parts[2].parse().unwrap(), - "right" => password.len() - parts[2].parse::().unwrap(), - "based" => { - let pos = find(&password, parts[6]); - - 2 * password.len() - if pos >= 4 { pos + 2 } else { pos + 1 } - }, - - _ => panic!("Cannot rotate by {}", parts[2]), - } % password.len(); - password = rotate_left(&password, amount); - }, - - "reverse" => { - let pos_1: usize = parts[2].parse().unwrap(); - let pos_2: usize = parts[4].parse().unwrap(); - reverse_range(&mut password, pos_1, pos_2); - }, - "move" => { - let pos_1: usize = parts[2].parse().unwrap(); - let pos_2: usize = parts[5].parse().unwrap(); - - let c = password.remove(pos_1); - password.insert(pos_2, c); - }, - _ => panic!("Don't understand {}", parts[0]), - } - } - - println!("Final password is {}", vec_str(&password)); - let mut password: Vec = "fbgdceah".chars().collect(); - - for line in rules.iter().rev() { - let parts: Vec<&str> = line.split(" ").collect(); - - match parts[0] { - "swap" => { - swap(&mut password, &parts[1], &parts[2], &parts[5]); - }, - "rotate" => { - // invert regular rotations, and - let amount = match parts[1] { - "right" => parts[2].parse().unwrap(), - "left" => password.len() - parts[2].parse::().unwrap(), - "based" => { - let pos = find(&password, parts[6]); - - let mut original = usize::max_value(); - if pos % 2 == 1 { - // original pos < 4 - for x in 0..4 { - if (2 * x + 1) % password.len() == pos { - original = x + 1; - break; - } - } - } else { - // original pos >= 4 - for x in 4..password.len() { - if (2 * x + 2) % password.len() == pos { - original = x + 2; - } - } - } - - original - }, - - _ => panic!("Cannot rotate by {}", parts[2]), - } % password.len(); - password = rotate_left(&password, amount); - }, - - "reverse" => { - let pos_1: usize = parts[2].parse().unwrap(); - let pos_2: usize = parts[4].parse().unwrap(); - reverse_range(&mut password, pos_1, pos_2); - }, - "move" => { - let pos_1: usize = parts[2].parse().unwrap(); - let pos_2: usize = parts[5].parse().unwrap(); - - let c = password.remove(pos_2); - password.insert(pos_1, c); - }, - _ => panic!("Don't understand {}", parts[0]), - } - } - - println!("Reversed password is {}", vec_str(&password)); - -} diff --git a/2016/day-21/input.txt b/2016/inputs/21.txt similarity index 100% rename from 2016/day-21/input.txt rename to 2016/inputs/21.txt diff --git a/2016/src/day21.rs b/2016/src/day21.rs new file mode 100644 index 0000000..aedbb32 --- /dev/null +++ b/2016/src/day21.rs @@ -0,0 +1,164 @@ +use common; +use itertools::Itertools; +use std::io::prelude::*; +use std::io::BufReader; + +#[derive(Default)] +pub struct Day21 { + password: Vec, +} + +impl Day21 { + + pub fn new() -> Day21 { + Default::default() + } + + + fn swap(&mut self, by: &str, id_1: &str, id_2: &str) + { + let pos_1: usize; + let pos_2: usize; + match by { + "position" => { + pos_1 = id_1.parse().unwrap(); + pos_2 = id_2.parse().unwrap(); + }, + "letter" => { + pos_1 = self.find(id_1); + pos_2 = self.find(id_2); + }, + _ => panic!("Can't swap {}", by), + } + + self.password.swap(pos_1, pos_2); + } + + fn find(&self, search: &str) -> usize { + let c = search.chars().next().unwrap(); + match self.password.iter().find_position(|&&x| x == c) { + Some((pos, _)) => pos, + _ => panic!("Char not in password: {}", c) + } + } + + fn reverse_range(&mut self, pos_1: usize, pos_2: usize) + { + self.password[pos_1..=pos_2].reverse(); + } +} + +impl common::Solution for Day21 { + fn part1(&mut self, input: &mut Read) -> String { + self.password = "abcdefgh".chars().collect(); + let reader = BufReader::new(input); + + for line in reader.lines() { + let contents = line.unwrap(); + let parts: Vec<&str> = contents.split(" ").collect(); + + match parts[0] { + "swap" => { + self.swap(&parts[1], &parts[2], &parts[5]); + }, + "rotate" => { + let amount = match parts[1] { + "left" => parts[2].parse().unwrap(), + "right" => self.password.len() - parts[2].parse::().unwrap(), + "based" => { + let pos = self.find(parts[6]); + + 2 * self.password.len() - if pos >= 4 { pos + 2 } else { pos + 1 } + }, + + _ => panic!("Cannot rotate by {}", parts[2]), + } % self.password.len(); + self.password.rotate_left(amount); + }, + + "reverse" => { + let pos_1: usize = parts[2].parse().unwrap(); + let pos_2: usize = parts[4].parse().unwrap(); + self.reverse_range(pos_1, pos_2); + }, + "move" => { + let pos_1: usize = parts[2].parse().unwrap(); + let pos_2: usize = parts[5].parse().unwrap(); + + let c = self.password.remove(pos_1); + self.password.insert(pos_2, c); + }, + _ => panic!("Don't understand {}", parts[0]), + } + } + + self.password.iter().collect() + } + + fn part2(&mut self, input: &mut Read) -> String { + let reader = BufReader::new(input); + let rules: Vec = reader.lines() + .map(|x| x.unwrap()) + .collect(); + self.password = "fbgdceah".chars().collect(); + + for line in rules.iter().rev() { + let parts: Vec<&str> = line.split(" ").collect(); + + match parts[0] { + "swap" => { + self.swap(&parts[1], &parts[2], &parts[5]); + }, + "rotate" => { + // invert regular rotations, and + let amount = match parts[1] { + "right" => parts[2].parse().unwrap(), + "left" => self.password.len() - parts[2].parse::().unwrap(), + "based" => { + let pos = self.find(parts[6]); + + let mut original = usize::max_value(); + if pos % 2 == 1 { + // original pos < 4 + for x in 0..4 { + if (2 * x + 1) % self.password.len() == pos { + original = x + 1; + break; + } + } + } else { + // original pos >= 4 + for x in 4..self.password.len() { + if (2 * x + 2) % self.password.len() == pos { + original = x + 2; + } + } + } + + original + }, + + _ => panic!("Cannot rotate by {}", parts[2]), + } % self.password.len(); + self.password.rotate_left(amount); + }, + + "reverse" => { + let pos_1: usize = parts[2].parse().unwrap(); + let pos_2: usize = parts[4].parse().unwrap(); + self.reverse_range(pos_1, pos_2); + }, + "move" => { + let pos_1: usize = parts[2].parse().unwrap(); + let pos_2: usize = parts[5].parse().unwrap(); + + let c = self.password.remove(pos_2); + self.password.insert(pos_1, c); + }, + _ => panic!("Don't understand {}", parts[0]), + } + } + + self.password.iter().collect() + } +} diff --git a/2016/src/main.rs b/2016/src/main.rs index 2fe6a56..17ce9f1 100644 --- a/2016/src/main.rs +++ b/2016/src/main.rs @@ -12,6 +12,7 @@ pub mod day2; pub mod day12; pub mod day15; pub mod day16; +pub mod day21; pub mod day23; pub mod day24; pub mod day25; @@ -23,6 +24,7 @@ fn get_impl(day: &str) -> Box { Ok(12) => { Box::new(day12::Day12::new()) } Ok(15) => { Box::new(day15::Day15::new()) } Ok(16) => { Box::new(day16::Day16::new()) } + Ok(21) => { Box::new(day21::Day21::new()) } Ok(23) => { Box::new(day23::Day23::new()) } Ok(24) => { Box::new(day24::Day24::new()) } Ok(25) => { Box::new(day25::Day25::new()) }