Làm thế nào nhiều Guinness trong một tổng số ba xu?


32

Cho đến khi số thập phân vào năm 1971 , tiền của Anh dựa trên việc chia bảng Anh thành 240 đồng xu. Một shilling là 12 penny nên 20 shilling đã tạo ra một pound. Mệnh giá nhỏ nhất là rắm ở một phần tư của một xu. Có nhiều mệnh giá và biệt danh khác cho tiền xu, có thể trở nên khá khó hiểu nếu bạn không quen với hệ thống.

Thử thách

Viết một chương trình hoặc chức năng có thể chuyển đổi (gần như) bất kỳ mệnh giá tiền tiếng Anh cũ nào sang tiền khác. Để giúp người dùng dễ dàng hơn, bạn cần hỗ trợ số nhiều và biệt danh.

Đây là các mệnh giá và các thuật ngữ đồng nghĩa của chúng mà bạn phải hỗ trợ. Để thuận tiện, giá trị của chúng trong khoảng cách dẫn mỗi dòng.

1: farthing, farthings
2: halfpence, halfpenny, halfpennies
4: penny, pennies, pence, copper, coppers
8: twopenny, twopennies, twopence, tuppence, half groat, half groats
12: threepence, threepenny, threepennies, threepenny bit, threepenny bits, thruppence, thrupenny, thrupennies, thrupenny bit, thrupenny bits
16: groat, groats
24: sixpence, sixpenny, sixpennies, sixpenny bit, sixpenny bits, tanner, tanners
48: shilling, shillings, bob
96: florin, florins, two bob bit, two bob bits
120: half crown, half crowns
240: crown, crowns
480: half sovereign, half sovereigns
504: half guinea, half guineas
960: pound, pounds, pounds sterling, sovereign, sovereigns, quid, quids
1008: guinea, guineas

(Tôi không phải là người Anh, danh sách này không có nghĩa là có thẩm quyền nhưng nó sẽ đủ cho thách thức.)

Thông qua stdin hoặc đối số hàm, bạn nên lấy một chuỗi có dạng

[value to convert] [denomination 1] in [denomination 2]

và trả lại hoặc in

[value to convert] [denomination 1] is [converted value] [denomination 2]

nơi [converted value][value to convert]đơn vị thuộc giáo phái 1 chuyển đổi sang mệnh giá 2.

Các [value to convert][converted value]đang nổi tích cực. Trong đầu ra cả hai nên được làm tròn hoặc cắt thành 4 chữ số thập phân. Nếu muốn, bạn có thể giả sử [value to convert]luôn có dấu thập phân và 0 khi nhập (ví dụ 1.0thay vì 1).

Mệnh giá 1 và 2 có thể là hai thuật ngữ bất kỳ trong danh sách trên. Đừng lo lắng về việc họ có số nhiều hay không, hãy đối xử với tất cả các mệnh giá và từ đồng nghĩa như nhau. Bạn có thể giả sử định dạng đầu vào và mệnh giá luôn hợp lệ.

Ví dụ

1 pounds in shilling1 pounds is 20 shilling
( 1.0000 pounds is 20.0000 shillingsẽ ổn thôi)

0.6 tuppence in tanner0.6 tuppence is 0.2 tanner

24 two bob bits in pounds sterling24 two bob bits is 2.4 pounds sterling

144 threepennies in guineas144 threepennies is 1.7143 guineas

Chấm điểm

Mã ngắn nhất tính bằng byte thắng.


1
"Đồng xu" chỉ được sử dụng để chỉ một số tiền, không phải là một số tiền.
David Richerby

4
Nit-chọn: Đăng decimalisation, số nhiều của quidquid. Nhiều khả năng điều này sẽ giống với tiền cũ. Ví dụ : Five quid a pint! Cor blimey guvnor. Ngoại lệ: quids-in
Chấn thương kỹ thuật số

7
Tôi có thể sẽ làm rối tung rất nhiều người để yêu cầu họ đưa vào "ha'penny".
kaine

3
Tôi chưa bao giờ nghe một ha'penny gọi bất cứ thứ gì ngoại trừ một ha'penny, @kaine. Như trong en.wikipedia.org/wiki/Ha%27penny_Bridge . Tất nhiên, tôi còn quá trẻ để nghe nó quá thường xuyên trong lời nói, nhưng dấu nháy đơn dường như là tiêu chuẩn trong văn bản.
TRiG

Câu trả lời:


9

Bình dương , 146 145

K4J24L?*y>b-5>b\t?2>b\t.5}<b2"hatw"@[1K8K12K16J48J1008*JT96*2J960)xc"fapetucothengrsishtagucrflbo"2<b2AGHcz" in"++G%" is %0.4f"*vhcGdcyjdtcGdytHH

