1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.
2. Support Ruby Quiz by submitting ideas as often as you can:
3. Enjoy!
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
by Jonas Pfenniger
__________________________________
< Welcome to this week's Ruby Quiz >
----------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
This week, we will make some ascii-art for fun.
Produce a script that generates funny talking animals. The executable
consists of three parts.
Part One : The balloon
=====================
The balloon is the surrounding part, in which the text will be shown. You can
make it like you want.
Examples :
One-liner
_______________
< I love ruby ! >
---------------
Multiple lines with text wrapping and carriage return
__________________________________________
/ Q:How do you stop an elephant from \
| charging? |
\ A:Take away his credit cards. /
------------------------------------------
Part Two : The template
=======================
To make it flexible, we'll need a template language that can combine the animal
and the text. You'll have to think about how you want to make it flexible
enough.
Example :
# thoughts is the balloon's tail
def animal(thoughts = '\', eyes = 'oo', tongue=' ')
%[#{baloon}
#{thoughts} ^__^
#{thoughts} (#{eyes})\\_______
(__)\\ )\\/\\
#{tongue} ||----w |
|| ||
]
end
Part Three : The command-line arguments
=======================================
There are no special arguments. I would suggest asking for a text input, but you
can also get the text from `fortune` or make it editable in place. Optional
arguments can be given to change the selected template and some of its
variables like the eyes, the tongue, and the balloon's tail.
Use your imagination !
So that's it for the quiz. Extra points are given to the person who
provides a duck template.
Credits
=======
- cowsay : http://www.cowsay.net/
-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
ez...@yakima-herald.com
> This looks like a really fun quiz!
I thought so too. Submitters always make better quizzes than me,
which is why I encourage them so much. ;)
This is a terrific problem for beginners, so hopefully we'll see some
new names in the solutions!
James Edward Gray II
Well, I'm new on this quiz thingy... And I've already have some results to
show off (which I hope isn't a spoiler):
_________________________
/The quick brown fox jumps\
\ over the lazy dog. /
-------------------------
\
` >(o)____,
(` =~~/
^~^~^~^~^~`---'^~^~^~^~^~^~^~^~^~^~
I've sacrificed a couple of characters to get flexibility on the template,
however. and no tongue. I also have the commandline arguments to take care
of as well.
/Johan
> Well, I'm new on this quiz thingy... And I've already have some
> results to
> show off (which I hope isn't a spoiler):
> _________________________
> /The quick brown fox jumps\
> \ over the lazy dog. /
> -------------------------
> \
> ` >(o)____,
> (` =~~/
> ^~^~^~^~^~`---'^~^~^~^~^~^~^~^~^~^~
Looking great! Can't wait to see it.
James Edward Gray II
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
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
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
if $0 == __FILE__
if ARGV.include?("--help")
puts "usage: #$0 animal thoughts eyes tongue <speech\n"
puts "animals: Duck Cow DuckOnWater\n"
puts "e.g.: #$0 DuckOnWater o x ) </etc/fortune\n"
else
animal = Object.const_get(ARGV.shift) rescue Duck
puts animal.say(STDIN.read, *ARGV)
end
end
/Johan B Eriksson
-----------
cowsay.rb:
-----------
# Rubyquiz #52, Ducksay
# ascii animals talking using ascii comic balloons.
#
#
# I couldn't get commandline arguments working properly on my machine, so I
skipped it.
# Instead, change the variable values to suit your needs.
#
# This solution does not automatically wordwrap the sayings. Do it manually
######################
#!/usr/bin/env ruby
# ~383 chars
# y = "eye"
# m = "beak/mouth"
# z = "balloon tail"
# f = "text" (defaults to fortune)
y="º"[0..1];m=">"[0..1];z="\\";w=40;N="\n";BS="\\"+N;S="
";f=`fortune`.split(N);e=f.collect{|v|v.split(/\s+/)};t="
#{"_"*w}\n/"+S*w+BS;while e.size>0;l="|";d=e.shift;while
d.size>0;while d.size>0&&(l+d.first).length<w;l+=d.shift+S;end;t+=l+S*(w-l.length+1)+"|"+N;l="|";end;end;t+="\\#{'_'*w}/"+N;h=S*3+z+N;b=S*5+"`
#{m}(#{y})____,\n"+S*8+"(` =~~/\n"+"^~"*5+"`---'"+"^~"*30;puts t+h+b
#######################
output:
________________________________________
/ \
|Q: What do you call the money you pay |
|to the government when |
| you ride into the country on the back |
|of an elephant? |
|A: A howdah duty. |
\________________________________________/
\
` >(º)____,
(` =~~/
^~^~^~^~^~`---'^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~
Jacob
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__/'-__~===-
'-~` ~~ ~~
It's my favourite line in the program, too. I was going to point it out in
my post, but I decided to paste instead of link.
Historical note: I originally wrote it the other way around, basing
everything on the Cow, but that's clearly not how it's meant to be.
BTW, another Cowsay reference:
http://www.nog.net/~tony/warez/cowsay.shtml
The above lists the cowsay perl software in its various forms, including the
CPAN module Acme::Cow.
Cheers,
Dave