genetic1/genetic.rb

60 lines
1.4 KiB
Ruby
Executable File

#!/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.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