94 lines
1.8 KiB
Ruby
94 lines
1.8 KiB
Ruby
class Program
|
|
include Comparable
|
|
|
|
def initialize
|
|
@instructions = []
|
|
(2 + rand(4)).times do
|
|
@instructions << random_instruction
|
|
end
|
|
end
|
|
|
|
def initialize_copy(other)
|
|
@instructions = Marshal.load(Marshal.dump(@instructions))
|
|
end
|
|
|
|
def to_s
|
|
@instructions.map do |instruction, *params|
|
|
case instruction
|
|
when :load
|
|
"load #{params.first.inspect}"
|
|
when :output
|
|
"output"
|
|
end
|
|
end.join("\n")
|
|
end
|
|
|
|
def execute
|
|
output = ""
|
|
register = "A"
|
|
@instructions.each do |instruction, *params|
|
|
case instruction
|
|
when :load
|
|
register = params.first
|
|
when :output
|
|
output += register
|
|
end
|
|
end
|
|
output
|
|
end
|
|
|
|
def mutate
|
|
case rand(4)
|
|
when 0 # remove an instruction
|
|
if @instructions.size > 1
|
|
i = rand(@instructions.size)
|
|
@instructions.delete_at(i)
|
|
end
|
|
when 1 # insert an instruction
|
|
i = rand(@instructions.size + 1)
|
|
@instructions.insert(i, random_instruction)
|
|
when 2 # replace an instruction
|
|
i = rand(@instructions.size)
|
|
@instructions[i] = random_instruction
|
|
when 3 # modify parameter
|
|
i = rand(@instructions.size)
|
|
if @instructions[i].first == :load
|
|
@instructions[i][1] = mutate_param(@instructions[i][1])
|
|
end
|
|
end
|
|
end
|
|
|
|
def length
|
|
@instructions.size
|
|
end
|
|
|
|
def <=>(other)
|
|
@instructions <=> other.instance_variable_get(:@instructions)
|
|
end
|
|
|
|
def eql?(other)
|
|
(other.class == self.class) && (other == self)
|
|
end
|
|
|
|
def hash
|
|
@instructions.hash
|
|
end
|
|
|
|
private
|
|
|
|
def random_instruction
|
|
case rand(2)
|
|
when 0
|
|
[:load, (65 + rand(26)).chr]
|
|
when 1
|
|
[:output]
|
|
end
|
|
end
|
|
|
|
def mutate_param(old_value)
|
|
chr = old_value.unpack("C").first
|
|
chr = (chr + (rand(2) + 1) * [-1, 1][rand(2)]) % 26
|
|
chr.chr
|
|
end
|
|
end
|