86 lines
1.5 KiB
Ruby
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
|