Haskell , 74 67 63 байт
r=read
f x|(a,(c,s:d):_)<-lex<$>lex x!!0=show(r a*r d+r c)++s:d
Спробуйте в Інтернеті!
Пояснення
Як зрозумів H.PWiz , ми можемо використовувати тут лексеми Haskell, щоб розбити рядок на його частини. (Раніше я використовував span(>'/')) І Лайконі зазначив, що <$>працює так само, як і mapSndвід Data.Tuple.
Захист шаблону розбиває наш код на три числа, які ми хочемо використовувати lex. lexвикликає лексеру haskell, щоб відірвати перший маркер. Він повертає список з кожним елементом, який представляє можливий спосіб розбору рядка. Ці елементи є кортежами, перший елемент є першим жетоном, а решта рядка - другим елементом. Оскільки формат введення дуже регулярний, ми будемо мати лише один синтаксичний аналіз, тому ми завжди можемо взяти перший. Перше, що ми робимо, - це посилання lexна вхід
lex x
Потім ми знімаємо його зі свого списку, даючи нам 2-кратні
lex x!!0
Першим жетоном буде вся частина змішаної фракції, залишаючи фракцію, попередньо пробілом для нерухомого розбору. Тоді, оскільки кортежі є, Functorsми можемо використовувати (<$>)псевдонім для fmapнанесення lexна другий елемент кортежу.
lex<$>lex x!!0
Це проїжджає через простір і відриває наступний жетон, чисельник нашої дроби. Тепер ми прив’язуємо це до відповідності шаблону за допомогою <-. Наш зразок такий
(a,(c,s:d):_)
aхапає всю частину дробу, наш перший жетон. :_розгортає список в результаті другого lex. cхапає другий жетон, який ми лексикували, тобто чисельник дробу. Все, що залишається, пов'язане з тим, s:dщо розбиває його на перший символ, гарантований форматом, який буде а, /а залишок, який буде знаменником.
Тепер, коли ми розібрали вхід, робимо фактичні обчислення:
show(r a*r d+r c)++s:d
Де rфункція читання, яку ми зв'язали раніше.
Важливо зауважити, що lexповертається список порожнім, якщо він не працює, і не порожній, якщо він успішний. Чому це не є Maybeя не знаю.