Игра в Имя

9

Напишите программу для игры в название игры .

вход

Ваша программа должна каким-то образом принимать одно имя в качестве ввода от пользователя (например, чтение из стандартного ввода или в качестве аргумента командной строки). Можно предположить, что имя представляет собой одно слово, состоящее из заглавной буквы, за которой следуют одна или несколько строчных букв.

Вывод

Ваша программа должна напечатать рифму для данного имени, как объяснено в песне, заполнив следующий шаблон:

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

Здесь (X)- оригинальное имя, и (Y)это имя в нижнем регистре с удаленными начальными согласными.

Однако есть одно исключение. Если оригинальное имя начиналось с m, fили b, оно должно быть написано без этой буквы в соответствующей строке. Например, если имя было Bob, строка "b" должна заканчиваться bo-ob. Обратите внимание, что в этом случае любые другие согласные сохраняются, так что для Fredэтого fo-redнет fo-ed.

Примеры

Ширли:

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!

счет

Самый короткий код выигрывает.

Хаммар
источник
1
Я думаю, Yчто обрабатывается как вокал, так Yvesже, как Ivesили Arnold.
пользователь неизвестен
1
А как же Йетс, Йестин, Иоланда или Юлия?
Эфимент
@ephemient: Я думаю, что вы можете рассматривать Yкак гласный, только если за ним следует согласный. Это должно охватывать как минимум эти случаи.
Хаммар
13
Мне жаль Такера.
Питер Олсон

Ответы:

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

Код включает в себя 5 управляющих символов, которые я поместил в скобки. Каждый учитывается только как один символ на счет персонажа.

РЕДАКТИРОВАТЬ: Перемещение первого соединения (J) на более позднее и изменение вставки перед (P) на вставку после (p) спасло мне 1 символ. Кроме того, отсутствие захвата в регулярном выражении спасло мне еще 2 символа.

migimaru
источник
3

SNOBOL4, 437 430 байт

 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 (плюс я добавил приглашение; вышеприведенное просто ожидает ввода имени):

      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

Это первая программа SNOBOL, которую я написал.

SNOBOL - это линейно-ориентированный язык, такой как FORTRAN, COBOL или BASIC. Каждая строка состоит из необязательной метки, начинающейся в столбце 1, кода для строки, которая может включать в себя назначения и сопоставление с образцом, и необязательной ветви. Да, строки заканчиваются (необязательно) GOTO. Они бывают двух видов:

        :(TARGET)

Ветви для маркировки TARGET, а

        :S(SUCCESS) F(FAILURE)

Ветвится, SUCCESSесли совпадение с шаблоном прошло успешно, или FAILUREиначе. Вы также можете просто перейти в случае успеха и перейти к следующей строке в случае неудачи, или наоборот.

Строки продолжения начинаются с +или .. Комментарии начинаются с *.

Как это работает?

Прочитайте имя, преобразуйте его в нижний регистр. Установите B-, F- и M-имена, предполагая, что они начинаются с гласной буквы. Тогда проверьте, начинается ли это с диапазона согласных. Если нет, мы готовы идти! Если так, удалите ведущие согласные и установите B-, F- и M-имена, предполагая, что они не начинаются ни с одной из этих букв. Наконец, проверьте, начинается ли он с каждой из этих букв по очереди, исправляя имена по мере необходимости. Тогда мы готовы играть в игру «Имя»!

Образец прогона:

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

Я запустил это на эмуляторе мейнфрейма Hercules S / 370, работающем под управлением версии 6.0a Мичиганской терминальной системы с использованием SNOBOL4 версии 3.10 от 1 апреля 1973 года, созданной для MTS 1 мая 1975 года, но, вероятно, есть более простые способы запуска SNOBOL4 на современная система. :)

Редактировать: удалил избыточную ветвь успеха, которая была эквивалентна падению (я не понимал, что могу поставить только ветку отказа), которая удаляла ненужную метку ветви, и превратила безусловный переход в ветку ошибки на предыдущей строке, для экономии 7 байтов.

Теперь, когда у TIO есть поддержка SNOBOL4, вы можете попробовать это онлайн! Примечание: он показывает размер как 429, а не 430, потому что когда я вставил его туда, окончательный перевод строки был удален. Я попытался изменить строку продолжения (начинающуюся с +) на одну строку, что было недопустимо в версии для мэйнфреймов, потому что строка была слишком длинной, и это сработало и уменьшило ее до 427. Очевидно, что CSNOBOL4 допускает более длинные строки. Я собираюсь оставить свой счет на 430, потому что это - то, сколько байтов был сценарий на моей машине, и кроме того, SNOBOL довольно неконкурентоспособен.

Дэвид Конрад
источник
Теперь вы можете запустить SNOBOL4 в режиме онлайн
Джузеппе
@ Джузеппе Вау, это круто! Спасибо, что дали мне знать.
Дэвид Конрад
CSNOBOL4 имеет несколько других отличий, так как для назначения требуется только начальный пробел, поэтому все ваши строки N = TRIM(INPUT)могут быть такими N =TRIM(INPUT).
Джузеппе
2

J , 149 знаков

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
ephemient
источник
2

Javascript, 115 байт

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

Объяснение:

эта функция возвращает имя без начальных согласных

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

