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 mapSndda Data.Tuple.
Il pattern guard suddivide il nostro codice nei tre numeri che vogliamo usare lex. lexinvoca 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 lexl'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 fmapapplicare lexal 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):_)
aprende l'intera parte della frazione, il nostro primo token. :_scartare l'elenco risultante dal nostro secondo lex. cprende il secondo token che abbiamo lasciato, cioè il numeratore della frazione. Tutto ciò che rimane è legato al s:dquale 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'è rla funzione di lettura che abbiamo associato in precedenza.
È importante notare che lexrestituisce un elenco vuoto se fallisce e non vuoto se riesce. Perché questo non è un Maybenon lo so.