Skip to content

Instantly share code, notes, and snippets.

@vertis
Created June 26, 2014 12:45
Show Gist options
  • Save vertis/667e7dcd3ff6eeb25d5b to your computer and use it in GitHub Desktop.
Save vertis/667e7dcd3ff6eeb25d5b to your computer and use it in GitHub Desktop.
This is a very basic example of a genetic algorithm for guessing the the correct word(s). Run with: ruby guessing_game.rb "My Word"
require 'pry'
class GuessOrganism
attr_accessor :guess
def initialize(word)
@guess = word
end
def fitness(target_word)
target = target_word
target.zip(@guess).inject(0) {|res,x| res+=1 if x[0]==x[1]; res }
end
def mix_and_mutate(organism)
#new_letters = [KEYSPACE.shuffle.first]
genes = self.guess.zip(organism.guess)
word = genes.map do |letters|
unless letters.uniq.count == 1
sum = letters.map{|l| KEYSPACE.index(l) }.inject{|sum,x| sum + x }
idx = sum % KEYSPACE.length
letters << KEYSPACE[idx]
end
letters.shuffle.first
end
self.class.new(word)
end
def eql?(comparee)
self == comparee
end
def ==(comparee)
self.guess == comparee.guess
end
end
target_word = ARGV.first.split('')
length = target_word.length
max = 100
current = []
minimum_health = 1
KEYSPACE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ".split("")
1.upto(10000) do |i|
current += (max-current.count).times.map do
guess_word = length.times.map { KEYSPACE.shuffle.first }
o = GuessOrganism.new(guess_word)
end
correct = current.select {|o| o.fitness(target_word) == target_word.length }
if correct.length > 0
puts "Got It! It's: #{correct.first.guess.join('')}"
break
end
alive = current.select {|o| o.fitness(target_word) >= minimum_health }
sorted = alive.sort {|a,b| b.fitness(target_word) <=> a.fitness(target_word) }
if !sorted.empty? && sorted.count>50
minimum_health = sorted[0].fitness(target_word)
end
thebest = sorted.uniq.first(KEYSPACE.length)
best_combos = thebest.combination(2)
children = best_combos.map {|a,b| [a.mix_and_mutate(b), a.mix_and_mutate(b)] }.flatten
current = thebest + children
puts "Generation: #{i} (Best: #{thebest.first.guess.join('')} #{thebest.first.fitness(target_word)} Target: #{target_word.length})"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment