add day 21
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
const INPUT: &str = "abcdefgh";
|
||||
const INPUT2: &str = "fbgdceah";
|
||||
|
||||
fn main() {
|
||||
let instructions: Vec<_> = std::fs::read_to_string("input.txt")
|
||||
.unwrap()
|
||||
.lines()
|
||||
.map(Instruction::parse)
|
||||
.collect();
|
||||
|
||||
let mut result: String = INPUT.chars().collect();
|
||||
|
||||
for i in &instructions {
|
||||
let mut chars: Vec<_> = result.chars().collect();
|
||||
result = i.apply(&mut chars)
|
||||
}
|
||||
|
||||
println!("{result}");
|
||||
|
||||
let mut result: String = INPUT2.chars().collect();
|
||||
|
||||
for i in instructions.iter().rev() {
|
||||
let mut chars: Vec<_> = result.chars().collect();
|
||||
result = i.reverse_apply(&mut chars)
|
||||
}
|
||||
|
||||
println!("{result}");
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Instruction {
|
||||
SwapPosition(usize, usize),
|
||||
SwapLetter(char, char),
|
||||
RotateLeft(usize),
|
||||
RotateRight(usize),
|
||||
RotateByLetter(char),
|
||||
ReversePositions(usize, usize),
|
||||
Move(usize, usize),
|
||||
}
|
||||
|
||||
fn find_idx_of_letter(s: &[char], a: char) -> Option<usize> {
|
||||
s.iter()
|
||||
.enumerate()
|
||||
.find_map(|(i, c)| (a == *c).then_some(i))
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
fn reverse_apply(&self, s: &mut [char]) -> String {
|
||||
match self {
|
||||
Instruction::SwapPosition(a, b) => {
|
||||
s.swap(*a, *b);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::SwapLetter(a, b) => {
|
||||
let a = find_idx_of_letter(s, *a).unwrap();
|
||||
let b = find_idx_of_letter(s, *b).unwrap();
|
||||
s.swap(a, b);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::RotateLeft(a) => {
|
||||
s.rotate_right(*a);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::RotateRight(a) => {
|
||||
s.rotate_left(*a);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::RotateByLetter(a) => {
|
||||
let len = s.len();
|
||||
for rot in 0..len {
|
||||
let mut candidate = s.to_vec();
|
||||
candidate.rotate_left(rot);
|
||||
let idx = find_idx_of_letter(&candidate, *a).unwrap();
|
||||
let expected_rot = if idx >= 4 {
|
||||
(1 + idx + 1) % len
|
||||
} else {
|
||||
(1 + idx) % len
|
||||
};
|
||||
if expected_rot == rot {
|
||||
return candidate.iter().collect();
|
||||
}
|
||||
}
|
||||
unreachable!("no valid rotation found")
|
||||
}
|
||||
Instruction::ReversePositions(a, b) => {
|
||||
s[*a..=*b].reverse();
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::Move(a, b) => {
|
||||
let mut string: Vec<char> = s.to_vec();
|
||||
let c = string.remove(*b);
|
||||
string.insert(*a, c);
|
||||
string.iter().collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn apply(&self, s: &mut [char]) -> String {
|
||||
match self {
|
||||
Instruction::SwapPosition(a, b) => {
|
||||
s.swap(*a, *b);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::SwapLetter(a, b) => {
|
||||
let a = find_idx_of_letter(s, *a).unwrap();
|
||||
let b = find_idx_of_letter(s, *b).unwrap();
|
||||
s.swap(a, b);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::RotateLeft(a) => {
|
||||
s.rotate_left(*a);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::RotateRight(a) => {
|
||||
s.rotate_right(*a);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::RotateByLetter(a) => {
|
||||
let a = find_idx_of_letter(s, *a).unwrap();
|
||||
let rotate = if a >= 4 {
|
||||
(1 + a + 1) % s.len()
|
||||
} else {
|
||||
(1 + a) % s.len()
|
||||
};
|
||||
s.rotate_right(rotate);
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::ReversePositions(a, b) => {
|
||||
s[*a..=*b].reverse();
|
||||
s[..].iter().collect()
|
||||
}
|
||||
Instruction::Move(a, b) => {
|
||||
let mut string: Vec<char> = s.to_vec();
|
||||
let c = string.remove(*a);
|
||||
string.insert(*b, c);
|
||||
string.iter().collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(s: &str) -> Self {
|
||||
let words = s.split_whitespace();
|
||||
let two_words: Vec<&str> = words.clone().take(2).collect();
|
||||
|
||||
let mut words = words.skip(2);
|
||||
|
||||
match two_words[..] {
|
||||
["swap", "position"] => {
|
||||
let a = words.next().unwrap().parse().unwrap();
|
||||
let b = words.last().unwrap().parse().unwrap();
|
||||
Self::SwapPosition(a, b)
|
||||
}
|
||||
["swap", "letter"] => {
|
||||
let a = words.next().unwrap().parse().unwrap();
|
||||
let b = words.last().unwrap().parse().unwrap();
|
||||
Self::SwapLetter(a, b)
|
||||
}
|
||||
["rotate", "left"] => {
|
||||
let a = words.next().unwrap().parse().unwrap();
|
||||
Self::RotateLeft(a)
|
||||
}
|
||||
["rotate", "right"] => {
|
||||
let a = words.next().unwrap().parse().unwrap();
|
||||
Self::RotateRight(a)
|
||||
}
|
||||
["rotate", "based"] => {
|
||||
let a = words.last().unwrap().parse().unwrap();
|
||||
Self::RotateByLetter(a)
|
||||
}
|
||||
["reverse", "positions"] => {
|
||||
let a = words.next().unwrap().parse().unwrap();
|
||||
let b = words.last().unwrap().parse().unwrap();
|
||||
Self::ReversePositions(a, b)
|
||||
}
|
||||
["move", "position"] => {
|
||||
let a = words.next().unwrap().parse().unwrap();
|
||||
let b = words.last().unwrap().parse().unwrap();
|
||||
Self::Move(a, b)
|
||||
}
|
||||
_ => panic!("unknown pattern: {two_words:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user