Skip to content

Commit

Permalink
Year 2015: Day 19
Browse files Browse the repository at this point in the history
  • Loading branch information
joshleaves committed Feb 14, 2024
1 parent 150ef67 commit 47d3081
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 1 deletion.
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
--require spec_helper
--fail-fast
-I .
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Consistency is hard without proper goals to set a good (let's dare say "atomic")
I'm also adding notes that may be useful if you're learning Ruby.

Notes for solving:
* [2015, up to day 18](year_2015.md)
* [2015, up to day 19](year_2015.md)
* [2023, up to day 03](year_2023.md)

# How to use
Expand Down
45 changes: 45 additions & 0 deletions spec/year_2015/day_19_input
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Al => ThF
Al => ThRnFAr
B => BCa
B => TiB
B => TiRnFAr
Ca => CaCa
Ca => PB
Ca => PRnFAr
Ca => SiRnFYFAr
Ca => SiRnMgAr
Ca => SiTh
F => CaF
F => PMg
F => SiAl
H => CRnAlAr
H => CRnFYFYFAr
H => CRnFYMgAr
H => CRnMgYFAr
H => HCa
H => NRnFYFAr
H => NRnMgAr
H => NTh
H => OB
H => ORnFAr
Mg => BF
Mg => TiMg
N => CRnFAr
N => HSi
O => CRnFYFAr
O => CRnMgAr
O => HP
O => NRnFAr
O => OTi
P => CaP
P => PTi
P => SiRnFAr
Si => CaSi
Th => ThCa
Ti => BP
Ti => TiTi
e => HF
e => NAl
e => OMg

ORnPBPMgArCaCaCaSiThCaCaSiThCaCaPBSiRnFArRnFArCaCaSiThCaCaSiThCaCaCaCaCaCaSiRnFYFArSiRnMgArCaSiRnPTiTiBFYPBFArSiRnCaSiRnTiRnFArSiAlArPTiBPTiRnCaSiAlArCaPTiTiBPMgYFArPTiRnFArSiRnCaCaFArRnCaFArCaSiRnSiRnMgArFYCaSiRnMgArCaCaSiThPRnFArPBCaSiRnMgArCaCaSiThCaSiRnTiMgArFArSiThSiThCaCaSiRnMgArCaCaSiRnFArTiBPTiRnCaSiAlArCaPTiRnFArPBPBCaCaSiThCaPBSiThPRnFArSiThCaSiThCaSiThCaPTiBSiRnFYFArCaCaPRnFArPBCaCaPBSiRnTiRnFArCaPRnFArSiRnCaCaCaSiThCaRnCaFArYCaSiRnFArBCaCaCaSiThFArPBFArCaSiRnFArRnCaCaCaFArSiRnFArTiRnPMgArF
5 changes: 5 additions & 0 deletions spec/year_2015/day_19_sample_one
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
H => HO
H => OH
O => HH

HOH
7 changes: 7 additions & 0 deletions spec/year_2015/day_19_sample_two
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
e => H
e => O
H => HO
H => OH
O => HH

HOHOHO
41 changes: 41 additions & 0 deletions spec/year_2015/day_19_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'year_2015/day_19'

describe Year2015::Day19 do
context 'when Part 1' do
subject(:sample_one) do
described_class.new(File.read('spec/year_2015/day_19_sample_one'), true)
end

it 'calculates all permutations' do
expect(sample_one.permutations).to eq(%w(HOOH HOHO OHOH HHHH).sort)
end

it 'gives a final result' do
expect(sample_one.to_i).to eq(4)
end
end

context 'when Part 2' do
subject(:sample_two) do
described_class.new(File.read('spec/year_2015/day_19_sample_two'))
end

it 'gives a final result' do
expect(sample_two.build_molecule).to eq(5)
end
end

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

it 'correctly answers part 1' do
expect(described_class.new(input_data, true).to_i).to eq(576)
end

it 'correctly answers part 2' do
expect(described_class.new(input_data).build_molecule).to eq(207)
end
end
end
16 changes: 16 additions & 0 deletions year_2015.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,19 @@ Year2015::Day18
I already touched upon [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) earlier, and this exercise is a good example of it.

I thought I was being smart by only keeping track of positions of only ON lights, which was a good implementation for a six-by-six data set, but proved UTTERLY SLOW on the final data set. Using an array of strings (as is the most naive implementation) is indeed the fastest way to do it. I still kept the old code commented.

## Day 19

```
Year2015::Day19
when Part 1
calculates all permutations
gives a final result
when Part 2
gives a final result
when Results
correctly answers part 1
correctly answers part 2
```

Part one is nothing to write home about. However, part two... First idea was the good ol' bruteforce approach, but when searching if there was an algorithm I didn't know, I stumbled upon a [very interesting Reddit comment](https://www.reddit.com/r/adventofcode/comments/3xflz8/day_19_solutions/cy4h7ji/)...
55 changes: 55 additions & 0 deletions year_2015/day_19.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class Year2015
class Day19
attr_accessor :starter, :molecules

RE_MOLECULE = /^(\w+) => (\w+)$/

def initialize(input_data, input_part_one = false)
@version = input_part_one ? 1 : 2
input_data = input_data.chomp.split("\n").reject(&:empty?)
@starter = input_data.pop
@molecules = {}
input_data.map do |input_line|
input_line =~ RE_MOLECULE
@molecules[$1] ||= []
@molecules[$1].push($2)
[$1, $2]
end
end

def do_permutations(input, replacements)
re_input = /(#{input})/
parts = starter.scan(re_input).length
replacements.each do |replacement|
0.upto(parts - 1) do |idx|
new_str = starter.gsub(re_input).each_with_index do |_part, i|
idx == i ? replacement : input
end
@permutations.push(new_str)
end
end
end

def permutations
@permutations ||= begin
@permutations = []
@molecules.each do |input, replacements|
do_permutations(input, replacements)
end
@permutations.sort.uniq
end
end

def to_i
@to_i ||= permutations.uniq.length
end

def count_str(symbol)
@starter.scan(/#{symbol}/).length
end

def build_molecule
@starter.scan(/[A-Z]/).length - count_str('Rn') - count_str('Ar') - (2 * count_str('Y')) - 1
end
end
end

0 comments on commit 47d3081

Please sign in to comment.