59 lines
1.3 KiB
Ruby
Executable File
59 lines
1.3 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
|
|
end
|
|
grade
|
|
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 "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
|