Jogando o jogo do nome

9

Escreva um programa para jogar o nome do jogo .

Entrada

Seu programa deve aceitar um único nome como entrada do usuário de alguma forma (por exemplo, ler da entrada padrão ou como um argumento da linha de comando). Você pode assumir que o nome é uma única palavra que consiste em uma letra maiúscula seguida por uma ou mais letras minúsculas.

Resultado

Seu programa deve imprimir a rima para o nome fornecido, conforme explicado na música, preenchendo o seguinte modelo:

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

Aqui, (X)é o nome original e (Y)é o nome em letras minúsculas, com as consoantes iniciais removidas.

Há uma exceção, no entanto. Se o nome original começar com m, fou b, ele deve ser escrito sem essa letra na linha correspondente. Por exemplo, se o nome era Bob, a linha "b" deve terminar com bo-ob. Note-se que, neste caso, quaisquer outras consoantes são mantidos, então para Fredque é fo-red, não fo-ed.

Exemplos

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!

Prumo:

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!

Pontuação

O menor código vence.

hammar
fonte
11
Eu acho que Yé tratado como vocal, assim Yvescomo é Ivesou Arnold.
usuário desconhecido
11
Mas e Yates, Yestin, Yolanda ou Yulia?
ephemient 7/11/11
@hemhemient: Eu acho que você só pode tratar Yuma vogal se for seguida por uma consoante. Isso deve cobrir esses casos pelo menos.
Hammar
13
Sinto muito por Tucker.
Peter Olson

Respostas:

3

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

O código inclui 5 caracteres de controle, que coloquei entre colchetes. Cada um conta apenas como um único caractere na contagem de caracteres.

EDIT: Mover a primeira junção (J) para mais tarde e alterar a pasta antes (P) para uma pasta após (p) me salvou 1 caractere. Além disso, não capturar o o no regex me salvou mais 2 caracteres.

migimaru
fonte
3

SNOBOL4, 437 430 bytes

 N = TRIM(INPUT)
 D = REPLACE(N,'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+'abcdefghijklmnopqrstuvwxyz')
 B = "b" D
 F = "f" D
 M = "m" D
 &ANCHOR = 1
 D SPAN('bcdfghjklmnpqrstvwxyz') . I REM . R :F(Y)
 B = "b" R
 F = "f" R
 M = "m" R
 I "b" :S(U)
 I "f" :S(V)
 I "m" :S(W) F(Y)
U D "b" REM . B :(Y)
V D "f" REM . F :(Y)
W D "m" REM . M
Y OUTPUT = N ", " N ", bo-" B
 OUTPUT = "Banana-fana fo-" F
 OUTPUT = "Fee-fi-mo-" M
 OUTPUT = N "!"
END

Ungolfed (mais eu adicionei um prompt; o acima apenas espera que um nome seja digitado):

      OUTPUT = "Please enter your name."
      Name = TRIM(INPUT)
      UC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
      LC = 'abcdefghijklmnopqrstuvwxyz'
      Low = REPLACE(Name, UC, LC)
      BName = "b" Low
      FName = "f" Low
      MName = "m" Low
      Consonants = SPAN('bcdfghjklmnpqrstvwxyz')
      &ANCHOR = 1
      Low Consonants . First REM . Rest  :F(READY)
      BName = "b" Rest
      FName = "f" Rest
      MName = "m" Rest
      First "b"                   :S(BINIT)
      First "f"                   :S(FINIT)
      First "m"                   :S(MINIT) F(READY)
BINIT Low "b" REM . BName         :(READY)
FINIT Low "f" REM . FName         :(READY)
MINIT Low "m" REM . MName
READY OUTPUT = Name ", " Name ", bo-" BName
      OUTPUT = "Banana-fana fo-" FName
      OUTPUT = "Fee-fi-mo-" MName
      OUTPUT = Name "!"
END

Este é o primeiro programa SNOBOL que eu já escrevi.

SNOBOL é uma linguagem orientada a linhas, como FORTRAN, COBOL ou BASIC. Cada linha consiste em um rótulo opcional começando na coluna 1, o código da linha que pode envolver atribuições e correspondência de padrões e uma ramificação opcional. Sim, as linhas terminam com GOTOs (opcionais). Eles vêm em duas formas:

        :(TARGET)

Ramos para rotular TARGET, enquanto

        :S(SUCCESS) F(FAILURE)

Ramifica para SUCCESSse a correspondência de padrões for bem-sucedida ou FAILUREnão. Você também pode simplesmente se ramificar no sucesso e passar para a próxima linha em caso de falha, ou vice-versa.

As linhas de continuação começam com um +ou .. Os comentários começam com a *.

Como funciona?

Leia um nome, converta-o para minúsculas. Configure os nomes B, F e M, assumindo que ele comece com uma vogal. Em seguida, verifique se começa com um período de consoantes. Caso contrário, estamos prontos para ir! Nesse caso, retire as consoantes principais e configure os nomes B, F e M, assumindo que não comece com nenhuma dessas letras. Por fim, verifique se começa com cada uma dessas letras, fixando os nomes conforme necessário. Então estamos prontos para jogar o nome do jogo!

Exemplo de execução:

 # $RUN *SNOBOL4 5=GOLF.SNO+*SOURCE* 6=*DUMMY*(1,28)+*SINK*(1,4)+*DUMMY*
 # Execution begins   16:57:25
   Snowman
   Snowman, Snowman, bo-bowman
   Banana-fana fo-fowman
   Fee-fi-mo-mowman
   Snowman!
 # Execution terminated   16:57:30  T=0.013

Eu executei isso no emulador de mainframe Hercules S / 370 executando a versão 6.0a do Michigan Terminal System usando o SNOBOL4 versão 3.10 de 1 de abril de 1973 criado para o MTS em 1 de maio de 1975, mas provavelmente existem maneiras mais fáceis de executar o SNOBOL4 em um sistema moderno. :)

Edit: Removido um ramo de sucesso redundante que era equivalente a um avanço (eu não sabia que poderia colocar apenas um ramo de falha sozinho) que elimina um rótulo de ramo desnecessário e transformou um ir incondicional em um ramo de falha na linha anterior, para uma economia de 7 bytes.

Agora que o TIO tem suporte ao SNOBOL4, você pode experimentá-lo online! Nota: Mostra o tamanho 429 em vez de 430, porque quando o colei lá, o avanço de linha final foi removido. Tentei alterar a linha de continuação (a que começa com +) para uma única linha, o que não era legal na versão mainframe porque a linha era muito longa e funcionou e a reduziu para 427. Obviamente, o CSNOBOL4 permite linhas mais longas. No entanto, vou deixar minha pontuação em 430, porque é quantos bytes o script tinha na minha máquina e, além disso, o SNOBOL é bastante não competitivo.

David Conrad
fonte
Agora você pode executar o SNOBOL4 no Try it online
Giuseppe
@ Giuseppe Uau, isso é legal! Obrigado por me avisar.
David Conrad
O CSNOBOL4 tem algumas outras diferenças, pois a atribuição requer apenas o espaço inicial, portanto todas as suas linhas N = TRIM(INPUT)podem ser assim N =TRIM(INPUT).
26718 Giuseppe
2

J , 149 caracteres

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
efémero
fonte
2

Javascript, 115 bytes

r=x=>x.match(/[aeiou]\w*/i)[0];f=x=>`${x}, ${x}, bo-b${r(x)}\nBanana-fana fo-f${r(x)}\nFee-fi-mo-m${r(x)}\n${x}!`

Explicação:

esta função retorna o nome sem as consoantes iniciais

r=x=>x.match(/[aeiouAEIOU]\w*/)[0]

Em seguida, o resto é uma função retornando a sequência completa.

f=x=>`${x}, ${x}, bo-b${r(x)}\nBanana-fana fo-f${r(x)}\nFee-fi-mo-m${r(x)}\n${x}!`

Editar: de 119 a 115 bytes graças a @Martin Ender

eniallator
fonte
11
Bem-vindo ao PPCG! Eu acredito que você pode encurtar esse regex para /[aeiou]\w*/i.
Martin Ender
11
Você pode substituir a versão original pela abreviada. O antigo será preservado no histórico de edições da postagem. Se você quiser, pode incluir pontuações anteriores, como JavaScript, <s>119</s> 115 bytesno cabeçalho, para dar às pessoas uma dica de que havia originalmente uma versão mais longa, se estiverem interessadas.
Martin Ender
Ah legal. Editado novamente :)
eniallator
1

Clojure , 292 caracteres após minimizar

Aqui está uma primeira tentativa, quase positiva de que eu possa entender melhor:

(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 "!")))

Estou apenas aprendendo clojure e pensei que seria divertido tentar. Aqui está o meu raciocínio:

- Para retirar as consoantes do início da string: (drop-while (fn [x] (not (some #(= % x) "aeiou"))) name)

- Para lidar com as regras extras para "b", "f" e "m", quebrei o texto na lista de frases: [", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"]

- Apliquei uma função que pergunta se a frase termina com a mesma letra em que o nome começa e usado para transformar essas três frases com base nas regras do quebra

- cabeça - O passo final é criar uma string com resultados

Atualização
fonte
1

Scala 281

Substituí (X) e (Y) no padrão por #e 012. Sé apenas um novo nome para Stringe a(b,c,d)é uma definição abreviada deb.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)

Chamada de teste:

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

E não destruído:

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")
Usuário desconhecido
fonte
1

Python 3, 148 145 142 bytes

Sim, eu sei que é um pouco tarde, mas ...

n=input();i=0
r=n[i:].lower()
while n[i]not in'aeiouAEIOU':i+=1;r=n[i:]
print(f'{n}, {n}, bo-b{r}\nBanana-fana fo-f{r}\nFee-fi-mo-m{r}\n{n}!')

Ele usa as novas strings f para formatar a string resultante.

Acho que o TIO ainda não suporta f-strings, infelizmente.

Versão antiga

def f(n,i=0):
 r=n[i:].lower()
 while n[i].lower()not in'aeiou':i+=1;r=n[i:]
 return f'{n}, {n}, bo-b{r}\nBanana-fana fo-f{r}\nFee-fi-mo-m{r}\n{n}!'

Guardado 3 bytes graças a @officialaimm

caird coinheringaahing
fonte
salvar três bytes usando 'AEIOUaeiou' literal e evitando inferior () 3 em linha
officialaimm
1

Sed, 162 bytes

sed 'h;G;G;G' |sed '1s/.*/&, &, bo-b\L&/i;2s/^.*/Banana-fana fo-f\L&/;3s/^.*/Fee-fi-mo-m\L&/;4s/$/!/;tx;:x;s/o-\([bfm]\)\1/o-/i;tz;s/\(o-[bfm]\)[^aeiou]\+/\1/;:z'

Eu não sabia muito bem antes de fazer isso. Eu sei muito melhor agora. O primeiro sed no pipeline duplica o nome três vezes, tornando-se "Bob \ nBob \ nBob \ nBob" em vez de apenas "Bob". O próximo sed faz o trabalho pesado.

Espera entrada no stdin como echo Name |sed ...

Ungolfed:

sed 'h                           ;# copy to hold buffer
G                                ;# append newline + hold buffer to pattern
G                                ;# ditto for next two G's
G' |sed '1s/.*/&, &, bo-b\L&/i   ;# 1st line -> X, X bo-bx (lowercase)
2s/^.*/Banana-fana fo-f\L&/      ;# 2nd line -> Banana-fana fo-fx
3s/^.*/Fee-fi-mo-m\L&/           ;# 3rd line -> Fee-fi-mo-mx
4s/$/!/                          ;# bang the 4th line!
tx                               ;# jump to :x if any s/// has matched
:x                               ;# spoiler alert: it has! reset t-flag
s/o-\([bfm]\)\1/o-/i             ;# match some o-cc where c = [bfm]
tz                               ;# if that matched, branch to :z
s/\(o-[bfm]\)[^aeiou]\+/\1/      ;# replace o-[bfm] plus consonants with o-[bfm]
:z                               ;# target of tz, skips over previous s///'

Algumas notas. As quatro primeiras correspondências, 1s, 2s, 3s, 4s, transformam a saída em algo não muito correto. Bob tornou-se bo-bbob, Fred tornou-se um fracassado, e Mike tornou-se mo-mmike. Kay se tornaria mo-mkay, mkay?

Então, precisamos substituir bo-bbob por bo-ob ou bo-bkay por bo-bay. Para fazer isso, podemos usar um recurso em que fazemos uma substituição s /// e, em seguida, ramificá-lo se for bem-sucedido, saltando sobre o segundo que agora queremos pular. Mas, se falhar, queremos passar pelo ramo e fazer a próxima substituição.

O comando t [label] faz isso, ramificando apenas se um s /// anterior corresponder. Mas, no início do script, eu já fiz um s /// para cada linha (os números iniciais em 1s, 2s etc. são endereços; eles significam que o comando só é executado se o endereço corresponder). Portanto, não importa em que linha estamos, 1, 2, 3 ou 4, pelo menos um s /// correspondeu. (Tentei fazer o contrário, massageando os nomes e adicionando o "Banana-etc." Depois, mas fiquei preso dessa maneira e tentar fazer tudo de uma vez causaria alguma repetição.) Felizmente, a bandeira pode ser limpo tomando um ramo, então fazemos isso com "tx;: x". tx ramifica para o rótulo x, e: x é o rótulo x.

Ufa! Isso limpa o paladar para as duas substituições finais. Tentamos um e, se conseguirmos, ramificamos sobre o outro, caso contrário, fazemos o segundo. De qualquer forma, acabamos no rótulo: z e o buffer do padrão contém uma linha de letra que é impressa em stdout.

Obrigado por me convencer a passar tempo suficiente com a página de manual do sed e o manual do Texinfo para finalmente entender como fazer mais do que sed s / foo / bar /

David Conrad
fonte
Oh, eu estou contando todo o comprimento do script com o comando sed e oe |tudo. Talvez eu deva chamar isso de bash / sed ou conte de forma diferente? Eu não sei. Estou feliz com isso como está, mas deixe-me saber se deve ser diferente pelos padrões do PPCG.
David Conrad
0

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

Acabei de perceber que meu código falha ...
- Não remove as constantes iniciais.
- Não gerencia o negócio de 'bo-ob'.

É o máximo que eu tenho, talvez alguém possa terminar.

Anti Terra
fonte
0

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!'''
]
Armand
fonte
0

R, 189 caracteres

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')))

Mas com apenas mais um caractere, você pode inserir muitos nomes de uma só vez:

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')))
Tommy
fonte
0

Pitão , 111 bytes SBCS

V"BFM"IqhzN=aYtrz0.?=aY+rN0:rz0"^[^aeiou]+"k))+%." s­ÞXY:lÍ"*]z2@Y0+." o1}1ÃЬÛJî½"@Y1+."-o Âkq°ë¹è"@Y2+z\!

Suíte de teste

O código usa caracteres não imprimíveis e, como tal, não é exibido corretamente no Stack Exchange. O link fornecido contém esses caracteres e é a versão correta do programa.

hakr14
fonte
-1

Pitão

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)
user1027046
fonte