Dễ đọc hơn (dòng mới và thụt lề phải được gỡ bỏ để chạy):

K4J24
L?*y>b-5>b\t?2>b\t.5
  }<b2"hatw"
  @[1K8K12K16J48J1008*JT96*2J960)
   xc"fapetucothengrsishtagucrflbo"2<b2
AGHcz" in"
++G
  %" is %0.4f"
   *vhcGdcyjdtcGdytH
 H

Cập nhật: Hóa ra, nó ngắn hơn 1 ký tự (không cần khoảng trống) để cắt chuỗi thành danh sách 2 chuỗi ký tự trước khi chạy hoạt động chỉ mục chuỗi. /x"string"<b2 2-> xc"string"2<b2. Không có gì khác cần phải thay đổi.

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

  • Điều này sử dụng phương pháp tìm kiếm giá trị của tiền tệ bằng cách sử dụng hai chữ cái đầu tiên của @ xnor, cũng như thủ thuật phát hiện chữ cái đầu halfhoặc twoxóa nó và gọi lại hàm.

  • Để tra cứu giá trị của hai ký tự đầu tiên, nó tìm vị trí của hai chữ cái đầu tiên của tiền tệ trong một chuỗi, sau đó chia cho 2 và lấy giá trị tại chỉ mục đó trong danh sách. Điều này là ngắn hơn nhiều so với một dict trong pyth.

  • Sử dụng thực tế là x(tìm trong chuỗi) trả về -1 khi không thể đặt po(bảng Anh)qu (quid) hoặc so(chủ quyền) trong chuỗi và chỉ cần trả về phần tử cuối cùng của danh sách, theo mặc định.

  • Bằng cách sắp xếp lại thứ tự các loại tiền trong hệ thống tra cứu và khởi tạo cẩn thận, với K4J24, tất cả các khoảng trống cần thiết để tách các số trong danh sách đã bị xóa.

  • Sử dụng toán tử gán kép của pyth, A , trên phần tách đầu vào inđể lấy phần đầu và phần cuối của phần đầu vào trong các biến riêng biệt.

  • Về cơ bản, cùng một tra cứu ở cuối, mặc dù pyth không có .split(_,1), vì vậy nó có phần rườm rà hơn.

Ví dụ:

$ pyth programs/currency.pyth <<< '5 florins in half guineas'
5 florins is 0.9524 half guineas

$ pyth programs/currency.pyth <<< '0.4 quid in sixpenny bits'
0.4 quid is 16.0000 sixpenny bits

3
Tôi từ bỏ ...;)
Martin Ender

Tôi không biết <>làm việc như các toán tử chuỗi / danh sách; đó là nhiều, tốt hơn nhiều so với việc người đứng đầu hoặc kết thúc của một Chop :)
miếng FryAmTheEggman

@FryAmTheEggman Có vẻ như cũng bị thiếu trong tài liệu - Tôi đã thêm nó.
isaacg

Tôi có lẽ nên đọc qua macros.py cẩn thận hơn :)
FryAmTheEggman

14

Hồng ngọc, 345 306 302 288 287 278 273 253 252 242 232 221 202 190 byte

