玩名字游戏


9

编写一个程序来玩名字游戏

输入项

您的程序应以某种方式接受单个名称作为用户输入的名称(例如,从标准输入中读取或作为命令行参数)。您可以假定名称是一个单词,由一个大写字母和一个或多个小写字母组成。

输出量

您的程序必须通过填写以下模板,按照歌曲中的说明打印给定名称的押韵:

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

在这里,(X)是原始名称,并且(Y)是小写的名称,其中删除了所有初始辅音。

但是,有一个例外。如果原始名称以或开头m,则应在相应的行上写上不带该字母的字母。例如,如果名称为,则“ b”行应以结尾。请注意,在这种情况下,任何其他辅音被保留,所以对于它的,不是。fbBobbo-obFredfo-redfo-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就像IvesArnold
用户未知,

1
但是Yates,Yestin,Yolanda或Yulia呢?
短暂

@ephemient:我猜Y只有在后跟辅音的情况下,您才可以将其视为元音。那至少应该涵盖这些情况。
hammar 2011年

13
我为塔克感到抱歉。
彼得·奥尔森

Answers:


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个字符。另外,没有在正则表达式中捕获o-,还为我节省了2个字符。


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

取消高尔夫(加上我添加了一个提示;上面的提示仅等待输入名称):

      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

我在运行1973年4月1日起为STS 的密歇根州终端系统运行6.0a版本的Hercules S / 370大型机模拟器上运行了此版本,此版本自1973年4月1日起为1975年5月1日为MTS构建,但是可能有更简单的方法在STS上运行SNOBOL4现代系统。:)

编辑:删除了一个等效于失败的冗余成功分支(我不知道自己可以单独放置一个失败分支),从而消除了不需要的分支标签,并将无条件的goto变成了上一行的失败分支,节省7个字节。

现在TIO已支持SNOBOL4,您可以 在线尝试!注意:它将大小显示为429而不是430,因为当我将其粘贴到此处时,最终的换行被删除了。我尝试将延续行(以开头的行+)更改为单行,这在大型机版本上不合法,因为该行太长了,它可以正常工作并将其降低到427。显然,CSNOBOL4允许更长的行。但是,我将分数保持在430,因为这是脚本在我的计算机上的多少字节,此外,SNOBOL几乎没有竞争力。


现在,您可以在在线尝试
Giuseppe,

@Giuseppe哇,太酷了!谢谢你让我知道。
戴维·康拉德

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

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


1
欢迎来到PPCG!我相信您可以将该正则表达式缩短为/[aeiou]\w*/i
Martin Ender

1
您可以用缩短的版本替换原始版本。旧的将保留在帖子的编辑历史记录中。如果愿意,您可以JavaScript, <s>119</s> 115 bytes在标题中添加以前的得分,例如,以使人们暗示如果他们感兴趣的话,最初的版本会更长。
Martin Ender'4

啊,酷。再次编辑:)
eniallator '04

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个短语

-最后一步是构建一个带有结果的字符串


1

斯卡拉281

我取代(X)和(Y)与图案#012S只是的新名称Stringa(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}!'

@officialaimm节省了3个字节


通过使用'AEIOUaeiou'文字并避免在第三行中使用lower()来节省三个字节
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与名称重复了3次,因此它变为“ Bob \ nBob \ nBob \ nBob”,而不仅仅是“ Bob”。下一个sed执行繁重的工作。

期望在stdin上输入 echo Name |sed ...

取消高尔夫:

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

几个注意事项。前四个匹配项1s,2s,3s,4s将输出转换为不太正确的内容。鲍勃(Bob)成了bo-bbob,弗雷德(Fred)变得迷恋,迈克(mike)成了陌生人。凯会变成mo-mkay,mkay?

然后,我们需要用bo-ob替换bo-bbob,或用bo-bay替换bo-bkay。为此,我们可以使用一种功能,在该功能中执行一个s ///替换,如果成功,则进行分支,跳过我们现在要跳过的第二个。但是,如果错过了,我们希望进入分支并进行下一个替换。

t [label]命令执行此操作,仅在先前的s ///匹配时分支。但是在脚本开始时,我已经为每行做了一个s ///(1s,2s等的前导数字是地址;它们表示仅在地址匹配时才执行命令)。因此,无论我们在1,2,3或4的哪一行上,至少有一个s ///都已匹配。(我尝试用另一种方法来做,将名称按摩然后在后面加上“香蕉等”,但是那样卡住了,尝试一次全部做会引起重复。)幸运的是,该标志可以可以通过分支来清除,所以我们用“ tx;:x”来完成。tx分支到x标签,而:x是x标签。

ew!这为最后的两次替代清除了味蕾。我们尝试其中一个,如果成功,则分支到另一个,否则,我们执行第二个。无论哪种方式,我们都以:z标签结尾,并且模式缓冲区包含一行歌词,该歌词被打印到stdout。

感谢您诱使我花足够的时间使用sed手册页和Texinfo手册,以最终了解除sed s / foo / bar /之外的其他方法。


哦,我正在用sed命令以及the |和all来计算脚本的整个长度。也许我应该称它为bash / sed,还是用不同的方式来计数?我不知道。我对它保持原样感到满意,但是请让我知道它是否应该与PPCG的标准有所不同。
戴维·康拉德

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

刚意识到我的代码失败了...-
不去除初始助剂。
-不管理“笨蛋”业务。

这是我获得的最远的成绩,也许有人可以完成。


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个字符

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上正确显示。提供的链接包含这些字符,并且是程序的正确版本。


-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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.