Chơi trò chơi tên


9

Viết một chương trình để chơi trò chơi tên .

Đầu vào

Chương trình của bạn nên chấp nhận một tên duy nhất làm đầu vào từ người dùng theo một cách nào đó (ví dụ: đọc từ đầu vào tiêu chuẩn hoặc dưới dạng đối số dòng lệnh). Bạn có thể giả sử rằng tên đó là một từ duy nhất bao gồm chữ in hoa và theo sau là một hoặc nhiều chữ cái viết thường.

Đầu ra

Chương trình của bạn phải in vần cho tên đã cho, như được giải thích trong bài hát, bằng cách điền vào mẫu sau:

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

Đây (X)là tên gốc và (Y)là tên viết thường với bất kỳ phụ âm đầu tiên nào bị loại bỏ.

Tuy nhiên, có một ngoại lệ. Nếu tên ban đầu bắt đầu bằng m, fhoặc b, nó nên được viết mà không có chữ cái này trên dòng tương ứng. Ví dụ: nếu tên là Bob, dòng "b" sẽ kết thúc bằng bo-ob. Lưu ý rằng trong trường hợp này, bất kỳ phụ âm khác được lưu giữ, vì vậy cho Fredfo-red, không phải fo-ed.

Ví dụ

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!

Chấm điểm

Mã ngắn nhất sẽ thắng.


1
Tôi đoán Yđược xử lý như một giọng hát, như vậy YvesIveshay Arnold.
người dùng không xác định

1
Nhưng còn Yates, Yestin, Yolanda hay Yulia thì sao?
ephemient

@ephemient: Tôi đoán bạn chỉ có thể coi Ynhư một nguyên âm nếu nó được theo sau bởi một phụ âm. Điều đó nên bao gồm những trường hợp ít nhất.
hammar

13
Tôi cảm thấy tiếc cho Tucker.
Peter Olson

Câu trả lời:


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

Mã này bao gồm 5 ký tự điều khiển mà tôi đã đặt trong ngoặc. Mỗi người chỉ được tính là một nhân vật duy nhất đối với số lượng nhân vật.

EDIT: Di chuyển phép nối đầu tiên (J) sang sau và thay đổi dán trước (P) thành dán sau (p) đã lưu cho tôi 1 ký tự. Ngoài ra, việc không bắt o- trong regex đã giúp tôi tiết kiệm thêm 2 ký tự.


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 (cộng với tôi đã thêm một dấu nhắc; cái ở trên chỉ chờ một tên được gõ):

      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

Đây là chương trình SNOBOL đầu tiên tôi từng viết.

SNOBOL là một ngôn ngữ định hướng theo dòng, như FORTRAN, COBOL hoặc BASIC. Mỗi dòng bao gồm một nhãn tùy chọn bắt đầu trong cột 1, mã cho dòng có thể liên quan đến bài tập và khớp mẫu và một nhánh tùy chọn. Có, dòng kết thúc bằng (tùy chọn) GOTOs. Chúng có hai dạng:

        :(TARGET)

Chi nhánh để dán nhãn TARGET, trong khi

        :S(SUCCESS) F(FAILURE)

Các nhánh để SUCCESSnếu khớp mẫu thành công, hoặc FAILUREnếu không. Bạn cũng có thể chỉ phân nhánh thành công và rơi vào dòng tiếp theo về thất bại, hoặc ngược lại.

Các dòng tiếp tục bắt đầu bằng một +hoặc .. Nhận xét bắt đầu bằng a *.

Làm thế nào nó hoạt động?

Đọc trong một tên, chuyển đổi nó thành chữ thường. Thiết lập tên B-, F- và M giả sử nó bắt đầu bằng nguyên âm. Sau đó kiểm tra nếu nó bắt đầu với một loạt các phụ âm. Nếu không, chúng tôi đã sẵn sàng để đi! Nếu vậy, hãy loại bỏ các phụ âm hàng đầu và thiết lập các tên B-, F- và M giả sử nó không bắt đầu bằng bất kỳ chữ cái nào trong số đó. Cuối cùng, kiểm tra xem nó có bắt đầu với từng chữ cái đó không, sửa tên nếu cần. Sau đó, chúng tôi đã sẵn sàng để chơi trò chơi tên!

Chạy mẫu:

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

