Haskell , 74 67 63 bytes
r=read
f x|(a,(c,s:d):_)<-lex<$>lex x!!0=show(r a*r d+r c)++s:d
Experimente online!
Explicação
Como H.PWiz descobriu, podemos usar o lexer de Haskell aqui para quebrar a corda em suas partes. (No começo eu estava usando span(>'/')
) E Laikoni apontou que <$>
funciona exatamente como mapSnd
em Data.Tuple
.
O protetor de padrão divide nosso código nos três números que queremos usar lex
. lex
chama o lexer de haskell para interromper o primeiro token. Ele retorna uma lista com cada elemento representando uma maneira possível de analisar a sequência. Esses elementos são tuplas, com o primeiro elemento sendo o primeiro token e o restante da string sendo o segundo elemento. Agora, como o formato de entrada é muito regular, apenas teremos exatamente uma análise, para que possamos sempre fazer a primeira. A primeira coisa que fazemos é chamar lex
na entrada
lex x
Em seguida, desembrulhámo-lo da lista, fornecendo uma
lex x!!0
O primeiro token será a parte inteira da fração mista, deixando a fração precedida por um espaço para análise. Então, como as tuplas são Functors
, podemos usar (<$>)
um alias para fmap
aplicar lex
ao segundo elemento da tupla.
lex<$>lex x!!0
Isso consome o espaço e interrompe o próximo token, o numerador da nossa fração. Agora, vinculamos isso a uma correspondência de padrão usando <-
. Nosso padrão é
(a,(c,s:d):_)
a
agarra a parte inteira da fração, nosso primeiro token. :_
desembrulha a lista resultante do nosso segundo lex
. c
pega o segundo token que inserimos, que é o numerador da fração. Tudo o que resta está vinculado ao s:d
que o divide em seu primeiro caractere, garantido pelo formato de a /
e o restante, que será o denominador.
Agora que analisamos a entrada, fazemos o cálculo real:
show(r a*r d+r c)++s:d
Onde r
está a função de leitura que ligamos anteriormente.
É importante observar que lex
retorna uma lista vazia se falhar e não vazia se for bem-sucedida. Por que isso não é um Maybe
eu não sei.