#!/usr/bin/env ruby require_relative "program" NUM_PROGRAMS = 100 EXPECTED_OUTPUT = "HELLOWORLD" def ord(chr) chr.unpack("C").first end def grade_program(p) output = p.execute grade = (EXPECTED_OUTPUT.size - output.size).abs * 100 [EXPECTED_OUTPUT.size, output.size].min.times do |i| grade += (ord(EXPECTED_OUTPUT[i]) - ord(output[i])).abs * 10 end grade + p.length end def main programs = NUM_PROGRAMS.times.map do p = Program.new [grade_program(p), p] end generation = 0 begin last_best = nil while true generation += 1 programs += programs.map do |grade, p| p2 = p.clone p2.mutate [grade_program(p2), p2] end programs.uniq! programs.sort! do |a, b| a.first <=> b.first end programs = programs.take(NUM_PROGRAMS) if last_best.nil? or programs.first.first < last_best last_best = programs.first.first $stdout.write("\rGrade: #{last_best}, output: #{programs.first.last.execute.inspect} ") end if programs.first.first == 0 puts puts "Program found after #{generation} generations:" puts programs.first.last break end end rescue Interrupt puts puts "Canceled at #{generation} generations" puts "The best program (grade #{programs.first.first}) is:" puts programs.first.last end end main