f=->s{" !#+/7OďǿȗϟЏ'"[%w{fa fp ^pe|co r..p ^gr x|ta sh|^b fl|b f.c ^c f.s .gu d|v ^g .}.index{|k|s[/#{k}/]}].ord-31}
$><<gets.sub(/ (.+ i)n /){" #{r=$1}s %0.4f ".%$`.to_f/f[$']*f[r]}

Lấy đầu vào từ STDIN và in sang STDOUT.

Tôi đang sử dụng các biểu thức chính quy ngắn để chỉ khớp với các mệnh giá mong muốn cho mỗi giá trị. Có hai mảng, một có regexes và một có giá trị, tại các chỉ số tương ứng. Mảng regex là một mảng được phân cách bằng dấu cách và mảng giá trị được đóng gói thành một chuỗi các ký tự UTF-8.

Tôi đang chọn chỉ mục vào các giá trị bằng cách tìm kiếm biểu thức chính phù hợp với từng mệnh giá. Tôi cũng mặc định là trường hợp tuppence / nửa họng (giá trị 8), vì điều đó đòi hỏi regex dài nhất. Tương tự, một số mẫu cho rằng các giá trị khác đã được khớp với các mẫu trước đó, vì vậy mỗi biểu thức chỉ phân biệt giá trị mong muốn chỉ với các giá trị còn lại. Sử dụng điều này, tôi có thể có thể loại bỏ một vài byte khác bằng cách sắp xếp lại thứ tự của các mệnh giá.

Cảm ơn Ventero đã giúp tôi đánh bại Pyth khiến nó ngắn hơn!


1
Đó là kết hợp regex ( s[k]) ghi đè, $1v.v. Bạn có thể lưu một vài ký tự bằng cách di chuyển khối bản đồ vào lambda và gọi nó trực tiếp ở dòng cuối cùng (cũng cho phép bạn bỏ các bài tập cho $1$2). Cũng .indexngắn hơn .find_index.
Ventero

@Ventero Ah, điều đó có ý nghĩa. Cảm ơn bạn!
Martin Ender

1
Regexp.new k/#{k}/$><<gets.sub(/foo/){a=$3;...}gets[/foo/];a=$3;puts...với tổng số 221. Và tất nhiên bạn có thể sử dụng thủ thuật cũ là đóng gói mảng int thành một chuỗi (sử dụng .pack("U*")) và sau đó lập chỉ mục vào chuỗi đó. Sẽ giúp bạn giảm xuống còn 195 ký tự / 200 byte.
Ventero

Thậm chí tốt hơn:a=gets[/foo/,3]
Ventero

@Ventero Cảm ơn rất nhiều. Tôi đã kết thúc với 196/202, vì tôi đã thêm một phần bù vào mã char để tránh ASCII không thể in được. Vẫn ngắn hơn Pyth. ;)
Martin Ender

8

Python 3: 264 239 ký tự

f=lambda c:c[:2]in"hatw"and f(c[5-(c>'t'):])*2/4**(c<'t')or[1,4,4,4,8,12,16,24,24,48,48,96,240,1008,960]['fapecoentuthgrsitashboflcrgu'.find(c[:2])//2]
a,b=input().split(" in ")
x,c=a.split(" ",1)
print(a,"is %0.4f"%(eval(x)*f(c)/f(b)),b)

Hàm flấy giá trị shilling của chuỗi tiền tệ cbằng cách lấy dấu hai chữ cái đầu tiên bằng từ điển bằng cách tìm chúng trong một chuỗi. Các tiền tố "một nửa" và "hai" được phát hiện và tính toán bằng cách cắt tiền tố và khoảng trắng và áp dụng một số nhân. Vì "nửa xu" thiếu một khoảng trống sau "một nửa", điều này dẫn đến "enny", nhưng điều đó được xử lý với một mục "en" hư cấu.

Cảm ơn @isaacg và @grc đã cải thiện rất nhiều về việc tra cứu từ điển.


Tôi biết điều đó có thể được thực hiện :) Tôi cũng vô cùng xấu hổ vì tôi không biết bạn có thể định nghĩa một từ điển như thế ...: S
FryAmTheEggman

2
@FryAmTheEggman Tôi không biết bạn có thể định nghĩa từ điển thông qua các từ khóa cho đến khi tôi thấy nó được sử dụng trong câu trả lời trên trang web này. Những điều bạn học chơi gôn ...
xnor

Tôi đã tạo một phiên bản Pyth này và nhận được 207 ký tự. Bạn có muốn tôi đăng nó ở đây để bạn thêm, hoặc đăng một câu trả lời wiki cộng đồng?
FryAmTheEggman

1
+1 cho 2/4**(c<'t')phần đó .
njzk2

1
Bạn có thể lưu 13 ký tự bằng cách sử dụng .get(c[:2],960)để tra cứu giá trị từ từ điển và bỏ qua các po=960,so=960,qu=960,mục từ từ điển.
isaacg

5

Con trăn 2 - 345 358

s=str.startswith
h='half'
u,v=raw_input().split(' in ')
a,b=u.split(' ',1)
C=dict(fa=1,pe=4,twop=8,tu=8,thr=12,gr=16,si=24,ta=24,sh=48,b=48,fl=96,c=240,po=960,so=960,q=960,gu=1008)
C.update({h+'p':2,h+' gr':8,'two ':96,h+' c':120,h+' s':480,h+' gu':504})
for c in iter(C):
 if s(b,c):k=C[c]
 if s(v,c):f=C[c]
print u+' is %0.4f '%(eval(a)*k/f)+v

Yêu cầu số đầu vào là số float trong python tức là 144.1

Tôi nghĩ rằng điều này có thể được rút ngắn trong python 3 ...

... Xác nhận nhờ @xnor. Cũng xác nhận rằng có một thuật toán tốt hơn rất nhiều vấn đề;)


Tôi sẽ thay thế q=raw_input().split(' in ')bằngq,b=raw_input().split(' in ')
njzk2

@ njzk2 Hoàn toàn đúng ... Bây giờ tôi cũng đã sử dụng nó cho dòng tiếp theo :)
FryAmTheEggman

Tôi nghĩ rằng có một xung đột giữa h+' gr':8h+' g':504tùy thuộc vào người được đánh giá đầu tiên cho một nửa số
njzk2

@ njzk2 đó là sự thật ... đã thêm u guinea ...
FryAmTheEggman

2

Haskell - 315 byte

w x=f(u x)*v(u x)
f=maybe 1 id.l"ha tw tu th si"[0.5,2,2,3,6]
v x@(_:xs)|Just w<-l"bo cr gr gu so co fa fl pe po qu sh ta"[12,60,4,252,240,1,0.25,24,1,240,240,12,6]x=w|True=v xs
l k v x=take 2 x`lookup`zip(words k)v
u=unwords
i s|(n:x,_:t)<-span(/="in")$words s=u$n:x++["is",show$read n*w x/w t]++t
main=interact i

2

JavaScript (ES5), 344

I=prompt()
n=I.match(/[\d.]+ /)[0]
A=I.slice(n.length).split(" in ")
function m(x){return{fi:1,he:2,p:4,pe:4,cr:4,tn:8,hg:8,tp:12,te:12,g:16,gs:16,sn:24,tr:24,si:48,b:48,fn:96,to:96,hc:120,c:240,cs:240,hs:480,hgtrue:504,ps:960,se:960,q:960,ga:1008}[x[0]+(x[5]||"")+(x[10]=="a"||"")]}
alert(n+A[0]+" is "+(n*m(A[0])/m(A[1])).toFixed(4)+" "+A[1])

Tôi đã thực hiện một cách tiếp cận hàm băm ... Tôi nghĩ rằng tôi đã đánh giá thấp (tương đối) mức độ phức tạp của quá trình xử lý đầu vào (so với phương pháp regex, điều đó sẽ không quan tâm đến con số).


1

Dựa trên câu trả lời của @ FryAmTheEggMan, với một cách kiểm tra khác str.startwith:

Con trăn 2: 317

h='half'
C=dict(fa=1,pe=4,twop=8,tu=8,thr=12,gr=16,si=24,ta=24,sh=48,b=48,fl=96,c=240,po=960,so=960,q=960,gu=1008)
C.update({h+'p':2,h+' gr':8,'two ':96,h+' c':120,h+' s':480,h+' gu':504})
u,v=raw_input().split(' in ')
a,b=u.split(' ',1)
s=lambda x:x and C.get(x, s(x[:-1]))
print u+' is %0.4f '%(eval(a)*s(b)/s(v))+v

Tôi nghĩ bạn cần thêm một khoảng trắng ở cuối printvà chuỗi được định dạng. Bạn cũng có thể viết lại lambda như s=lambda x:x and C.get(x,s(x[:-1]))or 0để lưu một ký tự (cùng với khoảng trắng). Đây là một ý tưởng khá gọn gàng, btw :)
FryAmTheEggman

cảm ơn, tôi loay hoay một lúc với ký hiệu tạm thời này, thứ mà tôi luôn tìm thấy dài dòng, nhưng không phải mặc dù and/orđiều đó.
njzk2

Vâng, tôi đã học được ở đây :) Tôi cũng nghĩ bạn cần phải u.split(' ')nói u.split(' ',1)về các loại tiền tệ có không gian, như "một nửa chủ quyền".
FryAmTheEggman

Vì vậy, đó là lý do cho , 1!
njzk2

2
x and y or 0Nói chung x and y, ternary có thể được rút ngắn , vì cả hai đều đánh giá 0hoặc tương đương Falsekhi xFalsey.
xnor

1

JavaScript ES6, 264 273

f=t=>{s=t.split(x=' in')
c=d=>{'t0sh|bo0^p|co0f0fp0fl|b b0gu0d|v0wn0gr0f g|t..?p0f s0f gu0f c0x|an'.split(0).map((e,i)=>{v=s[d].match(e)?[12,48,4,1,2,96,1008,960,240,16,8,480,504,120,24][i]:v})
return v}
return s.join(' is '+~~(1e4*t.split(' ')[0]*c(0)/c(1))/1e4)}

Điều này nhận được giá trị của mỗi loại tiền bằng cách kiểm tra nó dựa trên các biểu thức khác nhau, bắt đầu bằng mức rộng nhất /t/; giá trị được ghi đè nếu gặp phải trận đấu khác. Có thể có một cách để loại bỏ một vài byte bằng cách sắp xếp lại chuỗi regex. Bạn có thể kiểm tra nó bằng đoạn trích ở trên (Nó chỉ được định dạng để sử dụng hộp thoại và loại bỏ các chức năng mũi tên ES6 để mọi người có thể kiểm tra mã dễ dàng). Cảm ơn Alconja cho những lời đề nghị.


1
Bạn có thể cắt 2 chars bằng cách sử dụng 't0sh|bo0^p....'.split(0), 4 hơn bằng cách sử dụng .mapthay vì .forEach3 thêm bằng cách gọi c(0)c(1)và làms[d].match
Alconja
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.