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