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
я не знаю.