2025 day 7
This commit is contained in:
parent
7708169e56
commit
ca03e4367b
8
ruby/2025/7/bin/problem
Normal file
8
ruby/2025/7/bin/problem
Normal file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require "laboratories"
|
||||
|
||||
lab = Laboratories.for STDIN.read.chomp
|
||||
|
||||
puts "Part 1: #{lab.split_count}"
|
||||
puts "Part 2: #{lab.count_tachyon_lifetimes}"
|
||||
98
ruby/2025/7/lib/laboratories.rb
Normal file
98
ruby/2025/7/lib/laboratories.rb
Normal file
@ -0,0 +1,98 @@
|
||||
class Laboratories
|
||||
attr_reader :layers
|
||||
def initialize(layers)
|
||||
@layers = layers
|
||||
end
|
||||
|
||||
def self.for(input)
|
||||
new input.split("\n").map(&Layer.method(:new))
|
||||
end
|
||||
|
||||
def split_count
|
||||
layers.reduce([layers.first.blank_beams, 0]) do |acc, layer|
|
||||
out = layer.split_beams acc[0]
|
||||
[out[0], out[1] + acc[1]]
|
||||
end[1]
|
||||
end
|
||||
|
||||
def count_tachyon_lifetimes
|
||||
@memo = {}
|
||||
count_lifetimes layers.first.line.index("S"), 0
|
||||
end
|
||||
|
||||
def count_lifetimes(position, layer)
|
||||
return @memo["#{position}/#{layer}"] if @memo.key? "#{position}/#{layer}"
|
||||
|
||||
lt = if layer >= layers.count
|
||||
1
|
||||
else
|
||||
if layers[layer].line[position] == "^"
|
||||
count_lifetimes(position - 1, layer + 1) + count_lifetimes(position + 1, layer + 1)
|
||||
else
|
||||
count_lifetimes position, layer + 1
|
||||
end
|
||||
end
|
||||
@memo["#{position}/#{layer}"] = lt
|
||||
lt
|
||||
end
|
||||
|
||||
class Tachyon
|
||||
attr_reader :lab, :position, :layer
|
||||
def initialize(lab, position, layer=0)
|
||||
@lab = lab
|
||||
@position = position
|
||||
@layer = layer
|
||||
end
|
||||
|
||||
def count_lifetimes
|
||||
if layer >= lab.layers.count
|
||||
1
|
||||
else
|
||||
if at_splitter?
|
||||
self.class.new(lab, position - 1, layer + 1).count_lifetimes +
|
||||
self.class.new(lab, position + 1, layer + 1).count_lifetimes
|
||||
else
|
||||
self.class.new(lab, position, layer + 1).count_lifetimes
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def at_splitter?
|
||||
lab.layers[layer].line[position] == "^"
|
||||
end
|
||||
end
|
||||
|
||||
class Layer
|
||||
attr_reader :line
|
||||
def initialize(line)
|
||||
@line = line
|
||||
end
|
||||
|
||||
def self.for(line)
|
||||
new line.split("")
|
||||
end
|
||||
|
||||
def blank_beams
|
||||
Array.new(line.length, false)
|
||||
end
|
||||
|
||||
def split_beams(input_beams)
|
||||
split_count = 0
|
||||
output = 0.upto(line.length - 1).map do |i|
|
||||
if line[i] == "^"
|
||||
split_count += 1 if input_beams[i]
|
||||
false
|
||||
elsif i > 0 && line[i - 1] == "^" && input_beams[i - 1]
|
||||
true
|
||||
elsif i < (line.length - 1) && line[i + 1] == "^" && input_beams[i + 1]
|
||||
true
|
||||
elsif line[i] == "S"
|
||||
true
|
||||
else
|
||||
input_beams[i]
|
||||
end
|
||||
end
|
||||
[output, split_count]
|
||||
end
|
||||
end
|
||||
end
|
||||
44
ruby/2025/7/test/test_laboratories.rb
Normal file
44
ruby/2025/7/test/test_laboratories.rb
Normal file
@ -0,0 +1,44 @@
|
||||
require "minitest/autorun"
|
||||
|
||||
require "laboratories"
|
||||
|
||||
class TestLaboratories < Minitest::Test
|
||||
def test_split_count
|
||||
lab = Laboratories.for <<-END
|
||||
.......S.......
|
||||
...............
|
||||
.......^.......
|
||||
...............
|
||||
......^.^......
|
||||
...............
|
||||
.....^.^.^.....
|
||||
...............
|
||||
....^.^...^....
|
||||
...............
|
||||
...^.^...^.^...
|
||||
...............
|
||||
..^...^.....^..
|
||||
...............
|
||||
.^.^.^.^.^...^.
|
||||
...............
|
||||
END
|
||||
assert_equal(21, lab.split_count)
|
||||
end
|
||||
end
|
||||
|
||||
class TestLayer < Minitest::Test
|
||||
def test_split_beams
|
||||
layer = Laboratories::Layer.for(".S.")
|
||||
assert_equal([[false, true, false], 0], layer.split_beams([false, false, false]))
|
||||
|
||||
layer = Laboratories::Layer.for("..")
|
||||
assert_equal([[true, false], 0], layer.split_beams([true, false]))
|
||||
|
||||
layer = Laboratories::Layer.for(".^.")
|
||||
assert_equal([[true, false, true], 1], layer.split_beams([false, true, false]))
|
||||
|
||||
layer = Laboratories::Layer.for("^.^")
|
||||
assert_equal([[false, true, false], 0], layer.split_beams([false, true, false]))
|
||||
assert_equal([[false, true, false], 2], layer.split_beams([true, false, true]))
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user