aoc_omni/ruby/2017/15/lib/dueling_generator.rb

86 lines
1.5 KiB
Ruby

class DuelingGenerator
attr_reader :value, :start
def initialize(value)
@value = value
@start = value
end
def self.for(string)
type, value = string.gsub("Generator ", "").split(" starts with ")
Object.const_get("DuelingGenerator::Generator#{type}").new value.to_i
end
def reset!
@value = start
end
def generate!
@value = (value * factor) % 2147483647
end
def strict_generate!
@value = (value * factor) % 2147483647
generate! until meets_criterion?
end
def meets_criterion?
value % criterion == 0
end
class GeneratorA < DuelingGenerator
def factor
16807
end
def criterion
4
end
end
class GeneratorB < DuelingGenerator
def factor
48271
end
def criterion
8
end
end
class GeneratorPair
attr_reader :g1, :g2
def initialize(g1, g2)
@g1 = g1
@g2 = g2
end
def self.for(input)
new *input.split("\n").map { |line| DuelingGenerator.for line }
end
def loose_pair_count(comparisons = 40000000)
g1.reset!
g2.reset!
pairs = 0
comparisons.times do
g1.generate!
g2.generate!
pairs += 1 if g1.value & 65535 == g2.value & 65535
end
pairs
end
def strict_pair_count(comparisons = 5000000)
g1.reset!
g2.reset!
pairs = 0
comparisons.times do
g1.strict_generate!
g2.strict_generate!
pairs += 1 if g1.value & 65535 == g2.value & 65535
end
pairs
end
end
end