Skip to content

Commit 7c129d9

Browse files
committed
Add day 21: Scrambled Passwords
1 parent e5d1456 commit 7c129d9

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

21_scrambled_passwords.rb

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
def apply(instructions, input, undo: false)
2+
instructions.reduce(input.dup) { |pw, (cmd, *args)|
3+
case cmd
4+
when :swap_letter
5+
# Undo == do
6+
pw.tr(args.join, args.join.reverse)
7+
when :swap_position
8+
# Undo == do
9+
i, j = args
10+
pw[i], pw[j] = [pw[j], pw[i]]
11+
pw
12+
when :rotate_right
13+
pw.chars.rotate(args[0] * (undo ? 1 : -1)).join
14+
when :rotate_left
15+
pw.chars.rotate(args[0] * (undo ? -1 : 1)).join
16+
when :rotate_based
17+
i = pw.index(args[0])
18+
if undo
19+
# rotate_based needs the most work to undo.
20+
# pos shift newpos
21+
# 0 1 1
22+
# 1 2 3
23+
# 2 3 5
24+
# 3 4 7
25+
# 4 6 2
26+
# 5 7 4
27+
# 6 8 6
28+
# 7 9 0
29+
# all odds have a clear pattern, all evens have a clear pattern...
30+
# except 0, which we'll just special-case.
31+
rot = i / 2 + (i % 2 == 1 || i == 0 ? 1 : 5)
32+
else
33+
rot = -(i + 1 + (i >= 4 ? 1 : 0))
34+
end
35+
pw.chars.rotate(rot).join
36+
when :reverse_positions
37+
# Undo == do
38+
c = pw.chars
39+
s, e = args
40+
c[s..e] = c[s..e].reverse
41+
c.join
42+
when :move_position
43+
from, to = undo ? args.reverse : args
44+
c = pw.chars
45+
ch = c.delete_at(from)
46+
c.insert(to, ch)
47+
c.join
48+
else raise "Unknown command #{cmd} #{args}"
49+
end
50+
}
51+
end
52+
53+
instructions = ARGF.map { |l|
54+
words = l.split
55+
# All the args are either single letters or single digits.
56+
[words[0..1].join(?_).to_sym] + words.select { |w| w.size == 1 }.map { |w|
57+
w.match?(/\d+/) ? Integer(w) : w
58+
}.freeze
59+
}.freeze
60+
61+
puts apply(instructions, 'abcdefgh')
62+
puts apply(instructions.reverse, 'fbgdceah', undo: true)

0 commit comments

Comments
 (0)