This was quite fun. I decided not to go into ASCII art creation and
"cheated" by getting some wacky animals from http://www.ascii-art.de,
including several ducks. As noted in the source I developed this on a
Windows machine which does not have fortune (at least without getting
Cygwin, etc.), so I found a CGI script online which has fortune, and I
use open-uri to access it.
I'm sure my "bubble maker" could be golfed down a bit, but I preferred
clarity over terseness.
All the animals in the "zoo" are embedded in the DATA section of the
script, with a special format to delimit them. It is fairly easy to
add new animals should one want to.
I also used a different style of command-line options, since it fit
this problem. Here is an example run:
C:\_Ryan\ruby\quiz\52_ducksay>ruby ducksay.rb gecko.say "Ruby Rocks!"
···
_____________
< Ruby Rocks! >
-------------
\
\
___
)/_ ,@ /
>(_,' _@/
> /
\)/ / (_)/
((_/ ,----~
\ (_)/
/ ,-----~
((' _,-.
\\=//
The text after my name will be the code for my solution.
Ryan
require 'open-uri'
require 'singleton'
# Here we have a bubble machine
class Bubble
def self.make(text)
return '' if text.nil? or text == ''
result = ''
lines = text.split("\n")
max_length = lines.max{|a,b| a.length <=> b.length}.length
hf = proc {|s| " #{s * (max_length+2)} \n"}
result << hf['_']
case lines.length
when 1: result << "< #{lines[0]} >\n"
else
pad_it = proc {|s| s.ljust(max_length)}
result << "/ #{pad_it[lines.shift]} \\\n"
0.upto(lines.length-2) do |i|
result << "| #{pad_it[lines[i]]} |\n"
end
result << "\\ #{pad_it[lines[-1]]} /\n"
end
result << hf['-']
end
end
# 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
# 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>(.*)<\/pre>/m)[0][0].gsub("\t",' ')
end
end
if $0 == __FILE__
animal = nil
message = nil
case ARGV[0]
when 'list':
puts "Your zoo contains the following animals:"
puts Zoo.instance.animals.keys.sort.join("\n")
exit(0)
when /\A(\w*)\.say/:
animal = Zoo.instance.animals[$1]
unless animal
puts "Unknown animal #$1! Try 'list' to list your animals."
exit(1)
end
if ARGV.length > 1
message = ARGV[1..-1].join(" ")
end
when nil:
animal = Zoo.instance.escape
else
puts "Usage: #$0 <command>",
"Where command is",
"\tlist: to list your animals.",
"\t<animal>.say \"<message>\": to have that animal say that",
"\t\tmessage, where the message is optional.",
"\nWith no command the default is a random animal, with a",
"message from fortune."
exit(1)
end
unless message
message = get_fortune
end
puts Bubble.make(message)
puts animal
end
# The ASCII animals below are courtesy of http://www.ascii-art.de
__END__
'crazyduck':
\ _____
\ \\_-~~ ~~-_
\ /~ ~\
\ _| _ |
\ ___) ~~) ~~~–_ |
\ _-~ ~-_ ___ \ |/
\ / _-~ ~-_ /
\ | / \ |
\ | O) | | |
> > > >
> > (O | |
\ | | |\
(~-_ _-\ / _–_ / \
\__~~~ ~-_ _-~ / ~\
/ ~—~~-_ ~~~ _-~ /| |
_-~ / \ ~~–~ | | |
_-~ | / |
,-~~-_ __–~~ |-~ /
> \ | _-~
\ |–~~
\ | |
~-_ _ | |
~-_ ~~—__ _–~~\ |
~~–__ / |
~~—___ __–~~| |
~~~~~ | |
> >
'lazyduck':
\
\ .-"""-. _.—…-;
:.) ;"" \/
__…–'\ ;-"""-. ;._
`-.___.^.___.'-.____J__/-._J
'duck':
\
\ _.-.
__.-' , \
'–'-'._ \
'. \
)-- \ __.–._
/ .' '–.
. _/-._
: ____._/ _-'
'._ _.'-'
'-._ _.'
\_|/
__|||
>__/'
'chunkybacon':
\
\ __ _…_
.-'__`-._.'.–.'.__.,
/–' '-._.' '-._./
/__.–._.–._.'``-.__/
'._.-'-._.-._.-''-…'
'raccoon':
\
\ __ .-.
\ .-"` .`'. /\\|
_(\-/)_" , . ,\ /\\\/
{(#b^d#)} . ./, |/\\\/
`-.(Y).-` , | , |\.-`
/~/,_/~~~\,__.-`
////~ // ~\\
==`==` ==` ==`
'bat':
\
\
, \ ,
./( )\.
) \/\_/\/ (
`) (^Y^) (`
`),-(~)-,(`
'"'
'buffalo':
\
\ _.-````'-,_
_,.,_ ,-'` `'-.,_
/) (\ '``-.
(( ) ) `\
\) (_/ )\
> /) ' ,' / \
`\ ^' ' ( / ))
> _/\ , / ,`\ ( "`
\Y, | \ \ | ````| / \_ \
`)_/ \ \ ) ( > ( >
\( \( |/ |/
/_(/_( /_( /_(
'gecko':
\
\
___
)/_ ,@ /
>(_,' _@/
> /
\)/ / (_)/
((_/ ,----~
\ (_)/
/ ,-----~
((' _,-.
\\=//
'gorilla':
\
\
\ ."`".
.-./ _=_ \.-.
{ (,(oYo),) }}
{{ | " |} }
{ { \(—)/ }}
{{ }'-=-'{ } }
{ { }._:_.{ }}
{{ } -:- { } }
{_{ }`===`{ _}
((((\) (/))))
'gryphon':
\ ______
\ ______,—'__,—'
\ _,-'—_---__,—'
/_ (, —____',
/ ', `, ,-'
;/) ,',_/,'
> /\ ,.'//\
`-` \ ,' `.
`', ,-- `.
'/ / | `, _
//'',.\_ .\\ ,{==>-
__// __;_`- \ `;.__,;'
((,–,) (((,------; `–'
``` ' ```
'wombat':
\ ,.–""""–…_
\ ." .' `-.
\ ; ; ;
\ ' ; )
\ / ' . ;
/ ; `. `;
,.' : . : )
;|\' : `./|) \ ;/
;| \" -,- "-./ |; ).;
/\/ \/ );
: \ ;
: _ _ ; )
`. \;\ /;/ ; /
! : : ,/ ;
(`. : _ : ,/"" ;
\\\`"^" ` : ;
( )
////
'seaturtle':
/
/ _,.—.---.—.–…_
/ _.-' `–.`—.`—'-. _,`–…_
/ /`–._ .'. `. `,`-.`-._\
>> \ `.`—.__`__…-`. ,'`-._/
_ ,`\ `-._\ \ `. `_.-`-._,``-.
,` `-_ \/ `-.`–.\ _\_.-'\__.-`-.`-._`.
(_.o> ,–. `._/'–.-`,–` \_.-' \`-._ \
`—' `._ `—._/__,----` `-. `-\
/_, , _…-' `-._\
\_, \/ ._(
\_, \/ ._\
`._,\/ ._\
`._// ./`-._
`-._-_-_.-'
'lemur':
\ ,
\ ==
\ ==
\ ==
\ ==
== ==
== == ==
== ==
, , ==
>\/| ,-…-,
,d__(…)\_/ \
;-,_`o/ |
'-| \_,' /^| /
( // / \ \
>> \ < \ )
_\| \ ) _\\
~` _\| ~`
~`
'koala':
\
\ ) ( |
\ ) ( / .-
_ ,—. _ ( / /
(~-| . . |-~) V /
\._ 0 _,/ /
/ `-^-'`-._ /
' `-. (
: )E
: ,—' (
. )E (
'._____,—' (
) (
) (
) (
) (
'armadillo':
\
\ __-----.,
.-:::,\\\\\::::,
\|\;`:::`` \\\\\\\'':\
/`'\\:: |||||| '\
/ e (\` |||||| , '.
.` _.-`~\_____/`````_X__/'-__~===-
'-~` ~~ ~~