Понеділок Міні-Гольф №7: Спростіть вимірювання інгредієнтів


12

Понеділок Міні-Гольф: Серія коротких викликів з , що публікуються (сподіваємось!) Кожного понеділка.
Вибачте, що пізно; Я зрозумів 90% шляху через написання іншої думки, що це дублікат.

Моя сім'я досить велика, тому ми їмо багато їжі. Для приготування достатньої кількості їжі нам зазвичай потрібно подвоїти, потроїти або навіть учетверо викласти! Але оскільки множення вимірювань може бути болем, було б непогано мати програму, яка б це зробила для нас.

Виклик

Ваше завдання полягає в тому, щоб створити програму або функцію, яка приймає вимірювання як число N і літеру L , і повертає те саме вимірювання, максимально спрощене. Ось необхідні вимірювальні одиниці (усі американські, як і моя родина) та відповідні букви:

1 cup (c) = 16 tablespoons (T) = 48 teaspoons (t)
1 pound (l) = 16 ounces (o)
1 gallon (g) = 4 quarts (q) = 8 pints (p) = 128 fluid ounces (f)

"максимально спрощений" означає:

  • Використання найбільшої можливої ​​одиниці вимірювання. Кожна одиниця може мати залишки 1/4, 1/3, 1/2, 2/3 або 3/4.
  • Перетворення результату в змішане число, якщо необхідно.

Наприклад, 4 oце чотири унції, що стає 1/4 l, чверть фунта. 8 t, 8 чайних ложок, стає 2 2/3 T.

Деталі

  • Вхід може бути прийнятий у будь-якому розумному форматі; те саме з виходом. ( 1 t, 1,"t", 1\ntІ т.д.)
  • Переконайтесь, що з будь-якою дробовою частиною поводиться належним чином. ( 11/4замість цього 1 1/4заборонено.)
  • Число завжди буде являти собою змішаний номер, і завжди буде мати знаменник 2, 3або 4(або жодного). (ні 1 1/8 T, ні 1.5 Tі т.д.)
  • Як результат вищезазначеного, ніколи не потрібні перетворення вниз (наприклад, чашки на столові ложки).
  • Лист завжди буде однією з літер, перелічених вище ( Tcfglopqt).

Тестові кейси

Ось великий список, який, сподіваємось, охоплює всі типи справ:

Input   | Output
--------+--------
1/2 t   | 1/2 t
3/4 t   | 1/4 T
1 t     | 1/3 T
1 1/2 t | 1/2 T
2 t     | 2/3 T
2 1/4 t | 3/4 T
2 1/2 t | 2 1/2 t
3 t     | 1 T
10 t    | 3 1/3 T
16 t    | 1/3 c
5 1/3 T | 1/3 c
8 T     | 1/2 c
16 T    | 1 c
36 T    | 2 1/4 c
1/4 c   | 1/4 c
1024 c  | 1024 c
1 o     | 1 o
4 o     | 1/4 l
5 1/3 o | 1/3 l
5 2/3 o | 5 2/3 o
8 o     | 1/2 l
28 o    | 1 3/4 l
28 l    | 28 l
2 f     | 2 f
4 f     | 1/4 p
8 f     | 1/4 q
16 f    | 1/2 q
32 f    | 1/4 g
64 f    | 1/2 g
128 f   | 1 g
2/3 p   | 1/3 q
1 1/3 p | 2/3 q
2 p     | 1/4 g
1 q     | 1/4 g

Оцінка балів

Наша кухня дуже мала, тому код повинен бути якомога коротшим, щоб не зробити кухню більш тісною. Найкоротший дійсний код у байтах виграє; tiebreaker переходить до подання, яке досягло остаточного підрахунку байтів. Переможець буде обраний наступного понеділка, 9 листопада. Удачі!

Зауважте, що цей виклик схожий на, але не дублікат Всесвітньої великої дози .



@AlexA. Ага, так, я забув посилатися на це. IMHO, це досить різний: 1) він приймає інший формат введення. 2) вихід зовсім інший. 3) потрібно більше типів конверсій. 3a) 1/8 вимірювання не використовується.
ETHproductions

@ETHproductions подібний дух еквівалентний дублікату.
Акангка

