Granie w grę nazw

9

Napisz program, aby zagrać w grę nazw .

Wejście

Twój program powinien w jakikolwiek sposób zaakceptować jedną nazwę jako dane wejściowe od użytkownika (np. Odczytane ze standardowego wejścia lub jako argument wiersza poleceń). Możesz założyć, że nazwa jest pojedynczym słowem składającym się z dużej litery, po której następuje jedna lub więcej małych liter.

Wynik

Twój program musi wydrukować wierszyk dla podanego imienia, jak wyjaśniono w utworze, wypełniając następujący szablon:

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

Oto (X)oryginalna nazwa, która (Y)jest pisana małymi literami po usunięciu początkowych spółgłosek.

Jest jednak jeden wyjątek. Jeśli oryginalna nazwa zaczyna się od m, flub bpowinna być zapisana bez tej litery w odpowiednim wierszu. Np. Jeśli nazwa była Bob, wiersz „b” powinien kończyć się bo-ob. Zauważ, że w tym przypadku wszelkie inne spółgłoski są przechowywane, więc na Fredto fo-red, nie fo-ed.

Przykłady

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!

Kok:

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!

Punktacja

Najkrótszy kod wygrywa.

hammar
źródło
1
Myślę, że Yjest traktowany jako wokal, Yvespodobnie jak Iveslub Arnold.
użytkownik nieznany
1
Ale co z Yatesem, Yestinem, Yolandą lub Julią?
ephemient
@ephemient: Myślę, że można traktować Yjako samogłoskę tylko wtedy, gdy następuje po niej spółgłoska. To powinno obejmować przynajmniej te przypadki.
hammar
13
Współczuję Tuckerowi.
Peter Olson,

Odpowiedzi:

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

Kod zawiera 5 znaków kontrolnych, które umieściłem w nawiasach. Każdy liczy się jako pojedynczy znak w stosunku do liczby znaków.

EDYCJA: Przeniesienie pierwszego łączenia (J) na później i zmiana wklejania przed (P) na wklejanie po (p) pozwoliło mi zaoszczędzić 1 znak. Poza tym nie uchwycenie o- w wyrażeniu regularnym uratowało mi 2 kolejne znaki.

migimaru
źródło
3

SNOBOL4, 437 430 bajtów

 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

Niegolfowany (do tego dodałem monit; powyższy tylko czeka na wpisanie nazwy):

      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

To pierwszy program SNOBOL, jaki kiedykolwiek napisałem.

SNOBOL jest językiem zorientowanym liniowo, takim jak FORTRAN, COBOL lub BASIC. Każdy wiersz składa się z opcjonalnej etykiety rozpoczynającej się w kolumnie 1, kodu linii, która może obejmować przypisania i dopasowanie do wzorca, oraz opcjonalnej gałęzi. Tak, linie kończą się (opcjonalnie) GOTO. Występują w dwóch formach:

        :(TARGET)

Oddziały do ​​oznakowania TARGET, natomiast

        :S(SUCCESS) F(FAILURE)

Rozgałęzia się, SUCCESSjeśli dopasowanie wzorca się powiodło, lub w FAILUREinny sposób. Możesz także po prostu odnieść sukces i przejść do następnej linii w przypadku niepowodzenia lub odwrotnie.

Linie kontynuacji zaczynają się od a +lub .. Komentarze zaczynają się od *.

Jak to działa?

Czytaj w nazwie, konwertuj na małe litery. Ustaw nazwy B, F i M, zakładając, że zaczyna się od samogłoski. Następnie sprawdź, czy zaczyna się od rozpiętości spółgłosek. Jeśli nie, jesteśmy gotowi do pracy! Jeśli tak, usuń wiodące spółgłosek i ustaw nazwy B, F i M, zakładając, że nie zaczyna się na żadnej z tych liter. Na koniec sprawdź, czy zaczyna się od każdej z tych liter po kolei, w razie potrzeby poprawiając nazwy. Jesteśmy gotowi do gry w nazwę!

Przykładowy przebieg:

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

