summaryrefslogtreecommitdiff
path: root/d21
diff options
context:
space:
mode:
Diffstat (limited to 'd21')
-rw-r--r--d21/Cargo.toml7
-rw-r--r--d21/input.txt100
-rw-r--r--d21/src/main.rs109
3 files changed, 216 insertions, 0 deletions
diff --git a/d21/Cargo.toml b/d21/Cargo.toml
new file mode 100644
index 0000000..f06cd6a
--- /dev/null
+++ b/d21/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "d21"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+itertools = "0.10.5"
diff --git a/d21/input.txt b/d21/input.txt
new file mode 100644
index 0000000..b39b884
--- /dev/null
+++ b/d21/input.txt
@@ -0,0 +1,100 @@
+reverse positions 1 through 6
+rotate based on position of letter a
+swap position 4 with position 1
+reverse positions 1 through 5
+move position 5 to position 7
+swap position 4 with position 0
+swap position 4 with position 6
+rotate based on position of letter a
+swap position 0 with position 2
+move position 5 to position 2
+move position 7 to position 1
+swap letter d with letter c
+swap position 5 with position 3
+reverse positions 3 through 7
+rotate based on position of letter d
+swap position 7 with position 5
+rotate based on position of letter f
+swap position 4 with position 1
+swap position 3 with position 6
+reverse positions 4 through 7
+rotate based on position of letter c
+move position 0 to position 5
+swap position 7 with position 4
+rotate based on position of letter f
+reverse positions 1 through 3
+move position 5 to position 3
+rotate based on position of letter g
+reverse positions 2 through 5
+rotate right 0 steps
+rotate left 0 steps
+swap letter f with letter b
+rotate based on position of letter h
+move position 1 to position 3
+reverse positions 3 through 6
+rotate based on position of letter h
+swap position 4 with position 3
+swap letter b with letter h
+swap letter a with letter h
+reverse positions 1 through 6
+swap position 3 with position 6
+swap letter e with letter d
+swap letter e with letter h
+swap position 1 with position 5
+rotate based on position of letter a
+reverse positions 4 through 5
+swap position 0 with position 4
+reverse positions 0 through 3
+move position 7 to position 2
+swap letter e with letter c
+swap position 3 with position 4
+rotate left 3 steps
+rotate left 7 steps
+rotate based on position of letter e
+reverse positions 5 through 6
+move position 1 to position 5
+move position 1 to position 2
+rotate left 1 step
+move position 7 to position 6
+rotate left 0 steps
+reverse positions 5 through 6
+reverse positions 3 through 7
+swap letter d with letter e
+rotate right 3 steps
+swap position 2 with position 1
+swap position 5 with position 7
+swap letter h with letter d
+swap letter c with letter d
+rotate based on position of letter d
+swap letter d with letter g
+reverse positions 0 through 1
+rotate right 0 steps
+swap position 2 with position 3
+rotate left 4 steps
+rotate left 5 steps
+move position 7 to position 0
+rotate right 1 step
+swap letter g with letter f
+rotate based on position of letter a
+rotate based on position of letter b
+swap letter g with letter e
+rotate right 4 steps
+rotate based on position of letter h
+reverse positions 3 through 5
+swap letter h with letter e
+swap letter g with letter a
+rotate based on position of letter c
+reverse positions 0 through 4
+rotate based on position of letter e
+reverse positions 4 through 7
+rotate left 4 steps
+swap position 0 with position 6
+reverse positions 1 through 6
+rotate left 2 steps
+swap position 5 with position 3
+swap letter b with letter d
+swap letter b with letter d
+rotate based on position of letter d
+rotate based on position of letter c
+rotate based on position of letter h
+move position 4 to position 7
diff --git a/d21/src/main.rs b/d21/src/main.rs
new file mode 100644
index 0000000..34d5599
--- /dev/null
+++ b/d21/src/main.rs
@@ -0,0 +1,109 @@
+use std::fs;
+
+use itertools::Itertools;
+
+fn solve_part1(insts: &Vec<&str>, init: &str) -> String {
+ let mut chars: Vec<char> = init.chars().collect();
+
+ for inst in insts {
+ let mut next = chars.clone();
+
+ let words: Vec<&str> = inst.split_ascii_whitespace().collect();
+ if words[0] == "swap" {
+ if words[1] == "position" {
+ // Swap the characters at indices `i' and `j'
+ let i: usize = words[2].parse().unwrap();
+ let j: usize = words[5].parse().unwrap();
+ next[i] = chars[j];
+ next[j] = chars[i];
+ } else if words[1] == "letter" {
+ // Swap all occurrences of characters `x' and `y'
+ let x = words[2].chars().nth(0).unwrap();
+ let y = words[5].chars().nth(0).unwrap();
+ for i in 0..next.len() {
+ if next[i] == x {
+ next[i] = y;
+ } else if next[i] == y {
+ next[i] = x;
+ }
+ }
+ }
+ } else if words[0] == "rotate" {
+ if words[1] == "left" {
+ let n: usize = words[2].parse().unwrap();
+ next.rotate_left(n % chars.len());
+ } else if words[1] == "right" {
+ let n: usize = words[2].parse().unwrap();
+ next.rotate_right(n % chars.len());
+ } else if words[1] == "based" {
+ // Get the index `i' of character `x'
+ let x = words[6].chars().nth(0).unwrap();
+ let i = next.iter().position(|&c| c == x).unwrap();
+ // Rotate right by an amount determined by `i'
+ let n = if i < 4 { i + 1 } else { i + 2 };
+ next.rotate_right(n % chars.len());
+ }
+ } else if words[0] == "reverse" {
+ let i: usize = words[2].parse().unwrap();
+ let j: usize = words[4].parse().unwrap();
+ next[i..j + 1].reverse();
+ } else if words[0] == "move" {
+ let i: usize = words[2].parse().unwrap();
+ let j: usize = words[5].parse().unwrap();
+ let c = next.remove(i);
+ next.insert(j, c);
+ }
+
+ chars = next;
+ }
+
+ chars.into_iter().collect()
+}
+
+fn solve_part2(insts: &Vec<&str>, target: &str) -> String {
+ let init = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
+
+ // The "good" approach would be to reverse the operations in `insts'.
+ // I'm too lazy for that: I just go through all permutations of the
+ // input characters, run `insts' as in part 1, and see if it's the one.
+ for perm in init.into_iter().permutations(8) {
+ let string: String = perm.iter().collect();
+ if solve_part1(insts, &string) == target {
+ return string;
+ }
+ }
+
+ String::new() // shouldn't happen
+}
+
+fn main() {
+ // Read instructions from input text file
+ let input = fs::read_to_string("input.txt").unwrap();
+ let insts = input.lines().collect();
+
+ // Part 1 gives "gfdhebac" for me
+ println!("Part 1 solution: {}", solve_part1(&insts, "abcdefgh"));
+
+ // Part 2 gives "dhaegfbc" for me
+ println!("Part 2 solution: {}", solve_part2(&insts, "fbgdceah"));
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn part1_example1() {
+ let insts = vec![
+ "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!(solve_part1(&insts, "abcde"), "decab");
+ }
+}