From: Trans Date: 2008-03-03T09:47:37+09:00 Subject: Re: Hello, world? (#158) I decided to take a "meta" approach and created a quick and dirty code generator. I taught it some basic Ruby Identities and hen let it have at it. With just the 5 silly identities that it currently has it can generate never ending variations, though they get repetitive very quickly --nevertheless there are already some unexpected solutions. I suppose with maybe a few dozen identities it could get pretty interesting. Try running like so: ruby helloword.rb 100 ruby helloword.rb test 100 ruby helloword.rb output 100 The number is the number of solutions to generate, 'test' will run it through test/unit to make sure it all checks out and 'output' will print a whole bunch of "Hello, World!"s :) Oh, and yes, I know it's not all that robust. It was just a fun quick hack. But feel free to improve it and let me know if you have any good identities to add. T. --- class SimpleCodeGenerator def self.identities @identities ||= [] end def self.identity(&block) identities << block end attr_reader :original attr_accessor :alternates def initialize(original) @original = original @alternates = [original] end def generate(limit=100) work = original.dup while(alternates.size < limit) do alts = alternates.dup size = alternates.size alts.each do |alt| self.class.identities.each do |identity| self.alternates |= [identity[alt]] break if alternates.size >= limit end end end end def show_code alternates.each do |code| puts code end end def show_output alternates.each do |code| puts run(code) end end def generate_tests original_run = run(original) runner = method(:run) testcase = Class.new(Test::Unit::TestCase) alternates.each_with_index do |code, index| testcase.class_eval do define_method("test_#{index}") do assert_equal(original_run, runner[code]) end end end end def run(code) so = $stdout sio = StringIO.new $stdout, $stderr = sio, sio eval code, $TOPLEVEL_BINDING result = $stdout.string $stdout = so result end # code identities identity do |code| code.sub(/puts ["](.*)["]/, 'print "\1\n"') end identity do |code| code.sub(/puts ["](.*)["]/, 'printf "%s\n" % ["\1"]') end identity do |code| code.gsub(/["](.*)["]/, '"\1".reverse.reverse') end identity do |code| code.gsub(/['](.*)[']/){ $1.inspect } end identity do |code| code.gsub(/['](.*)[']/){ "#{$1.split(//).inspect}.join('')" } end end if __FILE__ == $0 cnt = (ARGV.find{ |a| /\d+/ =~ a } || 20).to_i scg = SimpleCodeGenerator.new("puts 'Hello, World!'") scg.generate(cnt) case ARGV[0] when 'test' require 'test/unit' scg.generate_tests when 'output' scg.show_output else scg.show_code end end