mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Reimplement day 21.
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "day-21"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Bert Peters <bert.ljpeters@gmail.com>"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
@@ -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
|
|
||||||
@@ -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<char>
|
|
||||||
{
|
|
||||||
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<String> = env::args().collect();
|
|
||||||
let f = File::open(&args[1]).expect("Could not open file");
|
|
||||||
let reader = BufReader::new(f);
|
|
||||||
|
|
||||||
let mut password: Vec<char> = "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::<usize>().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<char> = "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::<usize>().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));
|
|
||||||
|
|
||||||
}
|
|
||||||
164
2016/src/day21.rs
Normal file
164
2016/src/day21.rs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
use common;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::io::BufReader;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Day21 {
|
||||||
|
password: Vec<char>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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::<usize>().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<String> = 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::<usize>().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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ pub mod day2;
|
|||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day15;
|
pub mod day15;
|
||||||
pub mod day16;
|
pub mod day16;
|
||||||
|
pub mod day21;
|
||||||
pub mod day23;
|
pub mod day23;
|
||||||
pub mod day24;
|
pub mod day24;
|
||||||
pub mod day25;
|
pub mod day25;
|
||||||
@@ -23,6 +24,7 @@ fn get_impl(day: &str) -> Box<common::Solution> {
|
|||||||
Ok(12) => { Box::new(day12::Day12::new()) }
|
Ok(12) => { Box::new(day12::Day12::new()) }
|
||||||
Ok(15) => { Box::new(day15::Day15::new()) }
|
Ok(15) => { Box::new(day15::Day15::new()) }
|
||||||
Ok(16) => { Box::new(day16::Day16::new()) }
|
Ok(16) => { Box::new(day16::Day16::new()) }
|
||||||
|
Ok(21) => { Box::new(day21::Day21::new()) }
|
||||||
Ok(23) => { Box::new(day23::Day23::new()) }
|
Ok(23) => { Box::new(day23::Day23::new()) }
|
||||||
Ok(24) => { Box::new(day24::Day24::new()) }
|
Ok(24) => { Box::new(day24::Day24::new()) }
|
||||||
Ok(25) => { Box::new(day25::Day25::new()) }
|
Ok(25) => { Box::new(day25::Day25::new()) }
|
||||||
|
|||||||
Reference in New Issue
Block a user