Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Write a program to play the name game.

Input

Your program should accept a single name as input from the user in some way (e.g read from standard input or as a command-line argument). You can assume that the name is a single word consisting of an upper case letter followed by one or more lower case letters.

Output

Your program must print the rhyme for the given name, as explained in the song, by filling out the following template:

(X), (X), bo-b(Y)
Banana-fana fo-f(Y)
Fee-fi-mo-m(Y)
(X)!

Here, (X) is the original name, and (Y) is the name in lower case with any initial consonants removed.

There is one exception, however. If the original name began with m, f or b, it should be written without this letter on the corresponding line. E.g. if the name was Bob, the "b" line should end with bo-ob. Note that in this case, any other consonants are kept, so for Fred it's fo-red, not fo-ed.

Examples

Shirley:

Shirley, Shirley, bo-birley
Banana-fana fo-firley
Fee-fi-mo-mirley
Shirley!

Arnold:

Arnold, Arnold, bo-barnold
Banana-fana fo-farnold
Fee-fi-mo-marnold
Arnold!

Bob:

Bob, Bob, bo-ob
Banana-fana fo-fob
Fee-fi-mo-mob
Bob!

Fred:

Fred, Fred, bo-bed
Banana-fana fo-red
Fee-fi-mo-med
Fred!

Scoring

Shortest code wins.

share|improve this question
1  
I guess Y is handled as a vocal, so Yves is like Ives or Arnold. –  user unknown Nov 7 '11 at 2:14
    
But what about Yates, Yestin, Yolanda, or Yulia? –  ephemient Nov 7 '11 at 6:01
    
@ephemient: I guess you could treat Y as a vowel only if it's followed by a consonant. That should cover those cases at least. –  hammar Nov 7 '11 at 12:44
3  
I feel sorry for Tucker. –  Peter Olson Dec 3 '11 at 17:29
add comment

8 Answers

up vote 3 down vote accepted

vi, 118 115

Y2PA,<ESC>Ypj~Y2PIbo-b<c-o>wBanana-fana fo-f<c-o>wFee-fi-mo-m<c-o>2$!<ESC>HJJ:%s/\vo-(([bfm])\2([^aeiou]*))?([bfm]?)[^aeiou]*/o-\3\4
ZZ

The code includes 5 control characters, which I've put in brackets. Each only counts as a single character towards the character count.

EDIT: Moving the first join (J) to later and changing the paste-before (P) to a paste-after (p) saved me 1 character. Also, not capturing the o- in the regex saved me 2 more characters.

share|improve this answer
add comment

Scala 281

I replaced (X) and (Y) in the pattern with # and 012. S is just a new name for String and a(b,c,d) is shorthand definition for b.replaceAll(c,d)

val v="""#, #, bo-b0
Banana-fana fo-f1
Fee-fi-mo-m2
#!"""
type S=String
def a(b:S,c:S,d:S)=b.replaceAll(c,d)
def r(t:S,n:S,i:Int)=if(n(0)=="bfm"(i).toUpper)a(t,"."+i,n.tail)else
a(t,""+i,a(n,"^[^AEIOUaeiou]*([aeiou].*)","$1")).toLowerCase
def x(n:S)=a(r(r(r(v,n,0),n,1),n,2),"#",n)

Test invocation:

val l = List ("Shirley", "Arnold", "Bob", "Fred") 
for (n <- l) println (x (n) + "\n")

And ungolfed:

val templ = """#, #, bo-b0
Banana-fana fo-f1
Fee-fi-mo-m2
#!"""

val names = List ("Shirley", "Arnold", "Bob", "Fred") 
val keys = "bfm"

def recode (template: String, n: String, i: Int) = 
 if (n(0) == keys(i).toUpper)
   template.replaceFirst ("." + i, n.tail) else 
 template.replaceAll ("" + i, (n.replaceAll ("^[^AEIOUYaeiouy]*([aeiou].*)", "$1").toLowerCase))

for (name <- names)
  println (recode (recode (recode (templ, name, 0), name, 1), name, 2).replaceAll ("#", name) + "\n")