Тогда остальное - функция, возвращающая строку завершенную строку.

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

Редактировать: от 119 до 115 байт благодаря @Martin Ender

eniallator
источник
1
Добро пожаловать в PPCG! Я считаю, что вы можете сократить это регулярное выражение до /[aeiou]\w*/i.
Мартин Эндер,
1
Вы можете заменить оригинальную версию на сокращенную. Старый будет сохранен в истории редактирования поста. Если вы хотите, вы можете включить предыдущие оценки, как JavaScript, <s>119</s> 115 bytesв заголовке, чтобы дать людям подсказку, что изначально была более длинная версия, если они заинтересованы.
Мартин Эндер
Ах, круто. Отредактировано снова :)
eniallator
1

Clojure , 292 символа после минимизации

Вот первая попытка, почти положительная, я могу продолжать дальше:

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

Я только изучаю clojure и подумал, что было бы весело дать этому шанс. Вот мои рассуждения:

- Чтобы отделить согласные от начала строки: (drop-while (fn [x] (not (some #(= % x) "aeiou"))) name)

- Чтобы обработать дополнительные правила для "b", "f" и "m", я разбил текст на список фраз: [", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"]

- Затем я применил функцию, которая спрашивает, заканчивается ли фраза с той же буквой, с которой начинается название, и использовал ее для преобразования этих 3 фраз на основе правил головоломки

- последний шаг - построить строку с результатами

Upgradingdave
источник
1

Scala 281

Я заменил (X) и (Y) в шаблоне на #и 012. Sэто просто новое имя Stringи a(b,c,d)сокращенное определение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)

Тестовый вызов:

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

И безглым

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 байта

Да, я знаю, что уже немного поздно, но ...

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

Он использует новые f-строки для форматирования результирующей строки.

Я не думаю, что TIO пока поддерживает f-строки, к сожалению.

Старая версия

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

Сохранено 3 байта благодаря @officialaimm

Caird Coneheringaahing
источник
сохраните три байта, используя литерал 'AEIOUaeiou' и избегая lower () в 3-й строке
officialaimm
1

Sed, 162 байта

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'

Я не очень хорошо знал sed, прежде чем сделал это. Теперь я знаю это намного лучше. Первый sed в конвейере дублирует имя три раза, поэтому вместо «Bob» оно становится «Bob \ nBob \ nBob \ nBob». Следующий сед делает тяжелую работу.

Ожидает ввода на STDIN, как 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///'

Пару заметок. Первые четыре совпадения, 1 с, 2 с, 3 с, 4 с, превращают вывод в нечто не совсем правильное. Боб стал bo-bbob, Фред стал fo-ffred, а Майк стал mo-mmike. Кей станет Мо-Мкаем, Мкаем?

Затем нам нужно заменить либо bo-bbob на bo-ob, либо bo-bkay на bo-bay. Чтобы сделать это, мы можем использовать функцию, где мы делаем одну подстановку ///, а затем выполняем ветвь, если она удалась, перепрыгивая через другую, которую мы теперь хотим пропустить. Но если он пропустил, мы хотим провалиться через ветку и сделать следующую замену.

Команда t [label] делает это, разветвляясь, только если предыдущий s /// соответствует. Но в начале скрипта я уже сделал по одному s /// для каждой строки (первые числа в 1, 2 и т. Д. Являются адресами; они означают, что команда выполняется только при совпадении адреса). Поэтому независимо от того, на какой линии мы находимся, 1, 2, 3 или 4, по крайней мере, один s /// соответствует. (Я попытался сделать это наоборот, массируя имена, а затем добавив «Банан и т. Д.» После, но застрял таким образом, и попытка сделать все это сразу вызовет некоторое повторение.) К счастью, флаг может очистить, взяв ветку, поэтому мы делаем это с помощью "tx;: x". TX ветвится до метки x, а: x это метка x.

Уф! Это очищает вкус для последних двух замен. Мы пробуем один, и если это удается, мы разветвляемся на другой, в противном случае мы делаем второй. В любом случае мы получим метку: z, а буфер шаблонов содержит одну строку текста песни, которая выводится на стандартный вывод.

Спасибо, что обманули меня и потратили достаточно времени на man-страницу sed и руководство Texinfo, чтобы, наконец, понять, как сделать больше, чем sed s / foo / bar /

Дэвид Конрад
источник
О, я считаю всю длину сценария с помощью команды sed и |всех остальных. Может быть, я должен назвать это bash / sed или считать по-другому? Я не знаю. Я доволен этим как есть, но дайте мне знать, если он будет другим по стандартам PPCG.
Дэвид Конрад
0

Питон, 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

Просто понял, что мой код не работает ...
- Не удаляет начальные константы.
- Не управляет бизнесом «Бо-Обь».

Это самое дальнее, что у меня есть, может быть, кто-нибудь может закончить

Анти-Земля
источник
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
источник
0

R 189 символов

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

Но с помощью еще одного символа вы можете ввести сразу несколько имен:

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 байтов SBCS

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

Тестирование

В коде используются непечатаемые символы, и поэтому он не отображается должным образом в Stack Exchange. Приведенная ссылка содержит эти символы и является правильной версией программы.

hakr14
источник
-1

питон

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
источник