Tôi đã chạy nó trên trình giả lập máy tính lớn Hercules S / 370 chạy phiên bản 6.0a của Hệ thống đầu cuối Michigan sử dụng SNOBOL4 phiên bản 3.10 từ ngày 1 tháng 4 năm 1973 được xây dựng cho MTS vào ngày 1 tháng 5 năm 1975, nhưng có lẽ có nhiều cách dễ dàng hơn để chạy SNOBOL4 trên một hệ thống hiện đại. :)

Chỉnh sửa: Đã xóa một nhánh thành công dư thừa tương đương với một sự sụp đổ (Tôi không nhận ra rằng tôi có thể tự đặt một nhánh thất bại) để loại bỏ nhãn nhánh không cần thiết và biến một goto vô điều kiện thành một nhánh thất bại trên dòng trước đó, để tiết kiệm 7 byte.

Bây giờ TIO có hỗ trợ SNOBOL4, bạn có thể dùng thử trực tuyến! Lưu ý: Nó hiển thị kích thước là 429 thay vì 430 vì khi tôi dán nó ở đó, nguồn cấp dữ liệu cuối cùng đã bị xóa. Tôi đã thử thay đổi dòng tiếp tục (bắt đầu bằng +) thành một dòng duy nhất, không hợp pháp trên phiên bản máy tính lớn vì dòng này quá dài, và nó đã hoạt động và đưa nó xuống mức 427. Rõ ràng CSNOBOL4 cho phép các dòng dài hơn. Mặc dù vậy, tôi sẽ để điểm số của mình ở mức 430, bởi vì đó là bao nhiêu byte tập lệnh trên máy của tôi, và bên cạnh đó, SNOBOL khá không cạnh tranh.


Bây giờ bạn có thể chạy SNOBOL4 trên Dùng thử trực tuyến
Giuseppe

@Giuseppe Wow, thật tuyệt! Cảm ơn vì đã cho tôi biết.
David Conrad

CSNOBOL4 có một vài điểm khác biệt, vì bài tập chỉ yêu cầu không gian hàng đầu, vì vậy tất cả các dòng của bạn N = TRIM(INPUT)đều có thể N =TRIM(INPUT).
Giuseppe

2

J , 149 ký tự

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

Giải trình:

Hàm này trả về tên mà không có phụ âm đầu

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

Sau đó, phần còn lại là một hàm trả về chuỗi hoàn chỉnh chuỗi.

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

Chỉnh sửa: từ 119 đến 115 byte nhờ @Martin Ender


1
Chào mừng đến với PPCG! Tôi tin rằng bạn có thể rút ngắn regex đó /[aeiou]\w*/i.
Martin Ender

1
Bạn có thể thay thế phiên bản gốc bằng bản rút gọn. Cái cũ sẽ được lưu giữ trong lịch sử chỉnh sửa của bài viết. Nếu bạn muốn, bạn có thể bao gồm các điểm số trước đó như JavaScript, <s>119</s> 115 bytestrong tiêu đề để cung cấp cho mọi người một gợi ý rằng ban đầu có phiên bản dài hơn nếu họ quan tâm.
Martin Ender

À, tuyệt. Đã chỉnh sửa lại :)
eniallator

1

Clojure , 292 ký tự sau khi thu nhỏ

Đây là một nỗ lực đầu tiên, gần như tích cực Tôi có thể gạt nó xuống hơn nữa:

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

Tôi chỉ đang học clojure và nghĩ rằng sẽ rất vui nếu được thử cái này. Đây là lý do của tôi:

