class Program 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 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