Haskell , 74 67 63 byte
r=read
f x|(a,(c,s:d):_)<-lex<$>lex x!!0=show(r a*r d+r c)++s:d
Provalo online!
Spiegazione
Come ha capito H.PWiz , possiamo usare il lexer di Haskell qui per spezzare la corda nelle sue parti. (Prima span(>'/')
usavo) E Laikoni ha sottolineato che <$>
funziona proprio come mapSnd
da Data.Tuple
.
Il pattern guard suddivide il nostro codice nei tre numeri che vogliamo usare lex
. lex
invoca il lexer di haskell per interrompere il primo token. Restituisce un elenco con ogni elemento che rappresenta un modo possibile per analizzare la stringa. Questi elementi sono tuple con il primo elemento come primo token e il resto della stringa come secondo elemento. Dal momento che il formato di input è molto regolare avremo sempre e solo una analisi, quindi possiamo sempre prendere il primo. La prima cosa che facciamo è invocare lex
l'input
lex x
Quindi lo scartiamo dalla sua lista dandoci una 2 tupla
lex x!!0
Il primo token sarà l'intera parte della frazione mista lasciando la frazione anteposta da uno spazio per analizzare ancora. Quindi, poiché le tuple sono Functors
, possiamo usare (<$>)
un alias per fmap
applicare lex
al secondo elemento della tupla.
lex<$>lex x!!0
Questo mangia attraverso lo spazio e interrompe il token successivo, il numeratore della nostra frazione. Ora lo associamo a una corrispondenza di pattern usando <-
. Il nostro modello è
(a,(c,s:d):_)
a
prende l'intera parte della frazione, il nostro primo token. :_
scartare l'elenco risultante dal nostro secondo lex
. c
prende il secondo token che abbiamo lasciato, cioè il numeratore della frazione. Tutto ciò che rimane è legato al s:d
quale lo divide nel suo primo carattere, garantito dal formato come a /
e il resto che sarà il denominatore.
Ora che abbiamo analizzato l'input, eseguiamo il calcolo effettivo:
show(r a*r d+r c)++s:d
Dov'è r
la funzione di lettura che abbiamo associato in precedenza.
È importante notare che lex
restituisce un elenco vuoto se fallisce e non vuoto se riesce. Perché questo non è un Maybe
non lo so.