diff --git a/README.md b/README.md index 7578901..d22c9cd 100644 --- a/README.md +++ b/README.md @@ -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 11](year_2016.md) +* [2016, up to day 12](year_2016.md) * [2023, up to day 04](year_2023.md) # How to use diff --git a/spec/year_2016/day_12_input b/spec/year_2016/day_12_input new file mode 100644 index 0000000..0eeb395 --- /dev/null +++ b/spec/year_2016/day_12_input @@ -0,0 +1,23 @@ +cpy 1 a +cpy 1 b +cpy 26 d +jnz c 2 +jnz 1 5 +cpy 7 c +inc d +dec c +jnz c -2 +cpy a c +inc a +dec b +jnz b -2 +cpy c b +dec d +jnz d -6 +cpy 14 c +cpy 14 d +inc a +dec d +jnz d -2 +dec c +jnz c -5 diff --git a/spec/year_2016/day_12_sample_one b/spec/year_2016/day_12_sample_one new file mode 100644 index 0000000..01a004b --- /dev/null +++ b/spec/year_2016/day_12_sample_one @@ -0,0 +1,6 @@ +cpy 41 a +inc a +inc a +dec a +jnz a 2 +dec a diff --git a/spec/year_2016/day_12_spec.rb b/spec/year_2016/day_12_spec.rb new file mode 100644 index 0000000..64580b4 --- /dev/null +++ b/spec/year_2016/day_12_spec.rb @@ -0,0 +1,28 @@ +require 'year_2016/day_12' + +describe Year2016::Day12 do + context 'when Part 1' do + subject(:sample_one) do + described_class.new(File.read('spec/year_2016/day_12_sample_one')).program + end + + it 'gives a final result' do + sample_one.execute + expect(sample_one.registers['a']).to eq(42) + end + end + + context 'when Results' do + subject(:input_data) do + File.read('spec/year_2016/day_12_input') + end + + it 'correctly answers part 1' do + expect(described_class.new(input_data).part_one).to eq(318_007) + end + + it 'correctly answers part 2' do + expect(described_class.new(input_data).part_two).to eq(9_227_661) + end + end +end diff --git a/year_2016.md b/year_2016.md index 9328739..9ac252f 100644 --- a/year_2016.md +++ b/year_2016.md @@ -161,3 +161,16 @@ Year2016::Day11 It seems this exercise got [some people to give up](https://markheath.net/post/aoc-2016-day11), and quite frankly, I felt like it for a while too. In the end, brute-forcing wasn't efficient, but trying a proper implementation of [A* (A-Star)](https://en.wikipedia.org/wiki/A*_search_algorithm) will solve it in a good time. Now, as for part two... I hope you got twelve minutes to run tests. + +## Day 12: Leonardo's Monorail + +``` +Year2016::Day12 + when Part 1 + gives a final result + when Results + correctly answers part 1 + correctly answers part 2 +``` + +After yesterday's mess, building a [virtual machine](https://en.wikipedia.org/wiki/Virtual_machine) is a delight. Nothing specific, refer to [Year 2015, Day 23](year_2015.md#day-23-opening-the-turing-lock) for more info. diff --git a/year_2016/day_12.rb b/year_2016/day_12.rb new file mode 100644 index 0000000..18545e4 --- /dev/null +++ b/year_2016/day_12.rb @@ -0,0 +1,70 @@ +class Year2016 + class Day12 + attr_accessor :program + + class Program + attr_accessor :instructions, :pc, :registers + + def initialize(input_instructions) + @instructions = input_instructions.map do |instruction| + [instruction, compile(instruction)] + end + end + + def inc(register) + @pc += 1 + @registers[register] += 1 + end + + def dec(register) + @pc += 1 + @registers[register] -= 1 + end + + def cpy(from, to) + @pc += 1 + @registers[to] = registers[from] || from.to_i + end + + def jnz(value, jmp) + return @pc += 1 if (@registers[value] || value.to_i).zero? + + @pc += jmp.to_i + end + + def compile(instruction) + case instruction + when /^cpy (-?\d+|[abcd]) ([abcd])$/ + [:cpy, $1, $2] + when /^inc ([abcd])$/ + [:inc, $1] + when /^dec ([abcd])$/ + [:dec, $1] + when /^jnz (-?\d+|[abcd]) (-?\d+)$/ + [:jnz, $1, $2] + end + end + + def execute(init_registers = { 'a' => 0, 'b' => 0, 'c' => 0, 'd' => 0 }) + @pc = 0 + @registers = init_registers + + send(*instructions[@pc].last) while instructions[@pc] + end + end + + def initialize(input_data) + @program = Program.new(input_data.chomp.split("\n")) + end + + def part_one + @program.execute + @program.registers['a'] + end + + def part_two + @program.execute('a' => 0, 'b' => 0, 'c' => 1, 'd' => 0) + @program.registers['a'] + end + end +end