Haskell , 74 67 63 bajtów
r=read
f x|(a,(c,s:d):_)<-lex<$>lex x!!0=show(r a*r d+r c)++s:d
Wypróbuj online!
Wyjaśnienie
Jak się zorientował H.PWiz , możemy tutaj użyć leksyk Haskella, aby rozbić sznurek na części. (Wcześniej korzystałem span(>'/')
) I Laikoni wskazał, że <$>
działa tak samomapSnd
od Data.Tuple
.
Strażnik wzorów dzieli nasz kod na trzy liczby, których chcemy użyć lex
. lex
przywołuje leksykon haskell, aby zerwać pierwszy token. Zwraca listę z każdym elementem reprezentującym możliwy sposób parsowania łańcucha. Te elementy są krotkami, przy czym pierwszy element jest pierwszym tokenem, a reszta ciągu jest drugim elementem. Ponieważ format wejściowy jest bardzo regularny, zawsze będziemy mieli tylko jedną analizę, więc zawsze możemy wziąć pierwszą. Pierwszą rzeczą, którą robimy, jest wywołanie lex
na wejściu
lex x
Następnie odwijamy go z listy, dając nam 2-krotkę
lex x!!0
Pierwszy token będzie całą częścią mieszanej frakcji, pozostawiając frakcję poprzedzoną spacją, aby nadal analizować. Ponieważ krotki są Functors
, możemy użyć (<$>)
aliasu, fmap
aby zastosować lex
do drugiego elementu krotki.
lex<$>lex x!!0
To zjada przestrzeń i odrywa następny token, licznik naszej frakcji. Teraz łączymy to z dopasowaniem wzorca za pomocą <-
. Nasz wzór to
(a,(c,s:d):_)
a
chwyta całą część frakcji, naszego pierwszego tokena. :_
rozpakowuje listę wynikającą z naszego drugiego lex
. c
chwyta drugi żeton, który sprawdziliśmy, czyli licznik ułamka. Wszystko, co pozostaje, jest z tym związanes:d
co dzieli go na pierwszy znak, co gwarantuje format to/
a reszta, która będzie mianownikiem.
Po przeanalizowaniu danych wejściowych wykonujemy obliczenia:
show(r a*r d+r c)++s:d
Gdzie r
jest funkcja odczytu, którą związaliśmy wcześniej.
Należy zauważyć, że lex
zwraca listę pustą, jeśli się nie powiedzie, i niepustą, jeśli się powiedzie. Dlaczego to nie jest Maybe
nie wiem.