1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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()));
}
|