99 lines
2.2 KiB
Ruby
99 lines
2.2 KiB
Ruby
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
|