9
Це ніколи не відбудеться належними, вибачте, метричними одиницями;)
Адріан

5
Ваші гольфи стають все менше і менше міні.
Денніс

Відповіді:


2

Mathematica, 349 334 330 322 байт

Цей розділ відповідей почувався трохи самотнім. Так ось ось моя спроба. Введення слід подавати, як у тестових випадках.

n=ToExpression@StringSplit@InputString[];i=#~Mod~1&;b=#&@@n;If[Length@n==3,{x,y,z}=n,{x,y,z}=If[IntegerQ@b,{b,0,Last@n},{0,b,Last@n}]];v={0,1/4,1/3,1/2,2/3,3/4};s=<|T->16,t->3,o->16,q->4,p->2,f->16|>;r=<|T->c,t->T,o->l,f->p,p->q,q->g|>;If[v~MemberQ~i[a=(x+y)/s@z],{x,y,z}={Floor@a,i@a,r@z}]~Do~3;Print@Row[{x,y,z}/. 0->""]

Пояснення

Спочатку отримайте введення користувача, розділіть його на пробіл та призначте його n. i=#~Mod~1&створює функцію, яка отримує дробову частину числа, приймаючи її mod 1. b=#&@@nпросто отримає перший елемент у n; це було б все до першого простору.

Якщо nдовжина 3 елемента, це означає, що у нас є ціле число, дріб та одиниця. {x,y,z}=nприсвоїть x, yі zбути три частини n. Інший випадок - nце не три елементи; це означає, що замість цього буде два елементи. Щоб ми відповідали вище, ми хочемо xбути цілою частиною, yбути дробом та zодиницею. Тому в цьому випадку нам потрібно перевірити:

  • Якщо b(перший елемент n) є цілим числом, то x=b, y=0і z=Last@n(останній елемент n).
  • Якщо bце не ціле число, це означає, що ми маємо лише дріб без цілого числа. Отже ми хочемо обмінятись xі yзверху; замість цього, x=0, y=bі zте ж саме, що і вище.

Тепер нам потрібно встановити деякі списки:

v = {0, 1/4, 1/3, 1/2, 2/3, 3/4} - це перелік прийнятних дробів, як зазначено у питанні.

s = <|T -> 16, t -> 3, o -> 16, q -> 4, p -> 2, f -> 16|>це асоціація (пара ключів і значень, як словник Python), яка представляє кількість, необхідну даній одиниці, щоб піднятися «до» однієї з наступних найбільших одиниць. Наприклад, o -> 16це тому, що потрібно 16 унцій, перш ніж ми піднімаємося до 1 фунта.

r = <|T -> c, t -> T, o -> l, f -> p, p -> q, q -> g|>це об'єднання, яке насправді являє собою наступний підрозділ. Наприклад, T -> cозначає, що на одну одиницю більше, ніж столові ложки, є чашки.

If[v~MemberQ~i[a = (x + y)/s@z], {x, y, z} = {Floor@a, i@a, r@z}]~Do~3

Тепер максимальна кількість разів, коли нам потрібно піднятися на одиницю, - 3; це були б унції рідини (f) -> пінти (p) -> кварта (q) -> галон (g). Отже, зараз ми робимо наступні 3 рази:

  • Додати xі y, (цілі та дробові частини)
  • З sвищевказаної асоціації отримати елемент z; тобто отримати доступ до поточного блоку та отримати відповідне значення в цій асоціації.
  • Розділіть (x + y) на те значення, яке ми отримали вище, призначте його a, а потім отримайте його дробову частину.
  • Якщо ця частина є у списку v, тоді ми можемо піднятися на одну одиницю; встановити xна aокруглений вниз (ціла частина), встановити yна дробову частину a, потім отримати доступ до асоціації rз поточним блоком, zщоб отримати наступний блок, і встановіть це z.
  • Якщо це натомість не є частиною v, ми нічого не робимо, оскільки це неможливо спростити.

Після цього 3 рази ми роздруковуємо результат:

Print@Row[{x,y,z}/. 0->””]

Це просто роздруковується {x,y,z}підряд, але замінює будь-які нулі (якщо немає цілого чи немає дробу) порожнім рядком, тому вони не роздруковуються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.