Quante ghinee in un lordo di tre anni?


32

Fino alla decimalizzazione del 1971 , il denaro britannico si basava sulla divisione della sterlina in 240 centesimi. Uno scellino è stato di 12 centesimi quindi 20 scellini hanno fatto una sterlina. La più piccola denominazione era la scoreggia a un quarto di centesimo. C'erano molte altre denominazioni e soprannomi per le monete, che possono diventare abbastanza confusi se non sei abituato al sistema.

Sfida

Scrivi un programma o una funzione in grado di convertire (quasi) qualsiasi denominazione di denaro inglese antico in un'altra. Per rendere più semplice per l'utente è necessario supportare plurali e nickname.

Queste sono le denominazioni e i loro termini che devi supportare. Per praticità, il loro valore in termini di distanza conduce ad ogni linea.

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

(Non sono britannico, questo elenco non è affatto autorevole ma sarà sufficiente per la sfida.)

Tramite stdin o argomento della funzione dovresti prendere una stringa del modulo

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

e ritorna o stampa

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

dove [converted value]sono le [value to convert]unità della denominazione 1 convertite nella denominazione 2.

I [value to convert]e [converted value]sono galleggianti positivi. Nell'output entrambi devono essere arrotondati o troncati con 4 cifre decimali. Se lo si desidera, si può presumere che [value to convert]abbia sempre un punto decimale e zero quando si immette (ad es. 1.0Anziché1 ).

Le denominazioni 1 e 2 possono essere due termini dall'elenco precedente. Non preoccuparti se sono plurali o meno, tratta allo stesso modo tutte le denominazioni e i sinonimi. Si può presumere che il formato di input e le denominazioni siano sempre valide.

Esempi

1 pounds in shilling1 pounds is 20 shilling
( 1.0000 pounds is 20.0000 shillingandrebbe bene)

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

punteggio

Vince il codice più breve in byte .


1
I "penny" vengono sempre e solo usati per indicare un numero di monete, non una somma di denaro.
David Richerby,

4
Nit-pick: dopo la decimalizzazione, il plurale di quidè quid. Molto probabilmente questo sarebbe stato lo stesso con i vecchi soldi. Esempio: Five quid a pint! Cor blimey guvnor. Eccezione: quids-in
Digital Trauma,

7
Probabilmente avrei confuso un sacco di persone per richiedere loro di includere "ha'penny".
Kaine,

3
Non ho mai sentito un ha'penny chiamare nient'altro che un ha'penny, @kaine. Come in en.wikipedia.org/wiki/Ha%27penny_Bridge . Certo, sono troppo giovane per averlo sentito troppo spesso nei discorsi, ma l'apostrofo sembra standard nella scrittura.
TRiG,

Risposte:


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

Più leggibile (le righe e i rientri devono essere rimossi per essere eseguiti):

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

Aggiornamento: si scopre che è più corto di 1 carattere (non è necessario spazio) per tagliare la stringa in un elenco di 2 stringhe di caratteri prima di eseguire l'operazione dell'indice di stringa. /x"string"<b2 2-> xc"string"2<b2. Nient'altro deve essere cambiato.

Come funziona:

  • Questo utilizza l'approccio di @ xnor di cercare il valore della valuta usando le sue prime due lettere, così come il trucco di rilevare l'iniziale halfo two, rimuoverlo e richiamare nuovamente la funzione.

  • Per cercare il valore dei primi due caratteri, trova la posizione delle prime due lettere della valuta in una stringa, quindi si divide per 2 e assume il valore di quell'indice nell'elenco. Questo è molto più breve di un dict in Pyth.

  • Utilizza il fatto che x(trova all'interno della stringa) restituisce -1 in caso di errore per evitare di inserire po(libbre) qu(quid) o so(sovrani) nella stringa e restituisce semplicemente l'ultimo elemento dell'elenco, 960, per impostazione predefinita.

  • Riorganizzando l'ordine delle valute nel sistema di ricerca e inizializzando attentamente, con K4e J24, tutti gli spazi che sarebbero stati necessari per separare i numeri nell'elenco sono stati rimossi.

  • Utilizza l'operatore di doppia assegnazione di pyth A, sull'input diviso inper ottenere l'inizio e la fine dell'input in variabili separate.

  • Fa essenzialmente la stessa ricerca alla fine, anche se pyth non ha .split(_,1), quindi è un po 'più ingombrante.

Esempi:

$ 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
Mi arrendo ...;)
Martin Ender il

Non sapevo <e >lavoravo come operatori di stringa / lista; è molto, molto meglio che prendere la testa o la fine di una braciola :)
FryAmTheEggman

@FryAmTheEggman Sembra che mancasse anche quello nella documentazione - l'ho aggiunto.
isaacg,

Probabilmente dovrei leggere macros.py più attentamente :)
FryAmTheEggman

14

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

Riceve input da STDIN e stampa su STDOUT.

Sto usando brevi espressioni regolari per abbinare solo le denominazioni desiderate per ciascun valore. Esistono due matrici, una con regex e una con valori, con indici corrispondenti. L'array regex è un array delimitato da spazi letterale e l'array value è compresso in una stringa di caratteri UTF-8.

