From: Dave Burt Date: 2005-10-27T23:27:05+09:00 Subject: Re: [SUMMARY] Ducksay (#52) "Ruby Quiz" wrote in message news:20051027140053.ITEU4942.centrmmtao03.cox.net@localhost.localdomain... > __________________ > < class Cow < Duck > > ------------------ > \ _____ > \ \\_-~~ ~~-_ > \ /~ ~\ > \ _| _ | > \ ___) ~~) ~~~--_ | > \ _-~ ~-_ ___ \ |/ > \ / _-~ ~-_ / > \ | / \ | > \ | O) | | | > | | | | > | | (O | | > \ | | |\ > (~-_ _-\ / _--_ / \ > \__~~~ ~-_ _-~ / ~\ > / ~---~~-_ ~~~ _-~ /| | > _-~ / \ ~~--~ | | | > _-~ | / | > ,-~~-_ __--~~ |-~ / > | \ | _-~ > \ |--~~ > \ | | > ~-_ _ | | > ~-_ ~~---__ _--~~\ | > ~~--__ / | > ~~---___ __--~~| | > ~~~~~ | | > | | > > That's using Ryan Leavengood's solution to display the much celebrated > line from > Dave Burt's solution. It's just so Ruby! > > It looks like people had plenty of fun solving this quiz, which is great. > We're > all about The Fun Factor(tm) here at Ruby Quiz. > > Let's get to a solution: > > ______________________ > < Dave Burt's Solution > > ---------------------- > \ > \ .-"""-. _.---..-; > :.) ;"" \/ > __..--'\ ;-"""-. ;._ > `-.___.^.___.'-.____J__/-._J > > Dave is always teaching me great Ruby tricks in his solutions and this > week's > trick of choice is right at the top of the program: > > class String > def width > inject(0) {|w, line| [w, line.chomp.size].max } > end > def height > to_a.size > end > def top > to_a.first > end > def middle > to_a.values_at(1..-1) > end > def bottom > to_a.last > end > end > > # ... > > I just know I would have written width() as: > > map { |line| line.chomp.size }.max > > Dave's is more efficient though. It only ever keeps the highest number, > instead > of building an Array of all the lengths. Just one more reason inject() is > the > one iterator to rule them all. Thanks for trick #562, Dave! > > Obviously we're just dealing with some helpers added to String above, to > make > later work easier. Just remember that String.each() traverses lines by > default > and inject() and to_a() are defined in terms of each() and there shouldn't > be > any surprises here. > > # ... > > class Duck > def self.say(speech="quack?", *args) > balloon(speech) + body(*args) > end > > def self.balloon(speech) > " _#{ '_' * speech.width }_\n" + > if speech.chomp =~ /\n/ > "/ %-#{ speech.width }s \\\n" % speech.top.chomp + > speech.middle.map do |line| > "| %-#{ speech.width }s |\n" % line.chomp > end.join + > "\\ %-#{ speech.width }s /\n" % speech.bottom.chomp > else > "< #{ speech.chomp } >\n" > end + > " -#{ '-' * speech.width }-\n" > end > > def self.body(thoughts='\\', eyes='cc', tongue=' ') > " #{thoughts} > #{thoughts} > _ ___ > / \\ / \\ > \\. |: #{eyes}| > (.|:,---, > (.|: \\( | > (. y-' > \\ _ / #{tongue} > m m > " > end > end > > # ... > > The say() method should be easy enough to digest. Build a balloon() and a > body(), slap them together, and return them. Beyond that, body() is > almost > right out of the quiz. It just builds a String, interpolating the > substitutions. > > That leaves balloon(). It's really just building a String too, with a > little > more logic thrown in. The if branch handles multiline comments, so the > speech > bubble can be rounded at the edges. Otherwise the else branch is used. > The > rest is just border drawing. > > # ... > > class Cow < Duck > def self.body(thoughts='\\', eyes='oo', tongue=' ') > " #{thoughts} ^__^ > #{thoughts} (#{eyes})\\_______ > (__)\\ )\\/\\ > #{tongue} ||----w | > || || > " > end > end > > class DuckOnWater < Duck > def self.body(thoughts='\\', eyes='尊', tongue='>') > " #{thoughts} > ` #{tongue[0, 1]}(#{eyes[0, 1]})____, > (` =~~/ > ~^~^~^~^~`---'^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~ > " > end > end > > # ... > > From there, other animals can just inherit and define a new body() method. > Now > we all truly understand Duck Typing! Everything is really just a Duck... > > # ... > > if $0 == __FILE__ > if ARGV.include?("--help") > puts "usage: #$0 animal thoughts eyes tongue puts "animals: Duck Cow DuckOnWater\n" > puts "e.g.: #$0 DuckOnWater o x ) else > animal = Object.const_get(ARGV.shift) rescue Duck > puts animal.say(STDIN.read, *ARGV) > end > end > > The main code is trivial. Show usage (if branch), or locate the proper > class > with const_get() and call say() (else branch). That's all it really takes > to > get the animals talking. > > _________________________________________________________________ > < Ryan Leavengood's Solution: Where even Chunky Bacon can talk... > > ----------------------------------------------------------------- > \ > \ __ _.._ > .-'__`-._.'.--.'.__., > /--' '-._.' '-._./ > /__.--._.--._.'``-.__/ > '._.-'-._.-._.-''-..' > > I won't show the whole thing here, but do look it over. It had a nice > collection of animals embedded in the DATA section of the code. They were > controlled through a Zoo class, where even a random animal could be chosen > to > escape(): > > # ... > > # Our lovely Zoo, full of many wacky animals > class Zoo > include Singleton > attr_reader :animals > def initialize > @animals = {} > current_key = nil > DATA.each do |line| > if line.chomp =~ /^'(\w*)':$/ > current_key = $1 > @animals[current_key] = [] > elsif current_key > @animals[current_key] << line > end > end > end > > # A random animal has escaped! > def escape > choices = @animals.keys > @animals[choices[rand(choices.length)]] > end > end > > # ... > > Ryan also emulated fortune for Windows, with only a few lines of code: > > require 'open-uri' > > # ... > > # Since I wrote this on Windows I don't have fortune...but the > # internet does! > def get_fortune > open('http://www.coe.neu.edu/cgi-bin/fortune') do |page| > page.read.scan(/
(.*)<\/pre>/m)[0][0].gsub("\t",'   ')
>   end
> end
>
> # ...
>
> Fun to read and educational at the same time.  You can't beat that folks!
>
> ________________
> < The Other Guys >
> ----------------
>        \
>         \
>         _   ___
>        / \ /   \
>        \. |: ^-|
>         (.|:,---,
>         (.|: \( |
>         (.    y-'
>          \ _ /
>           m m
>
> Jacob Quinn Shenker golfed the solution, needing less than 400 strokes. 
> Check
> it out.
>
> JB Eriksson supported thought bubbles and sent in a duck on water 
> template.
> More good stuff.
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> (Wrap Up:  This went just swimmingly!)
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>       o
>        ` >(o)____,
>           (` =~~/
>   ^~^~^~^~^~`---'^~^~^~^~^~
>
> I have to offer major thanks to everyone who made is possible for me to 
> fill a
> quiz summary with animal drawings!  How cool is that?
>
> Tomorrow's quiz takes us from animals to appliances as we build our own 
> DRYer...
>
>