- Để loại bỏ các phụ âm từ đầu chuỗi: (drop-while (fn [x] (not (some #(= % x) "aeiou"))) name)

- Để xử lý các quy tắc bổ sung cho "b", "f" và "m", tôi chia văn bản thành danh sách các cụm từ: [", bo-b" "\nBanana-fana-fo-f" "\nFee-fi-mo-m"]

- Sau đó, tôi áp dụng một hàm hỏi xem cụm từ có kết thúc không với cùng một chữ cái mà tên bắt đầu và đã sử dụng để biến đổi 3 cụm từ đó dựa trên quy tắc của câu đố

- Bước cuối cùng là xây dựng một chuỗi có kết quả


1

Scala 281

Tôi đã thay thế (X) và (Y) trong mẫu bằng #012. Schỉ là một tên mới cho Stringa(b,c,d)là định nghĩa tốc ký chob.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)

Yêu cầu kiểm tra:

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

Và vô lương tâm:

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

Vâng, tôi biết là hơi muộn nhưng ...

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

Nó sử dụng chuỗi f mới để định dạng chuỗi kết quả.

Thật không may, tôi không nghĩ TIO hỗ trợ chuỗi f.

Phiên bản cũ

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

Đã lưu 3 byte nhờ @officialaimm


lưu ba byte bằng cách sử dụng chữ 'AEIOUaeiou' và tránh thấp hơn () trong dòng thứ 3
chính thức tuyên bố

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'

Tôi không biết rõ về sed trước khi tôi làm điều này. Tôi, uh, biết nó tốt hơn rất nhiều , bây giờ. Sed đầu tiên trong đường ống nhân đôi tên ba lần để nó trở thành "Bob \ nBob \ nBob \ nBob" thay vì chỉ "Bob". Chiếc sed tiếp theo làm việc nặng.

Mong đợi đầu vào trên stdin như echo Name |sed ...

Ung dung:

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

Một vài lưu ý. Bốn trận đấu đầu tiên, 1s, 2s, 3s, 4s, biến đổi đầu ra thành một cái gì đó không hoàn toàn chính xác. Bob đã trở thành bo-bbob, Fred đã trở thành fo-ffred và Mike đã trở thành mo-mmike. Kay sẽ trở thành mo-mkay, mkay?

Sau đó, chúng ta cần thay thế bo-bbob bằng bo-ob hoặc bo-bkay bằng bo-bay. Để làm điều đó, chúng ta có thể sử dụng một tính năng trong đó chúng ta thực hiện một thay thế s /// và sau đó phân nhánh nếu nó thành công, nhảy qua tính năng thứ hai mà bây giờ chúng ta muốn bỏ qua. Nhưng nếu nó bị bỏ lỡ, chúng tôi muốn rơi qua nhánh và thực hiện thay thế tiếp theo.

Lệnh t [nhãn] thực hiện điều đó, chỉ phân nhánh nếu s /// trước đó khớp. Nhưng ở phần đầu của tập lệnh, tôi đã thực hiện một s /// cho mỗi dòng (các số đứng đầu trong 1, 2, v.v. là các địa chỉ; chúng có nghĩa là lệnh chỉ được thực hiện nếu địa chỉ khớp). Vì vậy, cho dù chúng tôi đang ở dòng nào, 1, 2, 3 hoặc 4, ít nhất một s /// đã khớp. . được xóa bằng cách lấy một nhánh, vì vậy chúng tôi làm điều đó với "tx ;: x". các nhánh tx cho nhãn x và: x là nhãn x.

Phù! Điều đó làm sạch vòm miệng cho hai sự thay thế cuối cùng. Chúng tôi thử một cái, và nếu nó thành công, chúng tôi sẽ phân nhánh khác, nếu không chúng tôi sẽ làm cái thứ hai. Dù bằng cách nào, chúng ta kết thúc tại nhãn: z và bộ đệm mẫu chứa một dòng lời bài hát được in ra thiết bị xuất chuẩn.

Cảm ơn bạn đã lừa tôi dành đủ thời gian với trang sed man và hướng dẫn Texinfo để cuối cùng hiểu cách làm hơn so với sed s / foo / bar /


Ồ, tôi đang đếm toàn bộ chiều dài của kịch bản bằng lệnh sed |và tất cả. Có lẽ tôi nên gọi đây là bash / sed, hoặc tính nó khác đi? Tôi không biết. Tôi hài lòng với nó như hiện tại nhưng hãy cho tôi biết nếu nó khác với các tiêu chuẩn của PPCG.
David Conrad

0

Con trăn, 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

Chỉ cần nhận ra mã của tôi thất bại ...
- Không loại bỏ các yếu tố gây ngạc nhiên ban đầu.
- Không quản lý doanh nghiệp 'bo-ob'.

Đó là thứ xa nhất mà tôi có, có lẽ ai đó có thể hoàn thành nó.


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 ký tự

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

Nhưng chỉ với một ký tự nữa, bạn có thể nhập nhiều tên trong một lần:

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\!

Bộ kiểm tra

Mã sử ​​dụng các ký tự không thể in được và như vậy không hiển thị đúng trên Stack Exchange. Liên kết được cung cấp chứa các ký tự này và là phiên bản chính xác của chương trình.


-1

Con trăn

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.