Скільки Гвіней у валовій триденці?


32

До децималізації в 1971 році британські гроші базувалися на поділі фунта на 240 копійок. Шилінг становив 12 копійок, тому 20 шилінгів склали фунт. Найменшим номіналом було фартінг на чверті копійки. Було багато інших номіналів та прізвиська для монет, які можуть стати дуже заплутаними, якщо ви не звикли до системи.

Виклик

Напишіть програму або функцію, яка може конвертувати (майже) будь-яку номінал старих англійських грошей на будь-які інші. Щоб полегшити користувача, вам потрібно підтримувати множини та прізвиська.

Це номінали та їх синонімічні умови, які ви повинні підтримувати. Для зручності їх значення у доробках веде кожен рядок.

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

(Я не британець, цей список аж ніяк не є авторитетним, але його буде достатньо для виклику.)

Через аргумент stdin або функцію слід взяти рядок форми

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

і повернути або роздрукувати

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

де [converted value]є [value to convert]одиниці номіналу 1, перетворені на номінал 2.

[value to convert]І [converted value]позитивні поплавці. На виході обидва повинні бути округленими або усіченими до 4 знаків після коми. При бажанні ви можете припустити, що [value to convert]при введенні завжди є десяткова крапка і нуль (наприклад, 1.0замість 1).

Номіналами 1 і 2 можуть бути будь-які два терміни зі списку вище. Не хвилюйтеся, чи множинні вони чи ні, ставитесь до всіх номіналів та синонімів однаково. Ви можете припустити, що формат введення та номінали завжди дійсні.

Приклади

1 pounds in shilling1 pounds is 20 shilling
( 1.0000 pounds is 20.0000 shillingбуло б добре)

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

Оцінка балів

Виграє найкоротший код у байтах .


1
"копійки" використовуються лише колись для позначення кількості монет, а не про суму грошей.
Девід Річербі

4
Ніт-забрати: Post, десяткова грошова система множини quidIS quid. Швидше за все, це було б так само і зі старими грошима. Приклад: Five quid a pint! Cor blimey guvnor. Виняток: quids-in
Digital Trauma

7
Я, мабуть, зіпсує багато людей, щоб вимагати, щоб вони включали "хаппен".
kaine

3
Я ніколи не чув, щоб ха -пені називали що-небудь окрім ha'penny, @kaine. Як в en.wikipedia.org/wiki/Ha%27penny_Bridge . Звичайно, я сам занадто молодий, щоб занадто часто його чув у мовленні, але апостроф здається стандартним у письмовій формі.
TRiG

Відповіді:


9

Піта , 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

Більш читабельні (для запуску потрібно видалити нові рядки та відступи):

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

Оновлення: виявляється, на 1 символ коротше (не потрібно місця), щоб перебити рядок до списку з 2 символьних рядків перед запуском операції з індексом рядка. /x"string"<b2 2-> xc"string"2<b2. Нічого іншого не потрібно міняти.

Як це працює:

  • Для цього використовується підхід @ xnor до пошуку вартості валюти за допомогою перших двох літер, а також хитрість виявити початковий halfабо two, вилучити його та викликати функцію ще раз.

  • Щоб знайти значення перших двох символів, він знаходить розташування перших двох літер валюти в рядку, потім ділиться на 2 і приймає значення за цим індексом у списку. Це набагато коротше, ніж дикта в піті.

  • Використовує той факт, що x(знайти всередині рядка) повертає -1 за відмови уникнути введення po(фунтів) qu(quid) або so(суверенів) у рядок, а просто повернути за замовчуванням останній елемент списку 960.

  • Переставляючи порядок валют у системі пошуку та ретельно ініціалізуючи, з K4та J24, були видалені всі пробіли, які були б потрібні для розділення номерів у списку.

  • Використовує оператор подвійного призначення pyth A, на вхідному розщепленні, inщоб отримати початок і кінець введення в окремі змінні.

  • По суті, той самий пошук в кінці, хоча піту немає .split(_,1), тому він дещо громіздкий.

Приклади:

$ 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
Я здаюся ...;)
Мартін Ендер

Я не знав <і >працював як оператор фрагментів рядків / списків; це набагато, набагато краще, ніж взяти голову або закінчити
відбивання

@FryAmTheEggman Схоже, цього не вистачало і в документації - я це додав.
isaacg

Я, мабуть, повинен прочитати macros.py уважніше :)
FryAmTheEggman

14

Рубі, 345 306 302 288 287 278 273 253 252 242 232 221 202 190 байт

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]}

Здійснює вхід зі STDIN та друкує на STDOUT.

Я використовую короткі регулярні вирази для відповідності лише бажаним номіналам для кожного значення. Є два масиви, один з регулярними виразами та один зі значеннями, за відповідними показниками. Масив регулярних виразів є масивом, обмеженим пробілом, і масив значень упакований у рядок символів UTF-8.

Я підбираю індекс до значень, шукаючи регулярний вираз, який відповідає кожній номіналі. Я також дефолтував у справі "tuppence / half-groat" (значення 8), тому що це вимагало найдовшого регексу. Так само деякі з шаблонів припускають, що інші значення вже узгоджувались з більш ранніми шаблонами, тому кожен регулярний вираз відрізняє бажане значення лише від решти. Використовуючи це, я, ймовірно, міг би поголити ще пару байтів, переставивши порядок номіналів.

