Created
January 13, 2011 19:20
-
-
Save smazhara/778428 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'rubygems' | |
require 'open-uri' | |
class SpaceCat | |
attr_reader :weight, :limbs, :color | |
attr_accessor :fitness | |
def initialize(*traits) | |
@weight, @limbs, @color, @fitness = *traits | |
end | |
def hexcolor | |
('%6s' % color.to_s(16)).gsub(' ', '0') | |
end | |
def self.random | |
new rand(1000), rand(100), rand(0xffffff) | |
end | |
def mutate | |
@weight += rand(10 * 2 + 1) - 10 | |
@weight = [[@weight, 1000].min, 1].max | |
@limbs += rand(1 * 2 + 1) - 1 | |
@limbs = [[@limbs, 100].min, 0].max | |
@color += rand(167772 * 2 + 1) - 167772 | |
@color = [[@color, 0xffffff].min, 0].max | |
end | |
def clone | |
SpaceCat.new weight, limbs, color, fitness | |
end | |
def to_s | |
'[' + [weight, limbs, hexcolor, fitness].join(' ') + ']' | |
end | |
def <=>(other) | |
self.fitness.to_i <=> other.fitness.to_i | |
end | |
end | |
class Galaxy < Struct.new :name | |
def teleport(cats) | |
traits = {} | |
%w(weight limbs hexcolor).each do |trait| | |
traits[trait.to_sym] = cats.map{|cat|cat.send trait}.join(',') | |
end | |
url = "http://spacecats.heroku.com/galaxies/#{name}" + | |
"?batch=true" + | |
"&weight=#{traits[:weight]}" + | |
"&limbs=#{traits[:limbs]}" + | |
"&color=#{traits[:hexcolor]}" | |
fitnesses = open(url).read.split(',') | |
#puts "#{url}: #{fitnesses.join(',')}" | |
cats.each_index do |i| | |
cats[i].fitness = fitnesses[i] | |
end | |
end | |
def self.all | |
@@all ||= open("http://spacecats.heroku.com/galaxies").read.split(','). | |
map{|name| new(name)} | |
end | |
end | |
class Exploration < Struct.new :galaxy, :cats, :cycles, :cutoff | |
def run | |
cycles.times do |trip| | |
galaxy.teleport(cats) | |
self.cats.sort! | |
# eliminate bottom @cutoff underperformers | |
self.cats.slice!(0, cutoff) | |
# clone top @cutoff superperformers | |
clones = cats.slice(-cutoff, cutoff).map{|cat| cat.clone} | |
self.cats += clones | |
puts "#{trip}: #{best_cat}: " + | |
cats.slice(-20,20).map{|cat|cat.fitness}.join(',') | |
cats.each{|cat| cat.mutate} | |
end | |
end | |
def best_cat | |
@best_cat ||= cats.last.dup | |
@best_cat = [@best_cat, cats.last].max.dup | |
end | |
end | |
galaxy = ARGV | |
size = 100 | |
trips = 1000 | |
crew = size.times.map{SpaceCat.random} | |
gal = Galaxy.new galaxy | |
e = Exploration.new gal, crew, trips, crew.size / 10 | |
e.run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment