genetic1/program.rb

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