Wie viele Guineas in einem Brutto von dreißig Jahren?

32

Bis zur Dezimalisierung im Jahr 1971 beruhte das britische Geld auf der Aufteilung des Pfunds in 240 Pennys. Ein Schilling war 12 Pennys, also machten 20 Schilling ein Pfund. Die kleinste Stückelung war das Hochrad bei einem Viertel eines Pennys. Es gab viele andere Bezeichnungen und Spitznamen für Münzen, die ziemlich verwirrend werden können, wenn Sie nicht an das System gewöhnt sind.

Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die (fast) jede Stückelung alten englischen Geldes in eine andere umwandeln kann. Um es dem Benutzer einfacher zu machen, müssen Sie Pluralformen und Spitznamen unterstützen.

Dies sind die Konfessionen und deren Synonyme, die Sie unterstützen müssen. Der Einfachheit halber führt ihr Wert in Farthings jede Zeile.

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

(Ich bin kein Brite, diese Liste ist keineswegs maßgebend, aber sie wird für die Herausforderung ausreichen.)

Über stdin oder Funktionsargument sollten Sie einen String der Form übernehmen

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

und zurück oder drucken

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

wo [converted value]ist [value to convert]Einheiten Stückelung 1 bis Denomination 2 umgewandelt.

Die [value to convert]und [converted value]sind positive Schwimmer. In der Ausgabe sollten beide auf 4 Dezimalstellen gerundet oder abgeschnitten werden. Auf Wunsch können Sie [value to convert]bei der Eingabe immer von einem Dezimalpunkt und Null ausgehen (zB 1.0statt 1).

Die Bezeichnungen 1 und 2 können zwei beliebige Begriffe aus der obigen Liste sein. Kümmere dich nicht darum, ob es sich um Plural handelt oder nicht, sondern behandle alle Bezeichnungen und Synonyme gleich. Sie können davon ausgehen, dass das Eingabeformat und die Nennwerte immer gültig sind.

Beispiele

1 pounds in shilling1 pounds is 20 shilling
( 1.0000 pounds is 20.0000 shillingwäre gut)

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

Wertung

Der kürzeste Code in Bytes gewinnt.

Calvins Hobbys
quelle
1
"Pennies" bezieht sich immer nur auf eine Anzahl von Münzen, nicht auf einen Geldbetrag.
David Richerby
4
Nit-Pick Post decimalisation, die Mehrzahl von quidIS quid. Dies wäre höchstwahrscheinlich auch mit dem alten Geld so gewesen. Beispiel: Five quid a pint! Cor blimey guvnor. Ausnahme: Quids-in
Digitales Trauma
7
Ich würde wahrscheinlich eine Menge Leute durcheinander bringen, um von ihnen zu verlangen, "ha'penny" aufzunehmen.
Kaine
3
Ich habe noch nie gehört, dass ein Penny irgendetwas anderes heißt als ein Penny, @kaine. Wie in en.wikipedia.org/wiki/Ha%27penny_Bridge . Natürlich bin ich selbst zu jung, um es in der Rede zu oft gehört zu haben, aber das Apostroph scheint in der Schrift Standard zu sein.
TRiG

Antworten:

9

Pyth , 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

Mehr Lesbarkeit (Zeilenumbrüche und Einrückungen müssen entfernt werden, um ausgeführt zu werden):

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

Update: Es hat sich herausgestellt, dass es 1 Zeichen kürzer ist (kein Leerzeichen erforderlich), um die Zeichenfolge in eine Liste von 2 Zeichenfolgen zu zerlegen, bevor die Zeichenfolgenindexoperation ausgeführt wird. /x"string"<b2 2-> xc"string"2<b2. Ansonsten muss nichts geändert werden.

