Skip to content

Commit

Permalink
Year 2016: Day 21
Browse files Browse the repository at this point in the history
  • Loading branch information
joshleaves committed Mar 13, 2024
1 parent 7fc502e commit b663d89
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ I'm also adding notes that may be useful if you're learning Ruby.

Notes for solving:
* [2015, complete](year_2015.md)
* [2016, up to day 20](year_2016.md)
* [2016, up to day 21](year_2016.md)
* [2023, up to day 04](year_2023.md)

# How to use
Expand Down
100 changes: 100 additions & 0 deletions spec/year_2016/day_21_input
Original file line number Diff line number Diff line change
@@ -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
36 changes: 36 additions & 0 deletions spec/year_2016/day_21_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'year_2016/day_21'

describe Year2016::Day21 do
context 'when Part 1' do
subject(:sample_one) do
<<~HEREDOC
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
HEREDOC
end

it 'gives a final result' do
expect(described_class.new(sample_one, true).solve('abcde')).to eq('decab')
end
end

context 'when Results' do
subject(:input_data) do
File.read('spec/year_2016/day_21_input')
end

it 'correctly answers part 1' do
expect(described_class.new(input_data, true).solve('abcdefgh')).to eq('gfdhebac')
end

it 'correctly answers part 2' do
expect(described_class.new(input_data).solve('fbgdceah')).to eq('dhaegfbc')
end
end
end
13 changes: 13 additions & 0 deletions year_2016.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,16 @@ Year2016::Day20
```

Dealing with indexes inclusion can often be a pain in counting.

## Day 21: Scrambled Letters and Hash

```
Year2016::Day21
when Part 1
gives a final result
when Results
correctly answers part 1
correctly answers part 2
```

While [some of my counterparts](https://github.com/rHermes/adventofcode/blob/master/2016/21/y2016_d21_p02.py) tried using complete brute-force approach to get the original password, I found reversing the instructions to be much more funnier.
1 change: 0 additions & 1 deletion year_2016/day_11.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ def initialize(input_file, input_part_one = false)
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity

def search(states, moves_tried, depth)
# puts "DEPTH: #{depth} => #{states.length} (#{moves_tried.length})"
return depth if states.any?{|state| state.all?(3) }

next_states = []
Expand Down
89 changes: 89 additions & 0 deletions year_2016/day_21.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
class Year2016
class Day21
def initialize(input_data, input_part_one = false)
@version = input_part_one ? 1 : 2
@instructions = input_data.lines.map do |instruction|
compile_instruction(instruction.chomp)
end
end

# rubocop:disable Metrics/MethodLength
def compile_instruction(instruction)
case instruction
when /^swap position (\d+) with position (\d+)$/
[:swap_positions, $1.to_i, $2.to_i]
when /^swap letter (\w) with letter (\w)$/
[:swap_letters, $1, $2]
when /^rotate (\bleft\b|\bright\b) (\d+) steps?$/
[:"rotate_#{$1}", $2.to_i]
when /^rotate based on position of letter (\w)$/
[:rotate_based_on, $1]
when /^reverse positions (\d+) through (\d+)$/
[:reverse, $1.to_i, $2.to_i]
when /^move position (\d+) to position (\d+)$/
[:move, $1.to_i, $2.to_i]
else
raise "Unknown instruction: #{instruction}"
end
end
# rubocop:enable Metrics/MethodLength

def swap_positions(from, to)
@password[from], @password[to] = @password[to], @password[from]
end

def swap_letters(from, to)
@password.gsub!(from, '_')
@password.gsub!(to, from)
@password.gsub!('_', to)
end

def reverse(from, to)
@password[from..to] = @password[from..to].reverse
end

def _rotate(input, steps)
input.chars.rotate(steps).join
end

def rotate_left(steps)
@password = _rotate(@password, @version == 1 ? steps : steps * -1)
end

def rotate_right(steps)
@password = _rotate(@password, @version == 2 ? steps : steps * -1)
end

def move(from, to)
from, to = to, from if @version == 2
pass_arr = @password.chars
extract = pass_arr.delete_at(from)
pass_arr.insert(to, extract)
@password = pass_arr.join
end

def _rotate_based_on(input, index)
index = input.index(index)
index += index >= 4 ? 2 : 1
_rotate(input, index * -1)
end

def rotate_based_on(index)
return @password = _rotate_based_on(@password, index) if @version == 1

1.upto(@password.length) do |i|
str = _rotate(@password, i * - 1)
return @password = str if _rotate_based_on(str, index) == @password
end
raise 'NOT FOUND'
end

def solve(input_password)
@password = input_password
@instructions.send(@version == 2 ? :reverse_each : :each) do |instruction|
send(*instruction)
end
@password
end
end
end

0 comments on commit b663d89

Please sign in to comment.