Uruchomiłem to na emulatorze mainframe Hercules S / 370 z wersją 6.0a Michigan Terminal System, używając SNOBOL4 w wersji 3.10 od 1 kwietnia 1973 roku zbudowanej dla MTS 1 maja 1975 roku, ale prawdopodobnie są łatwiejsze sposoby na uruchomienie SNOBOL4 na nowoczesny system. :)

Edycja: Usunąłem zbędną gałąź sukcesu, która była równoważna z upadkiem (nie zdawałem sobie sprawy, że mogę sam umieścić tylko gałąź awarii), która eliminuje niepotrzebną etykietę gałęzi i zmieniła bezwarunkowe goto w gałąź awarii w poprzedniej linii, dla oszczędności 7 bajtów.

Teraz, gdy TIO ma obsługę SNOBOL4, możesz wypróbować online! Uwaga: pokazuje rozmiar jako 429 zamiast 430, ponieważ kiedy go wkleiłem, ostatni kanał został usunięty. Próbowałem zmienić linię kontynuacji (tę, która zaczyna się od +) na jedną linię, co nie było legalne w wersji na komputer mainframe, ponieważ linia była zbyt długa, i zadziałała i obniżyła ją do 427. Oczywiście CSNOBOL4 dopuszcza dłuższe linie. Zostawię jednak wynik na 430, ponieważ tyle bajtów był skrypt na moim komputerze, a poza tym SNOBOL jest dość niekonkurencyjny.

David Conrad
źródło
Możesz teraz uruchomić SNOBOL4 na Wypróbuj online
Giuseppe,
@Giuseppe Wow, to spoko! Dzięki, że dałeś mi znać.
David Conrad,
CSNOBOL4 ma kilka innych różnic, ponieważ przypisanie wymaga tylko wiodącej przestrzeni, więc wszystkie linie N = TRIM(INPUT)mogą być N =TRIM(INPUT).
Giuseppe,
2

J , 149 znaków

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
efemeryczny
źródło
2

JavaScript, 115 bajtów

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

Wyjaśnienie:

ta funkcja zwraca nazwę bez początkowych spółgłosek

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

Następnie reszta jest funkcją zwracającą ciąg pełny ciąg.

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

Edycja: od 119 do 115 bajtów dzięki @Martin Ender

eniallator
źródło
1
Witamy w PPCG! Wierzę, że możesz skrócić to wyrażenie regularne do /[aeiou]\w*/i.
Martin Ender
1
Możesz zastąpić oryginalną wersję skróconą. Stary zostanie zachowany w historii edycji postu. Jeśli chcesz, możesz dołączyć poprzednie wyniki, takie jak JavaScript, <s>119</s> 115 bytesw nagłówku, aby dać ludziom wskazówkę, że pierwotnie była dłuższa wersja, jeśli są zainteresowani.
Martin Ender
A, fajnie. Znowu wydano :)
eniallator
1

Clojure , 292 znaków po zminimalizowaniu

Oto pierwsza próba, prawie pozytywna, że ​​mogę ją dalej rozwinąć:

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

Uczę się clojure i pomyślałem, że fajnie byłoby spróbować. Oto moje rozumowanie:

- Aby usunąć spółgłoski z początku łańcucha: (drop-while (fn [x] (not (some #(= % x) "aeiou"))) name)

- Aby obsłużyć dodatkowe reguły dla „b”, „f” i „m”, podzieliłem tekst na listę fraz: [", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"]

- Następnie zastosowałem funkcję, która pyta, czy fraza się kończy z tą samą literą, od której zaczyna się nazwa, i użył go do przekształcenia tych 3 fraz w oparciu o reguły układanki

- Ostatnim krokiem jest zbudowanie łańcucha z wynikami

Upgradingdave
źródło
1

Scala 281

Zamieniłem (X) i (Y) we wzorze na #i 012. Sjest tylko nową nazwą Stringi a(b,c,d)jest skrótową definicją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)

Wywołanie testowe:

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

I bez golfa:

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")
nieznany użytkownik
źródło
1

Python 3, 148 145 142 bajtów

Tak, wiem, że jest trochę późno, ale ...

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

Używa nowych ciągów F do sformatowania wynikowego ciągu.

Niestety nie sądzę, że TIO obsługuje ciągi F.

Stara wersja

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

Zaoszczędź 3 bajty dzięki @officialaimm

Cairney Coheringaahing
źródło
zapisz trzy bajty, używając literału „AEIOUaeiou” i unikając dolnej () w 3. linii
officialaimm
1

Sed, 162 bajty

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'

Nie wiedziałem zbyt dobrze, zanim to zrobiłem. Wiem to dużo lepiej. Pierwszy sed w potoku powiela nazwę trzy razy, więc staje się „Bob \ nBob \ nBob \ nBob” zamiast po prostu „Bob”. Następny sed wykonuje ciężkie podnoszenie.

Oczekuje wkładu na standardowe wejście echo Name |sed ...

Nie golfowany:

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

Kilka notatek. Pierwsze cztery dopasowania, 1s, 2s, 3s, 4s, przekształcają wyjście w coś niezupełnie poprawnego. Bob stał się bo-bbobem, Fred stał się fo-fredem, a Mike stał się niemal podobny. Kay stałaby się mo-mkay, dobrze?

Następnie musimy zastąpić albo bo-bbob bo-ob, albo bo-bkay bo-bay. Aby to zrobić, możemy użyć funkcji, w której dokonujemy podstawienia s ///, a następnie rozgałęzić, jeśli się powiedzie, przeskakując nad drugim, który teraz chcemy pominąć. Ale jeśli to przeoczy, chcemy spaść przez gałąź i dokonać następnej zmiany.

Wykonuje to polecenie t [label], rozgałęziając się tylko wtedy, gdy pasowało poprzednie s ///. Ale na początku skryptu zrobiłem już jeden s /// dla każdej linii (wiodącymi liczbami w 1s, 2s itp. Są adresy; oznaczają one, że polecenie jest wykonywane tylko wtedy, gdy adres się zgadza). Bez względu na to, w jakiej linii się znajdujemy, 1, 2, 3 lub 4, co najmniej jeden s /// jest zgodny. (Próbowałem to zrobić na odwrót, masując nazwy, a następnie dodając „Banana-etc.” Później, ale utknąłem w ten sposób, a próba zrobienia tego wszystkiego naraz spowodowałaby powtórzenie.) Na szczęście flaga może zostać wyczyszczone przez przyjęcie gałęzi, więc robimy to za pomocą „tx;: x”. tx rozgałęzia się do etykiety x, a: x jest etykietą x.

Uff! To oczyszcza podniebienie dla dwóch ostatnich zmian. Próbujemy jednego, a jeśli się powiedzie, rozgałęziamy się nad drugim, w przeciwnym razie robimy drugi. Tak czy inaczej, kończymy na etykiecie: z, a bufor wzorców zawiera jedną linię tekstów, które są drukowane na standardowe wyjście.

Dzięki za nakłonienie mnie do spędzenia wystarczająco dużo czasu ze stroną man sed i instrukcją Texinfo, aby w końcu zrozumieć, jak to zrobić więcej niż sed s / foo / bar /

David Conrad
źródło
Och, liczę całą długość skryptu za pomocą polecenia sed |i wszystkich. Może powinienem nazwać to bash / sed lub policzyć inaczej? Nie wiem Jestem zadowolony z tego, co jest, ale daj mi znać, czy powinien być inny w stosunku do standardów 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

Właśnie zdałem sobie sprawę, że mój kod zawodzi ...
- Nie usuwa początkowych stałych.
- Nie zarządza biznesem „bo-ob”.

To najdalej, co mam, może ktoś to dokończy.

Anti Earth
źródło
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
źródło
0

R, 189 znaków

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

Ale z jeszcze jedną postacią możesz wprowadzić wiele nazwisk za jednym razem:

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
źródło
0

Pyth , 111 bajtów SBCS

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

Zestaw testowy

Kod używa znaków niedrukowalnych i jako taki nie wyświetla się poprawnie na Stack Exchange. Podany link zawiera te znaki i jest poprawną wersją programu.

hakr14
źródło
-1

Pyton

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)
użytkownik1027046
źródło