Wie es funktioniert:

  • Dabei wird @ xnors Ansatz verwendet, den Wert der Währung anhand der ersten beiden Buchstaben zu ermitteln. Außerdem wird der Trick verwendet, den Anfangsbuchstaben zu ermitteln halfoder ihn zu twoentfernen und die Funktion erneut aufzurufen.

  • Um den Wert der ersten beiden Zeichen zu ermitteln, wird die Position der ersten beiden Buchstaben der Währung in einer Zeichenfolge ermittelt, durch 2 geteilt und der Wert an diesem Index in der Liste übernommen. Dies ist viel kürzer als ein Diktat in Pyth.

  • Verwendet die Tatsache, dass x(find within string) -1 zurückgibt , wenn nicht vermieden wird, dass ( poPfund) qu(Quid) oder so(Sovereigns) in die Zeichenfolge eingefügt werden, und gibt standardmäßig einfach das letzte Element der Liste (960) zurück.

  • Durch Umstellen der Reihenfolge der Währungen im Nachschlagesystem und sorgfältiges Initialisieren mit K4und J24wurden alle Leerzeichen entfernt, die zum Trennen der Nummern in der Liste erforderlich gewesen wären.

  • Uses pyth Dual Zuweisungsoperator, Aam Eingang Split auf inden Anfang und das Ende der Eingabe in separaten Variablen zu erhalten.

  • Hat im Wesentlichen die gleiche Suche am Ende, obwohl Pyth keine hat .split(_,1), so ist es etwas umständlicher.

Beispiele:

$ 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
isaacg
quelle
3
Ich gebe auf ...;)
Martin Ender
Ich wusste es nicht <und >arbeitete als String- / Listen-Slice-Operatoren. Das ist viel, viel besser als den Kopf oder das Ende eines Koteletts zu nehmen :)
FryAmTheEggman
@FryAmTheEggman Sieht so aus, als hätte das auch in der Dokumentation gefehlt - ich habe es hinzugefügt.
isaacg
Ich sollte macros.py wahrscheinlich genauer durchlesen :)
FryAmTheEggman
14

Ruby, 345 306 302 288 287 278 273 253 252 242 232 221 202 190 Bytes

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

Nimmt Eingaben von STDIN und druckt auf STDOUT.

Ich verwende kurze reguläre Ausdrücke, um nur den gewünschten Nennwerten für jeden Wert zu entsprechen. Es gibt zwei Arrays, eines mit regulären Ausdrücken und eines mit Werten, an entsprechenden Indizes. Das Regex-Array ist ein durch Leerzeichen getrenntes Array-Literal, und das Wert-Array ist in eine Zeichenfolge aus UTF-8-Zeichen gepackt.

Ich wähle den Index in die Werte aus, indem ich nach einem regulären Ausdruck suche, der zu jedem Nennwert passt. Ich verwende auch standardmäßig den Fall Tuppence / Half-Groat (Wert 8), da hierfür die längste Regex erforderlich ist. Ebenso wird in einigen Mustern davon ausgegangen, dass andere Werte bereits mit früheren Mustern übereinstimmen, sodass jede Regex nur den gewünschten Wert von den übrigen unterscheidet. Auf diese Weise könnte ich wahrscheinlich noch ein paar Bytes abschneiden, indem ich die Reihenfolge der Bezeichnungen ändere.

Vielen Dank an Ventero, der mir geholfen hat, Pyth zu schlagen und es kürzer zu machen!

Martin Ender
quelle
1
Es ist die Regex-Übereinstimmung ( s[k]), die $1usw. überschreibt . Sie können einige Zeichen speichern, indem Sie den Kartenblock in ein Lambda verschieben und dies direkt in der letzten Zeile aufrufen (wodurch Sie auch die Zuweisungen für $1und löschen können $2). Ist auch .indexkürzer als .find_index.
Ventero
@Ventero Ah, das macht Sinn. Vielen Dank!
Martin Ender
1
Regexp.new k/#{k}/und $><<gets.sub(/foo/){a=$3;...}gets[/foo/];a=$3;puts...für insgesamt 221. Und Sie können natürlich den alten Trick anwenden, das int-Array in einen String zu packen (using .pack("U*")) und dann in diesen String zu indizieren. Solltest du auf 195 Zeichen / 200 Bytes bringen.
Ventero
Noch besser:a=gets[/foo/,3]
Ventero
@Ventero Vielen Dank. Am Ende hatte ich 196/202, weil ich den Zeichencodes einen Offset hinzugefügt habe, um nicht druckbares ASCII zu vermeiden. Immer noch kürzer als Pyth. ;)
Martin Ender
8

Python 3: 264 239 Zeichen

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)

Die Funktion ermittelt fden Schilling-Wert der Währungszeichenfolge, cindem sie die ersten beiden Buchstaben mithilfe des Wörterbuchs abtastet, indem sie sie in einer Zeichenfolge findet. Die Präfixe "half" und "two" werden durch Zerhacken des Präfixes und des Leerzeichens und Anwenden eines Multiplikators erkannt und berücksichtigt. Da "halfpenny" ein Leerzeichen nach "half" fehlt, ergibt dies "enny", aber das wird mit einem fiktiven "en" -Eintrag behandelt.

