solution: day 21
This commit is contained in:
parent
9c0653f39e
commit
9f353660f1
@ -18,7 +18,7 @@ pub mod d17;
|
|||||||
pub mod d18;
|
pub mod d18;
|
||||||
pub mod d19;
|
pub mod d19;
|
||||||
pub mod d20;
|
pub mod d20;
|
||||||
// pub mod d21;
|
pub mod d21;
|
||||||
// pub mod d22;
|
// pub mod d22;
|
||||||
// pub mod d23;
|
// pub mod d23;
|
||||||
// pub mod d24;
|
// pub mod d24;
|
||||||
|
|||||||
151
src/days/d21.rs
Normal file
151
src/days/d21.rs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = Vec<Inst>;
|
||||||
|
pub type O = String;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Inst {
|
||||||
|
SwapPos (usize, usize),
|
||||||
|
SwapLetter (char, char),
|
||||||
|
RotateLeft (usize),
|
||||||
|
RotateRight (usize),
|
||||||
|
RotatePos (char),
|
||||||
|
Reverse (usize, usize),
|
||||||
|
Move (usize, usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// const _rotations: [usize; 8] = [1,2,3,4,6,7,0,1];
|
||||||
|
// ↓
|
||||||
|
const _rotations: [usize; 8] = [1,1,6,2,7,3,0,4];
|
||||||
|
|
||||||
|
|
||||||
|
impl Inst {
|
||||||
|
fn from_str (i: &str) -> Self {
|
||||||
|
let i = i.trim();
|
||||||
|
if let Some(sfx) = i.strip_prefix("swap position ") {
|
||||||
|
let (l, r) = sfx.split_once(" with position ").unwrap();
|
||||||
|
Inst::SwapPos(p!(l), p!(r))
|
||||||
|
} else if let Some(sfx) = i.strip_prefix("swap letter ") {
|
||||||
|
let (l, r) = sfx.split_once(" with letter ").unwrap();
|
||||||
|
Inst::SwapLetter(l.trim().chars().next().unwrap(), r.trim().chars().next().unwrap())
|
||||||
|
} else if let Some(sfx) = i.strip_prefix("rotate left ") {
|
||||||
|
let (l, _) = sfx.split_once(' ').unwrap();
|
||||||
|
Inst::RotateLeft(p!(l))
|
||||||
|
} else if let Some(sfx) = i.strip_prefix("rotate right ") {
|
||||||
|
let (l, _) = sfx.split_once(' ').unwrap();
|
||||||
|
Inst::RotateRight(p!(l))
|
||||||
|
} else if let Some(sfx) = i.strip_prefix("rotate based on position of letter ") {
|
||||||
|
Inst::RotatePos(sfx.chars().next().unwrap())
|
||||||
|
} else if let Some(sfx) = i.strip_prefix("reverse positions ") {
|
||||||
|
let (l, r) = sfx.split_once(" through ").unwrap();
|
||||||
|
Inst::Reverse(p!(l), p!(r))
|
||||||
|
} else if let Some(sfx) = i.strip_prefix("move position ") {
|
||||||
|
let (l, r) = sfx.split_once(" to position ").unwrap();
|
||||||
|
Inst::Move(p!(l), p!(r))
|
||||||
|
} else {
|
||||||
|
panic!("unknown instruction")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply (self, target: &mut Vec<char>) {
|
||||||
|
use Inst as I;
|
||||||
|
match self {
|
||||||
|
I::SwapPos(l, r) => target.swap(l, r),
|
||||||
|
I::SwapLetter(l, r) => {
|
||||||
|
let lpos = target.iter().position(|&c| c == l);
|
||||||
|
let rpos = target.iter().position(|&c| c == r);
|
||||||
|
if let Some(lpos) = lpos && let Some(rpos) = rpos {
|
||||||
|
target.swap(lpos, rpos);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
I::RotateLeft(times) => target.rotate_left(times),
|
||||||
|
I::RotateRight(times) => target.rotate_right(times),
|
||||||
|
I::RotatePos(needle) => {
|
||||||
|
let pos = target.iter().position(|&c| c == needle);
|
||||||
|
if let Some(pos) = pos {
|
||||||
|
let rotations = pos + 1 + if pos >= 4 { 1 } else { 0 };
|
||||||
|
let len = target.len(); // % len is useless in my input but needed for the general correctness of the algorithm
|
||||||
|
target.rotate_right(rotations % len);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
I::Reverse(from, to) => (&mut target[from..=to]).reverse(),
|
||||||
|
I::Move(from, to) => {
|
||||||
|
let val = target.remove(from);
|
||||||
|
target.insert(to, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn undo (self, target: &mut Vec<char>) {
|
||||||
|
use Inst as I;
|
||||||
|
match self {
|
||||||
|
I::SwapPos(l, r) => target.swap(l, r),
|
||||||
|
I::SwapLetter(l, r) => {
|
||||||
|
let lpos = target.iter().position(|&c| c == l);
|
||||||
|
let rpos = target.iter().position(|&c| c == r);
|
||||||
|
if let Some(lpos) = lpos && let Some(rpos) = rpos {
|
||||||
|
target.swap(lpos, rpos);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
I::RotateLeft(times) => target.rotate_right(times),
|
||||||
|
I::RotateRight(times) => target.rotate_left(times),
|
||||||
|
I::RotatePos(needle) => {
|
||||||
|
let pos = target.iter().position(|&c| c == needle);
|
||||||
|
if let Some(pos) = pos {
|
||||||
|
target.rotate_left(_rotations[pos]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
I::Reverse(from, to) => (&mut target[from..=to]).reverse(),
|
||||||
|
I::Move(from, to) => {
|
||||||
|
let val = target.remove(to);
|
||||||
|
target.insert(from, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> I {
|
||||||
|
data.trim().lines().map(Inst::from_str).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (start: &'static str, list: I) -> O {
|
||||||
|
let mut state = start.chars().collect_vec();
|
||||||
|
list.into_iter().for_each(|i| i.apply(&mut state));
|
||||||
|
state.into_iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (start: &'static str, mut list: I) -> O {
|
||||||
|
list.reverse();
|
||||||
|
let mut state = start.chars().collect_vec();
|
||||||
|
list.into_iter().for_each(|i| i.undo(&mut state));
|
||||||
|
state.into_iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> I {
|
||||||
|
let data = inc!(21);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver("abcdefgh", data);
|
||||||
|
|
||||||
|
assert_eq!(ans, s!("bfheacgd"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold("fbgdceah", data);
|
||||||
|
|
||||||
|
assert_eq!(ans, s!("gcehdbfa"))
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user