Sto selezionando l'indice nei valori cercando una regex che corrisponda a ciascuna denominazione. Sto anche inadempiendo al caso tuppence / half-groat (valore 8), perché quello richiedeva la regex più lunga. Allo stesso modo, alcuni dei modelli presuppongono che altri valori siano già stati associati a modelli precedenti, quindi ogni regex distingue solo il valore desiderato solo da quelli rimanenti. Usando questo, potrei probabilmente radere via un altro paio di byte riorganizzando l'ordine delle denominazioni.

Grazie a Ventero per avermi aiutato a battere Pyth rendendolo più breve!


1
È la corrispondenza regex ( s[k]) che sovrascrive $1ecc. Puoi salvare alcuni caratteri spostando il blocco della mappa in un lambda e chiamandolo direttamente nell'ultima riga (che ti consente anche di eliminare i compiti per $1e $2). Inoltre .indexè più breve di .find_index.
Ventero,

@Ventero Ah, ha senso. Grazie!
Martin Ender,

1
Regexp.new k/#{k}/e $><<gets.sub(/foo/){a=$3;...}gets[/foo/];a=$3;puts...per un totale di 221. E ovviamente puoi usare il vecchio trucco di impacchettare l'array int in una stringa (usando .pack("U*")) e quindi indicizzarla in quella stringa. Dovresti portarti a 195 caratteri / 200 byte.
Ventero,

Ancora meglio:a=gets[/foo/,3]
Ventero

@Ventero Grazie mille. Ho finito con 196/202, perché ho aggiunto un offset ai codici char per evitare ASCII non stampabile. Ancora più corto di Pyth. ;)
Martin Ender il

8

Python 3: 264 239 caratteri

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)

La funzione fottiene il valore shilling della stringa cdi valuta imprimendo le prime due lettere usando il dizionario trovandole in una stringa. I prefissi "metà" e "due" vengono rilevati e considerati tagliando il prefisso e lo spazio e applicando un moltiplicatore. Poiché "halfpenny" manca di spazio dopo "half", questo si traduce in "enny", ma viene gestito con una voce "en" fittizia.

Grazie a @isaacg e @grc per molti miglioramenti nella ricerca del dizionario.


Sapevo che poteva essere fatto :) Sono anche estremamente imbarazzato dal fatto che non sapevo che potessi definire un dizionario del genere ...: S
FryAmTheEggman,

2
@FryAmTheEggman Non ho potuto definire i dizionari tramite parole chiave fino a quando non l'ho visto utilizzato in una risposta su questo sito. Le cose che impari giocando a golf ...
xnor

Ho realizzato una versione Pyth di questo e ho ottenuto 207 caratteri. Preferiresti che lo pubblicassi qui per consentirti di aggiungere o pubblicare una risposta wiki della community?
FryAmTheEggman,

1
+1 per quella 2/4**(c<'t')parte.
njzk2,

1
Puoi salvare 13 caratteri usando .get(c[:2],960)per cercare il valore dal dizionario e omettendo le po=960,so=960,qu=960,voci dal dizionario.
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

Richiede che il numero di input sia un float in python ie 144.1

Penso che questo potrebbe essere abbreviato in Python 3 ...

... Confermato grazie a @xnor. Ha anche confermato che avere un algoritmo migliore è molto importante;)


Sostituirei q=raw_input().split(' in ')conq,b=raw_input().split(' in ')
njzk2 il

@ njzk2 Esatto ... L'ho usato anche per la riga successiva, ora :)
FryAmTheEggman,

Penso che ci sia un conflitto tra h+' gr':8e a h+' g':504seconda di chi viene valutato per primo per
semifreddi

@ njzk2 è vero ... aggiunto ua quello della 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])

Sono andato con un approccio con funzione hash ... Penso di aver sottovalutato (relativamente) quanto complesso sarebbe il processo di input (rispetto all'approccio regex, che non mi importerebbe del numero).


1

Basato sulla risposta di @ FryAmTheEggMan, con un modo diverso di testare 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

Penso che sia necessario aggiungere uno spazio finale alla printstringa formattata. Puoi anche riscrivere la lambda s=lambda x:x and C.get(x,s(x[:-1]))or 0per salvare un personaggio (insieme agli spazi). Questa è un'idea piuttosto carina, tra l'altro :)
FryAmTheEggman,

grazie, ho armeggiato per un po 'con questa notazione ternaria, che trovo sempre verbosa, ma non ho pensato alla and/orcosa.
njzk2,

Sì, l'ho imparato qui :) Penso anche che tu abbia bisogno di u.split(' ')dire qualcosa u.split(' ',1)per le valute che hanno spazi, come "mezzo sovrano".
FryAmTheEggman,

quindi questo è il motivo per il , 1!
njzk2,

2
Il ternario x and y or 0può essere abbreviato in generale x and y, poiché entrambi valutano 0o equivalentemente Falsequando xè Falsey.
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)}

Questo ottiene il valore di ogni valuta controllandola con varie regex, a partire dalla più ampia /t/; il valore viene sovrascritto se viene rilevata un'altra corrispondenza. Potrebbe esserci un modo per radere via un paio di byte riordinando la stringa regex. Puoi testarlo usando lo snippet sopra (È formattato solo per usare le finestre di dialogo e rimuovere le funzioni della freccia ES6 in modo che tutti possano testare facilmente il codice). Grazie ad Alconja per i suggerimenti.


1
È possibile tagliare 2 caratteri utilizzando 't0sh|bo0^p....'.split(0), 4 di più utilizzando .mapal posto di .forEache 3 di più chiamando c(0)ed c(1)e facendos[d].match
Alconja
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.