Vielen Dank an @isaacg und @grc für viele Verbesserungen beim Nachschlagen des Wörterbuchs.

xnor
quelle
Ich wusste, dass es möglich ist :) Es ist mir auch sehr peinlich, dass ich nicht wusste, dass man so ein Wörterbuch definieren kann ...: S
FryAmTheEggman
2
@FryAmTheEggman Ich konnte Wörterbücher auch nicht über Schlüsselwörter definieren, bis ich sah, dass sie in einer Antwort auf dieser Site verwendet wurden. Die Dinge, die Sie Golf lernen ...
Xnor
Ich habe eine Pyth-Version davon erstellt und 207 Zeichen erhalten. Möchtest du lieber, dass ich es hier poste, damit du es hinzufügst, oder eine Community-Wiki-Antwort postest?
FryAmTheEggman
1
+1 für diesen 2/4**(c<'t')Teil.
njzk2
1
Sie können 13 Zeichen speichern, indem Sie .get(c[:2],960)den Wert aus dem Wörterbuch nachschlagen und die po=960,so=960,qu=960,Einträge aus dem Wörterbuch auslassen .
isaacg
5

Python 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

Erfordert die Eingabe einer Zahl als Float in Python 144.1

Ich denke, das könnte in Python 3 verkürzt werden ...

... Bestätigt dank @xnor. Auch bestätigt, dass ein besserer Algorithmus sehr wichtig ist;)

FryAmTheEggman
quelle
Ich würde q=raw_input().split(' in ')durchq,b=raw_input().split(' in ')
njzk2
@ njzk2 Ganz richtig ... Ich habe dies jetzt auch für die nächste Zeile verwendet :)
FryAmTheEggman
Ich denke, es gibt einen Konflikt zwischen h+' gr':8und h+' g':504je nachdem, wer zuerst für die Hälfte Grütze ausgewertet wird
njzk2
@ Njzk2 das ist wahr ... hinzugefügt, uum die Guinea One ...
FryAmTheEggman
2

Haskell - 315 Bytes

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

Ich habe mich für einen Ansatz mit Hash-Funktionen entschieden ... Ich glaube, ich habe (relativ) unterschätzt, wie komplex die Eingabeverarbeitung sein würde (im Gegensatz zum Regex-Ansatz, bei dem die Zahl keine Rolle spielt).

FireFly
quelle
1

Basierend auf der Antwort von @ FryAmTheEggMan mit einer anderen Art des Testens str.startwith:

Python 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
njzk2
quelle
Ich denke, Sie müssen der printund der formatierten Zeichenfolge ein Leerzeichen hinzufügen . Sie können das Lambda auch umschreiben s=lambda x:x and C.get(x,s(x[:-1]))or 0, um ein Zeichen (zusammen mit den Leerzeichen) zu speichern. Dies ist eine ziemlich nette Idee, übrigens :)
FryAmTheEggman
danke, ich habe eine weile mit dieser ternären notation rumgespielt, die ich immer wortreich finde, aber an der and/orsache nicht gedacht habe.
njzk2
Ja, ich habe es hier gelernt :) Ich denke auch, dass Sie für Währungen, die Leerzeichen haben, wie "Half Sovereign" , u.split(' ')mitreden u.split(' ',1)müssen.
FryAmTheEggman
das ist also der grund für die , 1!
njzk2
2
Das Ternär x and y or 0kann generell zu verkürzt werden x and y, da beide zu 0oder gleichwertig auswerten Falsewann xFalsey ist.
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)}

Dies ermittelt den Wert jeder Währung, indem sie mit verschiedenen regulären Ausdrücken verglichen wird, beginnend mit der breitesten /t/; Der Wert wird überschrieben, wenn eine andere Übereinstimmung festgestellt wird. Möglicherweise gibt es eine Möglichkeit, einige Bytes zu reduzieren, indem Sie die Regex-Zeichenfolge neu anordnen. Sie können es mit dem obigen Snippet testen (Es ist nur zur Verwendung von Dialogfeldern und zum Entfernen von ES6-Pfeilfunktionen formatiert, damit jeder den Code problemlos testen kann). Danke an Alconja für die Vorschläge.

NinjaBearMonkey
quelle
1
Sie können 2 Zeichen mit 't0sh|bo0^p....'.split(0), 4 weitere mit .mapanstelle von .forEachund 3 weitere mit c(0)und c(1)und tuns[d].match
Alconja