Дякую Вентеро за те, що допомагає мені перемогти Pyth, скорочуючи його!


1
Це збіг регулярних виразів ( s[k]) перезаписує $1і т. Д. Ви можете зберегти кілька символів, перемістивши блок карти в лямбда і зателефонувавши безпосередньо в останній рядок (що також дозволяє скидати завдання для $1і $2). Також .indexкоротше, ніж .find_index.
Вентеро

@ Вентеро Ах, це має сенс. Дякую!
Мартін Ендер

1
Regexp.new k/#{k}/і $><<gets.sub(/foo/){a=$3;...}gets[/foo/];a=$3;puts...загалом 221. І ви, звичайно, можете використовувати старий трюк упаковки масиву int у рядок (використовуючи .pack("U*")), а потім індексувати в цей рядок. Якщо вам доведеться знизити до 195 символів / 200 байт.
Вентеро

Навіть краще: a=gets[/foo/,3]
Вентеро

@ Вентеро Велике спасибі Я закінчив 196/202, тому що я додав зміщення до char кодів, щоб уникнути недрукуваного ASCII. Ще коротший за Піта. ;)
Мартін Ендер

8

Пітон 3: 264 239 символів

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)

Функція fотримує значення шилінгу валютного рядка cшляхом дактилоскопії перших двох літер за допомогою словника шляхом знаходження їх у рядку. Префікси "половина" та "два" виявляються та обліковуються шляхом подрібнення префікса та пробілу та застосування множника. Оскільки "halfpenny" не вистачає місця після "половини", це призводить до "enny", але це обробляється вигаданим "en" записом.

Дякуємо @isaacg та @grc за багато вдосконалень у пошуку словника.


Я знав, що це можна зробити :) Я також дуже збентежений, що не знав, що ти можеш визначити такий словник ...: S
FryAmTheEggman

2
@FryAmTheEggman Я не знаю, що ви могли визначати словники за допомогою ключових слів, поки я не побачив, що це використовується у відповіді на цьому сайті. Те, чого ти вивчаєш гольфу ...
xnor

Я зробив Pyth версію цього і отримав 207 символів. Ви хочете, щоб я розмістив його тут, щоб ви додали або опублікували відповідь на вікі спільноти?
FryAmTheEggman

1
+1 для цієї 2/4**(c<'t')частини.
njzk2

1
Ви можете зберегти 13 символів, використовуючи .get(c[:2],960)для пошуку значення зі словника та опущення po=960,so=960,qu=960,записів зі словника.
isaacg

5

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

Потрібен номер вхідного сигналу з плаваючою в python, тобто 144.1

Я думаю, що це може бути скорочено в python 3 ...

... Підтверджено завдяки @xnor. Також підтвердили, що мати кращий алгоритм має велике значення;)


Я хотів би замінити q=raw_input().split(' in ')наq,b=raw_input().split(' in ')
njzk2

@ njzk2 Цілком вірно ... Зараз я також використовував це для наступного рядка :)
FryAmTheEggman

Я думаю, що існує конфлікт між h+' gr':8і h+' g':504залежно від того, хто оцінюється першим за половину крупи
njzk2

@ njzk2 це правда ... додано uв
Гвінею

2

Haskell - 315 байт

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

Я пішов з підходом до хеш-функцій ... Я думаю, що я недооцінив (відносно), наскільки складною буде обробка вводу (над підсумком регулярних виразів, що не хвилює кількість).


1

На основі відповіді @ FryAmTheEggMan з іншим способом тестування str.startwith:

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

Я думаю, що вам потрібно додати пробіл printу відтвореному рядку та відформатованому рядку. Ви також можете переписати лямбда, s=lambda x:x and C.get(x,s(x[:-1]))or 0щоб зберегти символ (разом із пробілами). Це досить охайна ідея, btw :)
FryAmTheEggman

дякую, я на деякий час поспілкувався з цим потрійним позначенням, яке я завжди знаходжу багатослівним, але нічого з цього не зробив and/or.
njzk2

Так, я це навчився тут :) Я також думаю, що вам потрібно u.split(' ')говорити u.split(' ',1)про валюти, які мають пробіли, як "напівсуверен".
FryAmTheEggman

так що це причина для , 1!
njzk2

2
Трійця x and y or 0може бути скорочена в цілому до x and y, оскільки обидва оцінюють 0або рівнозначно, Falseколи xце Фолсі.
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)}

Це отримує значення кожної валюти, перевіряючи її на різні регулярні вирази, починаючи з найширшого /t/; значення перезаписується, якщо зустрічається інша відповідність. Можливо, є спосіб стригти пару байтів, упорядкувавши рядок регулярних виразів. Ви можете перевірити його за допомогою фрагмента, описаного вище (він відформатований лише для використання діалогових вікон та видалення функцій стрілок ES6, щоб кожен міг легко перевірити код). Дякуємо Alconja за пропозиції.


1
Ви можете обрізати 2 символів, використовуючи 't0sh|bo0^p....'.split(0), 4 більше, використовуючи .mapзамість .forEachі 3 більш по телефону c(0)і c(1)і робитиs[d].match
Alconja
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.