Skip to content

Instantly share code, notes, and snippets.

@Vaguery
Created November 9, 2010 01:25
Show Gist options
  • Select an option

  • Save Vaguery/668573 to your computer and use it in GitHub Desktop.

Select an option

Save Vaguery/668573 to your computer and use it in GitHub Desktop.
The StrawpigScript class for creating and evaluating random arithmetic expressions in a simple linear GP language, and two examples from the book I'm working on.
require './strawpig'
puts "sample, x-20, x-10, x-1, x0, x1, x10, x20"
100.times do |i|
straw = StrawpigScript.new(10)
puts "#{i}" +
[-20,-10,-1,0,1,10,20].inject("") {|line, x| line + ", #{straw.evaluate(x).round(5)}"}
end
require './strawpig'
class StrawpigScript
def wtf
stack = []
@script.split.each do |token|
begin
case token
when /([-+]?[0-9]*\.?[0-9]+)/, /[-+]?[0-9]+/, "x"
stack.push(token)
when "+", "-", "*", "/"
raise ArgumentError, "short stack" if stack.length < 2
arg1, arg2 = stack.pop(2)
result = "(#{arg1} #{token} #{arg2})"
stack.push(result)
else
# ignore unrecognized tokens
end
rescue ArgumentError => e
# don't pop items from the stack
end
end
return stack
end
end
straw = StrawpigScript.new(50)
puts "#{straw.script}\n\n[top]"
straw.wtf.reverse.each {|item| puts ">> #{item}\n"}
20.times {puts StrawpigScript.new(20).wtf.length}
class StrawpigScript
attr_accessor :script
TOKENS = ["+", "-", "*", "/", "x", "integer", "float"]
def initialize(length)
intermediate = length.times.inject("") {|program, i| program + " #{TOKENS.sample}"}
with_ints = intermediate.gsub(/integer/) {rand(21)-10}
@script = with_ints.gsub(/float/) {(rand*20.0-10.0).round(2)}
end
def evaluate(x)
stack = []
@script.split.each do |token|
begin
case token
when /([-+]?[0-9]*\.?[0-9]+)/ # float
stack.push($1.to_f)
when /[-+]?[0-9]+/ # integer
stack.push($1.to_i)
when "+", "-", "*"
raise ArgumentError, "short stack" if stack.length < 2
arg1, arg2 = stack.pop(2)
result = arg1.send(token.intern, arg2)
stack.push(result)
when "/"
raise ArgumentError, "short stack" if stack.length < 2
arg1, arg2 = stack.pop(2)
result = (arg2 == 0) ? 0 : arg1.send(token.intern, arg2)
stack.push(result)
when "x"
stack.push x
else
# ignore unrecognized tokens
end
rescue ArgumentError => e
# don't pop items from the stack
end
end
return stack[-1] || 1000000 # the top stack item, or a huge value if it's missing
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment