Giocare al gioco del nome


9

Scrivi un programma per giocare al gioco del nome .

Ingresso

Il tuo programma dovrebbe accettare un singolo nome come input dall'utente in qualche modo (es. Letto da input standard o come argomento da riga di comando). Si può presumere che il nome sia una singola parola composta da una lettera maiuscola seguita da una o più lettere minuscole.

Produzione

Il programma deve stampare la rima per il nome dato, come spiegato nella canzone, compilando il seguente modello:

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

Qui, (X)è il nome originale ed (Y)è il nome in minuscolo con eventuali consonanti iniziali rimosse.

C'è un'eccezione, tuttavia. Se il nome originale è iniziato con m, fo b, dovrebbe essere scritto senza questa lettera sulla riga corrispondente. Ad esempio, se il nome fosse Bob, la riga "b" dovrebbe terminare con bo-ob. Si noti che in questo caso, tutte le altre consonanti vengono mantenute, quindi Frednon lo fo-redè fo-ed.

Esempi

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!

punteggio

Il codice più corto vince.


1
Immagino che Ysia gestito come una voce, quindi Yvesè come Iveso Arnold.
utente sconosciuto il

1
Ma che dire di Yates, Yestin, Yolanda o Yulia?
effimero

@ephemient: immagino che potresti trattare Ycome una vocale solo se seguita da una consonante. Questo dovrebbe coprire almeno quei casi.
Martedì

13
Mi dispiace per Tucker.
Peter Olson,

Risposte:


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

Il codice include 5 caratteri di controllo, che ho messo tra parentesi. Ciascuno conta solo come un singolo personaggio per il conteggio dei personaggi.

EDIT: spostando il primo join (J) in un secondo momento e cambiando il paste-before (P) in un paste-after (p) mi ha salvato 1 carattere. Inoltre, non catturare o-in regex mi ha salvato altri 2 personaggi.


3

SNOBOL4, 437 430 byte

 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 (più ho aggiunto un prompt; quello sopra attende solo che venga digitato un nome):

      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

Questo è il primo programma SNOBOL che abbia mai scritto.

SNOBOL è un linguaggio orientato alla linea, come FORTRAN, COBOL o BASIC. Ogni riga è composta da un'etichetta opzionale che inizia nella colonna 1, dal codice per la riga che può comportare assegnazioni e corrispondenza dei motivi e da un ramo opzionale. Sì, le righe terminano con GOTO (facoltativi). Vengono in due forme:

        :(TARGET)

Rami da etichettare TARGET, mentre

        :S(SUCCESS) F(FAILURE)

Si dirige verso SUCCESSse la corrispondenza del modello ha avuto esito positivo o in FAILUREaltro modo. Puoi anche ramificare il successo e passare alla riga successiva in caso di fallimento, o viceversa.

Le righe di continuazione iniziano con un +o .. I commenti iniziano con a *.

Come funziona?

Leggi in un nome, convertilo in minuscolo. Imposta i nomi B, F e M supponendo che inizi con una vocale. Quindi controlla se inizia con un arco di consonanti. Altrimenti, siamo pronti per partire! In tal caso, togli le principali consonanti e imposta i nomi B, F e M supponendo che non inizi con nessuna di quelle lettere. Infine, controlla se inizia con ciascuna di quelle lettere a turno, fissando i nomi secondo necessità. Quindi siamo pronti per giocare al gioco del nome!

Esecuzione di esempio:

 # $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

L'ho eseguito sull'emulatore mainframe Hercules S / 370 che esegue la versione 6.0a del Michigan Terminal System utilizzando SNOBOL4 versione 3.10 dal 1 aprile 1973, costruita per MTS il 1 maggio 1975, ma probabilmente ci sono modi più semplici per eseguire SNOBOL4 su un sistema moderno. :)

Modifica: rimosso un ramo di successo ridondante che equivaleva a un fallthrough (non mi rendevo conto di poter mettere da solo un ramo di errore da solo) che elimina un'etichetta di ramo non necessaria e trasformava un goto incondizionato in un ramo di errore sulla riga precedente, per un risparmio di 7 byte.

Ora che TIO ha il supporto SNOBOL4 puoi provarlo online! Nota: mostra le dimensioni come 429 anziché 430 perché quando l'ho incollato lì, l'alimentazione di linea finale è stata rimossa. Ho provato a cambiare la linea di continuazione (quella che inizia con +) in una singola linea, che non era legale nella versione mainframe perché la linea era troppo lunga e funzionava e la portava a 427. Ovviamente CSNOBOL4 consente linee più lunghe. Lascerò il mio punteggio a 430, però, perché questo è il numero di byte che lo script era sulla mia macchina e, inoltre, SNOBOL è piuttosto non competitivo.


Ora puoi eseguire SNOBOL4 su Provalo online
Giuseppe,

@Giuseppe Wow, è fantastico! Grazie per avermi fatto sapere.
David Conrad,

CSNOBOL4 ha un paio di altre differenze, poiché l'assegnazione richiede solo lo spazio iniziale, quindi tutte le tue linee N = TRIM(INPUT)possono essere N =TRIM(INPUT).
Giuseppe,

2

J , 149 caratteri

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

2

Javascript, 115 byte

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}!`

Spiegazione:

questa funzione restituisce il nome senza le consonanti iniziali

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

Quindi il resto è una funzione che restituisce la stringa stringa completa.

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

Modifica: da 119 a 115 byte grazie a @Martin Ender


1
Benvenuti in PPCG! Credo che tu possa abbreviare quella regex a /[aeiou]\w*/i.
Martin Ender,

1
È possibile sostituire la versione originale con quella abbreviata. Quello vecchio verrà conservato nella cronologia delle modifiche del post. Se lo desideri, puoi includere i punteggi precedenti come JavaScript, <s>119</s> 115 bytesnell'intestazione per dare alla gente un suggerimento che in origine esisteva una versione più lunga, se interessati.
Martin Ender,

Ah, bello. Modificato di nuovo :)
eniallator

1

Clojure , 292 caratteri dopo la minimizzazione

Ecco un primo tentativo, quasi positivo, posso rovinarlo ulteriormente:

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

Sto solo imparando il clojure e ho pensato che sarebbe divertente provarlo. Ecco il mio ragionamento:

- Per eliminare le consonanti dall'inizio della stringa: (drop-while (fn [x] (not (some #(= % x) "aeiou"))) name)

- Per gestire le regole extra per "b", "f" e "m", ho diviso il testo in un elenco di frasi: [", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"]

- Quindi, ho applicato una funzione che chiede se la frase termina con la stessa lettera con cui inizia il nome, e usata per trasformare quelle 3 frasi in base alle regole del puzzle

- Il passo finale è costruire una stringa con i risultati


1

Scala 281

Ho sostituito (X) e (Y) nel modello con #e 012. Sè solo un nuovo nome per Stringed a(b,c,d)è una definizione abbreviata perb.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)

Invocazione di prova:

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

E non golfato:

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

1

Python 3, 148 145 142 byte

Sì, lo so che è un po 'tardi ma ...

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

Utilizza le nuove stringhe f per formattare la stringa risultante.

Sfortunatamente, non penso che TIO supporti ancora le f-string.

Vecchia versione

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}!'

Salvato 3 byte grazie a @officialaimm


salva tre byte usando 'AEIOUaeiou' letterale ed evitando lower () in terza riga
officialaimm

1

Sed, 162 byte

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'

Non conoscevo sed molto bene prima di farlo. Ora lo so molto meglio. Il primo sed nella pipeline duplica il nome tre volte in modo che diventi "Bob \ nBob \ nBob \ nBob" anziché solo "Bob". La prossima sed esegue il sollevamento pesante.

Si aspetta input su stdin like 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///'

Un paio di note. Le prime quattro partite, 1s, 2s, 3s, 4s, trasformano l'output in qualcosa di non del tutto corretto. Bob è diventato bo-bbob, Fred è diventato fo-ffred e Mike è diventato mo-mmike. Kay diventerebbe mo-mkay, mkay?

Quindi, dobbiamo sostituire bo-bbob con bo-ob o bo-bkay con bo-bay. Per fare ciò, possiamo usare una funzione in cui facciamo una sostituzione ///, e poi diramare se ha successo, saltando sulla seconda che ora vogliamo saltare. Ma se ci fosse mancato, vogliamo passare attraverso il ramo e fare la prossima sostituzione.

Il comando t [label] lo fa, ramificandosi solo se un precedente s /// corrisponde. Ma all'inizio dello script ho già fatto uno s /// per ogni riga (i numeri iniziali in 1s, 2s, ecc. Sono indirizzi; significano che il comando viene eseguito solo se l'indirizzo corrisponde). Quindi, indipendentemente dalla linea su cui ci troviamo, 1, 2, 3 o 4, almeno una s /// è stata abbinata. (Ho provato a farlo al contrario, massaggiando i nomi e poi aggiungendo "Banana-etc." Dopo, ma mi sono bloccato in quel modo, e provare a farlo tutto in una volta avrebbe causato qualche ripetizione.) Fortunatamente, la bandiera può essere cancellato prendendo un ramo, quindi lo facciamo con "tx;: x". tx si dirama verso l'etichetta x e: x è l'etichetta x.

Meno male! Questo cancella il palato per le ultime due sostituzioni. Ne proviamo uno e se ci riesce ci ramifichiamo sull'altro, altrimenti facciamo il secondo. In entrambi i casi finiamo sull'etichetta: z e il buffer di pattern contiene una riga di testi che viene stampata su stdout.

Grazie per avermi indotto a passare abbastanza tempo con la pagina man di sed e il manuale di Texinfo per capire finalmente come fare più di sed s / foo / bar /


Oh, sto contando l'intera lunghezza della sceneggiatura con il comando sed e il |e tutto. Forse dovrei chiamare questo bash / sed o contarlo in modo diverso? Non lo so. Sono contento così com'è ma fammi sapere se dovrebbe essere diverso dagli standard di 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

Ho appena realizzato che il mio codice fallisce ...
- Non rimuove i costanti iniziali.
- Non gestisce l'attività "bo-ob".

È il più lontano che ho, forse qualcuno può finirlo.


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!'''
]

0

R, 189 caratteri

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

Ma con solo un altro personaggio, puoi inserire molti nomi in una volta sola:

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

0

Pyth , 111 byte SBCS

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

Suite di test

Il codice utilizza caratteri non stampabili e come tale non viene visualizzato correttamente su Stack Exchange. Il link fornito contiene questi caratteri ed è la versione corretta del programma.


-1

Pitone

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.