名前ゲームをプレイする


9

名前ゲームをプレイするプログラムを作成します。

入力

プログラムは、何らかの方法でユーザーからの入力として単一の名前を受け入れる必要があります(たとえば、標準入力から、またはコマンドライン引数として読み取る)。名前は、大文字の後に1つ以上の小文字が続く単一の単語であると想定できます。

出力

次のテンプレートに入力することにより、プログラムは、曲で説明されているように、指定された名前の韻を印刷する必要があります。

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

ここで、(X)は元の名前で、(Y)小文字で、最初の子音をすべて削除した名前です。

ただし、例外が1つあります。元の名前が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

@ephemient:Y子音が続く場合にのみ、母音として扱うことができると思います。それはそれらのケースを少なくともカバーするべきです。
— hammar

13
タッカーをごめんなさい。
— Peter Olson

回答:


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つの制御文字が含まれており、これを角かっこで囲みました。それぞれが1文字としてカウントされ、文字カウントにカウントされます。

編集:最初の結合(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

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で終わります。彼らは2つの形で来ます:

        :(TARGET)

ラベルを付けるブランチTARGET、一方

        :S(SUCCESS) F(FAILURE)

SUCCESSパターンの一致が成功した場合は分岐し、FAILUREそうでない場合は分岐します。また、成功時に分岐して失敗時に次の行に進むことも、その逆も可能です。

継続行はa +またはで始まります.。コメントはで始まります*。

それはどのように機能しますか?

名前を読み取り、小文字に変換します。母音で始まると仮定して、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

私は、1975年5月1日にMTS用に構築された1973年4月1日からのSNOBOL4バージョン3.10を使用してミシガンターミナルシステムの 6.0aリリースを実行するHercules S / 370メインフレームエミュレーターでこれを実行しましたが、おそらくSNOBOL4を現代のシステム。:)

編集:不要なブランチラベルを排除し、無条件のgotoを前の行の失敗ブランチに変えた、フォールスルーと同等の冗長な成功ブランチを削除しました(失敗ブランチだけを単独で配置できるとは知りませんでした)。 7バイトの節約。

TIOがSNOBOL4をサポートしたので、オンラインでお 試しください!注:サイズを430ではなく429と表示しています。貼り付けたときに、最後の改行が削除されたためです。継続行(で始まる行+)を単一行に変更しようとしましたが、これはメインフレームバージョンでは長すぎたため、合法ではありませんでしたが、機能して427になりました。CSNOBOL4では明らかに長い行を使用できます。ただし、スコアは430のままにしておきます。これは、スクリプトが私のマシン上にあったバイト数であり、さらに、SNOBOLは競争力がないためです。



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

編集:@Martin Enderのおかげで119バイトから115バイトに


1
PPCGへようこそ!その正規表現をに短縮できると思います/[aeiou]\w*/i。
— マーティンエンダー2017

1
元のバージョンを短縮バージョンに置き換えることができます。古いものは投稿の編集履歴に保持されます。必要に応じてJavaScript, <s>119</s> 115 bytes、ヘッダーなどに以前のスコアを含めて、興味がある場合は元々長いバージョンがあったことを人々にヒントを与えることができます。
— マーティンエンダー2017

ああ、かっこいい。再び編集されました:)
— eniallator 2017

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

私はクロジュールを学んでいるだけで、これを試してみるのは楽しいだろうと思いました。ここに私の推論があります:

-文字列の先頭から子音を削除するには:(drop-while (fn [x] (not (some #(= % x) "aeiou"))) name)

-「b」、「f」、および「m」の追加ルールを処理するために、テキストをフレーズのリストに分割しました:[", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"]

-次に、フレーズが終了するかどうかを尋ねる関数を適用しました名前が始まるのと同じ文字を使用し、それを使用してパズルのルールに基づいてこれらの3つのフレーズを変換します

-最終ステップは、結果を含む文字列を作成することです


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-stringを使用して、結果の文字列をフォーマットします。

残念ながら、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'リテラルを使用して3行目で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は名前を3回複製するので、単に「Bob」ではなく「Bob \ nBob \ nBob \ nBob」になります。次の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///'

いくつかのメモ。最初の4つの一致、1、2、3、4は、出力をまったく正しくないものに変換します。Bobはbo-bbob、Fredはfo-ffred、Mikeはmo-mmikeになりました。ケイはmo-mkayになります、mka​​y?

次に、bo-bbobをbo-obに、またはbo-bkayをbo-bayに置き換える必要があります。これを行うには、1つのs ////置換を行い、成功した場合は分岐して、スキップしたい2つ目のものにジャンプする機能を使用できます。しかし、それが失敗した場合は、分岐を通り抜けて、次の置換を行います。

t [label]コマンドはこれを行い、前のs ///が一致した場合にのみ分岐します。しかし、スクリプトの冒頭で、各行に1つのs ///を既に実行しました(1s、2sなどの先頭の数字はアドレスです。アドレスが一致する場合にのみコマンドが実行されることを意味します)。したがって、現在のラインが1、2、3、または4の場合でも、少なくとも1つのs ///が一致しています。(私はそれを逆にして名前をマッサージしてから「バナナなど」を追加しようとしましたが、そのように行き詰まり、一度にすべてしようとするといくつかの繰り返しが発生しました。)幸い、フラグはブランチを取ることでクリアされるので、「tx;:x」でそれを行います。txはxラベルに分岐し、:xはxラベルです。

ふew!これにより、最後の2つの置換の味覚が明確になります。1つを試してみて、成功した場合はもう1つに分岐し、それ以外の場合は2つ目を実行します。いずれにしても、:zラベルで終わり、パターンバッファーにはstdoutに出力される歌詞の1行が含まれています。

sedのmanページとTexinfoのマニュアルで十分な時間をかけて、sedのs / foo / bar /以外の方法を最終的に理解できるように私をだましてくれてありがとう


ああ、私はsedコマンド|とすべてのスクリプトの全長を数えています。多分私はこれを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

ちょうど私のコードが失敗
することに気づきました...-初期拘束を削除しません。
-「bo-ob」ビジネスを管理していない。

それは私が得た最も遠いところです、おそらく誰かがそれを終えることができます。


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

しかし、あと1文字あれば、一度に多くの名前を入力できます。

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.