diff options
-rw-r--r-- | input/day21.txt | 100 | ||||
-rw-r--r-- | src/bin/day21.rs | 122 |
2 files changed, 222 insertions, 0 deletions
diff --git a/input/day21.txt b/input/day21.txt new file mode 100644 index 0000000..68bb697 --- /dev/null +++ b/input/day21.txt @@ -0,0 +1,100 @@ +swap position 5 with position 6 +reverse positions 1 through 6 +rotate right 7 steps +rotate based on position of letter c +rotate right 7 steps +reverse positions 0 through 4 +swap letter f with letter h +reverse positions 1 through 2 +move position 1 to position 0 +rotate based on position of letter f +move position 6 to position 3 +reverse positions 3 through 6 +rotate based on position of letter c +rotate based on position of letter b +move position 2 to position 4 +swap letter b with letter d +move position 1 to position 6 +move position 7 to position 1 +swap letter f with letter c +move position 2 to position 3 +swap position 1 with position 7 +reverse positions 3 through 5 +swap position 1 with position 4 +move position 4 to position 7 +rotate right 4 steps +reverse positions 3 through 6 +move position 0 to position 6 +swap position 3 with position 5 +swap letter e with letter h +rotate based on position of letter c +swap position 4 with position 7 +reverse positions 0 through 5 +rotate right 5 steps +rotate left 0 steps +rotate based on position of letter f +swap letter e with letter b +rotate right 2 steps +rotate based on position of letter c +swap letter a with letter e +rotate left 4 steps +rotate left 0 steps +move position 6 to position 7 +rotate right 2 steps +rotate left 6 steps +rotate based on position of letter d +swap letter a with letter b +move position 5 to position 4 +reverse positions 0 through 7 +rotate left 3 steps +rotate based on position of letter e +rotate based on position of letter h +swap position 4 with position 6 +reverse positions 4 through 5 +reverse positions 5 through 7 +rotate left 3 steps +move position 7 to position 2 +move position 3 to position 4 +swap letter b with letter d +reverse positions 3 through 4 +swap letter e with letter a +rotate left 4 steps +swap position 3 with position 4 +swap position 7 with position 5 +rotate right 1 step +rotate based on position of letter g +reverse positions 0 through 3 +swap letter g with letter b +rotate based on position of letter b +swap letter a with letter c +swap position 0 with position 2 +reverse positions 1 through 3 +rotate left 7 steps +swap letter f with letter a +move position 5 to position 0 +reverse positions 1 through 5 +rotate based on position of letter d +rotate based on position of letter c +rotate left 2 steps +swap letter b with letter a +swap letter f with letter c +swap letter h with letter f +rotate based on position of letter b +rotate left 3 steps +swap letter b with letter h +reverse positions 1 through 7 +rotate based on position of letter h +swap position 1 with position 5 +rotate left 1 step +rotate based on position of letter h +reverse positions 0 through 1 +swap position 5 with position 7 +reverse positions 0 through 2 +reverse positions 1 through 3 +move position 1 to position 4 +reverse positions 1 through 3 +rotate left 1 step +swap position 4 with position 1 +move position 1 to position 3 +rotate right 2 steps +move position 0 to position 5 \ No newline at end of file diff --git a/src/bin/day21.rs b/src/bin/day21.rs new file mode 100644 index 0000000..c195c08 --- /dev/null +++ b/src/bin/day21.rs @@ -0,0 +1,122 @@ +use std::io::{self, Read}; + +#[derive(Debug, Clone, Copy)] +enum Operation { + SwapPosition(usize, usize), + SwapLetter(u8, u8), + RotateLeft(usize), + RotateRight(usize), + RotateLetter(u8), + Reverse(usize, usize), + Move(usize, usize), +} + +impl Operation { + fn apply(self, slice: &mut [u8]) { + match self { + Operation::SwapPosition(i, j) => slice.swap(i, j), + Operation::SwapLetter(a, b) => { + let i = slice.iter().position(|&x| x == a).unwrap(); + let j = slice.iter().position(|&x| x == b).unwrap(); + slice.swap(i, j); + }, + Operation::RotateLeft(n) => { + let n = n % slice.len(); + slice[0..n].reverse(); + slice[n..].reverse(); + slice.reverse(); + }, + Operation::RotateRight(n) => { + let n = n % slice.len(); + slice.reverse(); + slice[0..n].reverse(); + slice[n..].reverse(); + }, + Operation::RotateLetter(a) => { + let mut n = 1 + slice.iter().position(|&x| x == a).unwrap(); + if n >= 4 { n += 1 } + n %= slice.len(); + slice.reverse(); + slice[0..n].reverse(); + slice[n..].reverse(); + }, + Operation::Reverse(i, j) => slice[i..(j + 1)].reverse(), + Operation::Move(i, j) if i < j => { + let a = slice[i]; + for k in i..j { + slice[k] = slice[k + 1]; + } + slice[j] = a; + }, + Operation::Move(i, j) => { + let a = slice[i]; + for k in (j..i).rev() { + slice[k + 1] = slice[k]; + } + slice[j] = a; + }, + } + } +} + +impl<'a> From<&'a str> for Operation { + fn from(s: &'a str) -> Self { + let mut iter = s.split_whitespace(); + match (iter.next().unwrap(), iter.next().unwrap()) { + ("swap", "position") => Operation::SwapPosition( + iter.next().unwrap().parse().unwrap(), + iter.nth(2).unwrap().parse().unwrap(), + ), + ("swap", "letter") => Operation::SwapLetter( + iter.next().unwrap().as_bytes()[0], + iter.nth(2).unwrap().as_bytes()[0], + ), + ("rotate", "left") => Operation::RotateLeft(iter.next().unwrap().parse().unwrap()), + ("rotate", "right") => Operation::RotateRight(iter.next().unwrap().parse().unwrap()), + ("rotate", "based") => Operation::RotateLetter(iter.nth(4).unwrap().as_bytes()[0]), + ("reverse", _) => Operation::Reverse( + iter.next().unwrap().parse().unwrap(), + iter.nth(1).unwrap().parse().unwrap(), + ), + ("move", _) => Operation::Move( + iter.next().unwrap().parse().unwrap(), + iter.nth(2).unwrap().parse().unwrap(), + ), + (x, y) => panic!("invalid operation {} {}", x, y), + } + } +} + +fn solve(password: &str, input: &str) -> String { + let mut password = password.as_bytes().to_owned(); + + for operation in input.lines().map(Operation::from) { + print!("{} ", std::str::from_utf8(&password).unwrap()); + operation.apply(&mut password); + println!("{:^20} {}", format!("{:?}", operation), std::str::from_utf8(&password).unwrap()); + } + + String::from_utf8(password).unwrap() +} + +fn main() { + let mut input = String::new(); + io::stdin().read_to_string(&mut input).unwrap(); + + println!("Part 1: {}", solve("abcdefgh", &input)); +} + +#[test] +fn part1() { + let input = " +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 +"; + assert_eq!("decab", solve("abcde", input.trim())); +} |