share|improve this answer
add comment

J, 149 characters

1!:2&2>|.(n,'!');('Fee-fi-mo-';'Banana-fana fo-';n,', ',n,', bo-'),&.>;/'mfb'(,`(}.@])`($:}.)@.((=+.2*5='aeiou'i.]){.)"0 _)a.{~32(23 b.)a.i.n=.1!:1]3
share|improve this answer
add comment

Clojure, 292 characters after minimizing

Here's a first attempt, almost positive I can widdle it down further:

(defn name-game
  [n]
  (let [[b f m] (map (fn [x] (if (some #(= % (first n) (last x)) "bfm")
                              (str (apply str (butlast x)) (apply str (rest n)))
                              (str x (apply str (drop-while (fn [x] (not (some #(= % x) "aeiou"))) n))))) [", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"])]
    (str n ", " n b f m "\n" n "!")))

I'm just learning clojure and thought it'd be fun to give this a shot. Here's my reasoning:

- To strip off consonants from beginning of string: (drop-while (fn [x] (not (some #(= % x) "aeiou"))) name)

- To handle the extra rules for "b", "f" and "m", I broke text into list of phrases: [", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"]

- Then, I applied a function that asks whether the phrase ends with the same letter that the name starts with, and used that to transform those 3 phrases based on the rules of the puzzle

- Final step is to build a string with results

share|improve this answer
add comment

Python, 161

x=raw_input('')
a,b,c=x[0],x[1:],'bfm'
if b[0] in c:b=b[1:]
d="X, X, bo-@\nBanana-fana fo-@\nFee-fi-mo-@\nX!".replace('X',a)
for y in c:d=d.replace('@',y+b,1)
print d

Just realised my code fails...
- Doesn't remove initial constonants.
- Doesn't manage the 'bo-ob' business.

It's the furthest I got, maybe somebody can finish it.

share|improve this answer
add comment

Groovy, 146

r={n->m={n[0]==it[0]?n[1..-1]:it[1]+(n.toLowerCase()=~'[aeiou].*')[0]};"$n, $n, bo-${m 'Bb'}\nBanana-fana fo-${m 'Ff'}\nFee-fi-mo-${m 'Mm'}\n$n!"}

assert ['Shirley', 'Arnold', 'Bob', 'Fred'].collect { r(it) } == [
'''Shirley, Shirley, bo-birley
Banana-fana fo-firley
Fee-fi-mo-mirley
Shirley!''',
'''Arnold, Arnold, bo-barnold
Banana-fana fo-farnold
Fee-fi-mo-marnold
Arnold!''',
'''Bob, Bob, bo-ob
Banana-fana fo-fob
Fee-fi-mo-mob
Bob!''',
'''Fred, Fred, bo-bed
Banana-fana fo-red
Fee-fi-mo-med
Fred!'''
]
share|improve this answer
add comment

R, 189 chars

x=scan(,'');f=function(b)if(grepl(b,x))sub('.','',x)else tolower(sub('^[^aoueiy]*',b,x,i=T));cat(sprintf('%s, %1$s, bo-%s\nBanana-fana fo-%s\nFee-fi-mo-%s\n%1$s!\n',x,f('B'),f('F'),f('M')))

But with just one more character, you can entry many names in one go:

x=scan(,'');f=function(b)ifelse(grepl(b,x),sub('.','',x),tolower(sub('^[^aoueiy]*',b,x,i=T)));cat(sprintf('%s, %1$s, bo-%s\nBanana-fana fo-%s\nFee-fi-mo-%s\n%1$s!\n',x,f('B'),f('F'),f('M')))
share|improve this answer
add comment

Python

n=raw_input('')
if n[0].lower() in ("m", "f", "b"): r=n[1:]
else:
    i = iter(n.lower())
    for a in range(len(n)):
        if i.next() in ("a","e","i","o","u"):
            r = n[a:]
            break
print "%s, %s, bo-b%s\nBanana-fana fo-f%s\nFee-fi-mo-m%s\n%s!" %(name,name,rhyme,rhyme,rhyme,name)
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.