Немає такого поняття, як безкоштовний обід


17

... чи є?

Ваше завдання - проаналізувати мій рахунок на обід, який містить базову ціну, підказки, знижки, купони та додаткові послуги та дізнатися, чи був мій обід 0 доларів чи менше . Якщо це вхід:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Тоді вихід може бути false. Ось як це працює:

12.34 є базовою ціною.

15 tipозначає додати 15% до загальної кількості.

25 discountозначає відняти 25% від загальної кількості.

1.5 extraозначає додати 1,5 до загальної суми.

2 couponозначає відняти 2 від загальної суми.

Може бути будь-яка кількість підказок, знижок, купонів та додаткових послуг, але завжди буде одна базова ціна.

Тоді ми робимо (12.34 * 1.15) * 0.75 + 1.5 - 2для виходу 10,14. 10.14 більше 0, тому ми виводимо помилкові. Мій обід був не безкоштовним.

Правила

число tip означає додати число відсотків до загальної суми.

число discount означає відняти число відсотків від загальної кількості

число extra означає додати число до загальної суми

число coupon означає відняти число від загального

Ще один приклад:

10
20 tip
20 discount
2 coupon
2 coupon
1 coupon
50 discount
2.55 coupon

Ціна -0.24((10 * 1,20 * 0,80 - 2 - 2 - 1) * 0,5 - 2,55), тому вихід правдивий (мій обід був безкоштовним.)

Примітки:

  • Точність повинна бути не менше 2 знаків після коми.
  • Ви можете взяти введення як рядок з новими рядками (необов'язковий останній рядок) або іншим символом розділення, або масивом / списком входів.

5
Чи потрібно вводити ім'я, чи ми можемо вважати порядок, якщо ми просто вводимо масив чисел [12.34,15,25,1.5,2]?
Синусоїд

@StewieGriffin Ви не можете обрати замовлення. Може бути більше 5 рядів, а може і менше. Ви можете взяти 2 купони як купон на 2,00, а 15 tipяк0.15 tip
програміст5000

Чи вхідний до регістру? Це всі слова, які нам потрібно підтримати?
Rɪᴋᴇʀ

@Riker - це всі потрібні слова, і введення завжди буде мати малі літери.
програміст5000

5
Як працює наказ про оцінку? Наприклад, якщо ми маємо знижку, то підказка, чи застосовується підказка до початкової суми чи суми, що знижується?

Відповіді:


2

05AB1E , 37 33 34 байт

I|vy#`0èÇ7%`">* - (>* +"#sè.V}î0›_

Спробуйте в Інтернеті!

Пояснення

Позикує mod 7хитрість з відповіді Джонатана Аллана на желе

I                                  # initialize stack with first input
 |v                                # loop over all other inputs
   y#`                             # split input on space as separate to stack
      0èÇ                          # get the character code of the first letter of the type
         7%`                       # mod by 7
            ">* - (>* +"#          # push the list ['>*','-','(>*','+'] where
                                   # '>*' =  increment and multiply
                                   # '-' =   subtract
                                   # '(>*' = negate, increment, multiply
                                   # '+' =   add
                         s         # swap the top 2 items on the stack
                          è        # use the mod result to index into the list
                           .V      # run as 05AB1E code
                             }     # end loop
                              î0›_ # check if the result rounded up to nearest integer 
                                   # is less than or equal to 0

Я отримую, 1коли значення <1.
12431234123412341234123

@ 12431234123412341234123: Хороший улов. Порівняння, очевидно, кидається на ціле число: /
Емінья,

9

JavaScript (ES6), 88 85 байт

Приймає введення як масив рядків. Повертається 0не безкоштовно або 1безкоштовно.

a=>a.map(s=>([a,b]=s.split` `,t+={e:+a,c:-a,t:x=t*a/100,d:-x}[(b||'e')[0]]),t=0)|t<=0

Як це працює

Кожен рядок розділений на простір, щоб отримати a= сума, b= тип операції. Якщо взагалі немає операцій (що стосується першого рядка), bза замовчуванням встановлено значення "e""додатково".

Щоб додати правильну суму до загальної суми t, ми використовуємо об'єкт, ключі якого є першою літерою операції:

{
  e: +a,           // extra
  c: -a,           // coupon
  t: t * a / 100,  // tip
  d: -t * a / 100  // discount
}

Примітка : Якщо вексель складався лише з одного елемента, map()він повертає одноелементний масив, який буде приведений до цілого числа при застосуванні |оператора, що робить остаточний тест невдалим. Але ОП підтвердило, що цього не може статися. (Масиви з 2 або більше елементів примусові до 0.)

Демо


3

CJam , 45 42 байт

q~Sf/(sd\{L(d\~ci6%"1\-* + )* -"S/=~}fL0>!

Візьміть дані як масив рядків, а підказки та знижки приймайте як десятичні.

Спробуйте в Інтернеті!

Пояснення

q~                e# Read and eval the input.
Sf/               e# Split each string by spaces.
(sd               e# Pull out the first element (base price) and cast it to a double.
\                 e# Bring the array back to the top.
{                 e# For each element L in the array:
 L                e#  Push L.
 (d               e#  Pop out the first element and cast it to a double.
 \~               e#  Bring the second element to the top of the stack.
 ci6%             e#  Mod its first character's ASCII value by 6. (c,d,e,t) -> (3,4,5,2)
 "1\-* + )* -"S/  e#  Push this string and split it on spaces.
 =                e#  Get the element given by number from the mod. CJam uses modular arrays,
                  e#    so 4 and 5 get elements 0 and 1 respectively.
 ~                e#  Eval whichever string was retrieved.
}fL               e# (end of loop)
0>!               e# Check if it's not greater than 0.

Код, який оцінюється залежно від перших літер:

t -> ")*"    Adds 1 to the tip amount and multiplies it by the current price.

d -> "1\-*"  Subtracts the discount amount from 1 and multiplies it by the current price.

e -> "+"     Adds the extra amount to the current price.

c -> "-"     Subtracts the coupon amount from the current price.

3

Желе ,  42 39 байт

⁾_@
⁾C×
”+
⁾‘×
ḲµṪḢO%7µĿṭ
ḢW;Ç€j”µFV>0¬

Бере список рядків з десятковими форматованими числами
(Провідні нулі будуть працювати, але мають побічний ефект друку нулів до STDOUT до кінцевого результату).

Спробуйте в Інтернеті! - не безкоштовно; або безкоштовно .

Як?

⁾_@ - Link 1: a coupon
⁾_@ - literal "_@" - the Jelly code for subtraction with reversed arguments

⁾C× - Link 2: a discount
⁾C× - literal "C×" - the Jelly code for complement (1-input) then multiply

”+ - Link 3: extra cost
”+ - literal '+' - the Jelly code for add

⁾‘× - Link 4: a tip
⁾‘× - literal "‘×" - the Jelly code for increment (input+1) then multiply

ḲµṪḢO%7µĿṭ - Link 5, switch: char list
Ḳ          - split on spaces (gives [amount, type] as char lists)
 µ     µ   - monadic chain separation to get a value, say v
  Ṫ        - tail (get the type: "coupon", "discount", "extra", or "tip")
   Ḣ       - head (get the first character: 'c', 'd', 'e' or 't') 
    O      - cast to ordinal (99, 100, 101, or 116)
     %7    - mod 7 (1, 2, 3, or 4)
        Ŀ  - call link v as a monad
         ṭ - tack to the amount char list

ḢW;Ç€j”µFV>0¬ - Main link: list of strings (char lists)
Ḣ             - head - the base price char list
 W            - wrap in a list
   Ç€         - call the last link (5) as a monad for €ach of the rest
  ;           - concatenate
      ”µ      - literal 'µ' - Jelly's monadic chain separator
     j        - join all the parts with 'µ's             "10",".2 tip",".2 discount", "2 coupon","2 coupon","1 coupon",".5 discount","2.55 coupon":
        F     - flatten (makes a char list, for example: "10µ.20‘×µ.20C×µ2_@µ2_@µ1_@µ.50C×µ2.55_@")
         V    - evaluate as Jelly code (the above evaluates to -0.2499999999999991)
          >0  - greater than 0?
            ¬ - not

Послідовно виводить 0 для мене ...
програміст5000

А, можливо, я повинен сказати, що формат використовує десяткові?
Джонатан Аллан

Ой. Так, слід.
програміст5000

Я пишу пояснення в мо, ось приклад безкоштовного обіду.
Джонатан Аллан

3

GNU sed + dc, 117 111 107 байт

Використовуючи -zпрапор перекладача (включений у бал як 1 байт):

s/discount/_tip/g
s/tip/.01*1+*/g
s/extra/+/g
s/coupon/-/g
s/.*/dc -e '& 0r-p'/e
s/[^-]*$/free/
s/-/not /

Пояснення

#!/bin/sed -fz

# Convert to dc expression (discount is just a negative tip)
s/discount/_tip/g
s/tip/.01*1+*/g
s/extra/+/g
s/coupon/-/g

# Run dc
s/.*/dc -e '& 0r-p'/e

# Convert to pretty output
s/[^-]*$/free/
s/-/not /

Оскільки вхідні дані вже дуже близькі до зворотних польських позначень, перетворення extraі couponна, +і -, і не набагато більше, змінити відсотки на множники. Потім викликайте dcі виробляйте читабельний результат залежно від того, чи -знайдений (ми маємо заперечувати результат, тому -мається на увазі "не вільний", інакше 0 буде особливим випадком, який потребує власної обробки).

Приклад

Другий випадок із запитання:

10
20 tip
20 discount
2 coupon
2 coupon
1 coupon
50 discount
2.55 coupon

Це стає цією dcпрограмою:

10
20 .01*1+*
20 _.01*1+*
2 -
2 -
1 -
50 _.01*1+*
2.55 -
 0r-p

Результат:

free

2

JavaScript, 173 169 145 байт

i=>{w=i.split`\n`.map($=>$.split` `);t=+w.shift()[0];p=$=>t*$/100;w.map(x=>{k=+x[0];f=x[1][0];l={e:k,c:-k,t:p(k),d:-p(k)},t+=l[f]});return t<=0;}

У гольфі ще має бути багато

Спробуйте в Інтернеті! (145 байт зараз)

Спробуй:

<script>var _=i=>{w=i.split('\n').map($=>$.split(' '));t=+w.shift()[0];p=$=>t*$/100;w.map(x=>{k=+x[0];f=x[1][0];t+=f=='e'&&k||f=='c'&&(-k)||f=='t'&&p(k)||f=='d'&&(-p(k))});return t<=0;}</script>
<textarea oninput="document.querySelector('pre').innerText=_(this.value)"></textarea>
<pre></pre>

Дякуємо програмісту 5000 за всі його поради щодо гольфу


Чому потрібен вузол?
програміст5000

1
Також ви можете робити {w=i.split`<nl>`там, де <nl> - це буквальний новий рядок
програміст5000

Вузол не потрібно. Я просто використовував його для тестування на TIO
Альберто Рівера

Я додав фрагмент стека для його випробування. Не соромтеся відкатати, якщо вам це не подобається.
програміст5000

1
Ви можете зняти f=деталь, це дозволено правилами, а можна замінити $.split(' ')на $.split` `.
програміст5000

2

JavaScript (ES6), 97 107

Введіть як багаторядковий рядок із заднім рядком.

t=>t.replace(/(\S+) ?(.*)?\n/g,(x,d,b)=>t-=b>'t'?-t*d/100:b>'e'?d:b>'d'?t*d/100:b?-d:d,t=0)&&t>=0

Регепс розбиває числову та необов'язкову текстову частину для кожного рядка у d та b .
Розрахунки повинні бути більш-менш обвідними. Лише певна примітка:
- використання, -=щоб уникнути проблем зі змішуванням числа з рядками
- сума заперечується, щоб зберегти 1 байт, тому остання перевірка призначена >= 0замість<= 0

PS все ще довший, ніж @ Arnauld's. Щури

Тест

var f=
t=>t.replace(/(\S+) ?(.*)?\n/g,(x,d,b)=>t-=b>'t'?-t*d/100:b>'e'?d:b>'d'?t*d/100:b?-d:d,t=0)&&t>=0

a=`12.34
15 tip
25 discount
1.5 extra
2 coupon
`
b=`10
20 tip
20 discount
2 coupon
2 coupon
1 coupon
50 discount
2.55 coupon
`

console.log('Not free: '+a,f(a))
console.log('Free: '+b,f(b))


1

C # 324 219 байт

bool a(string[] l){var x=0f;foreach(var s in l){var b=float.Parse(s.Split(' ')[0]);if(s.EndsWith("p"))x*=b;else if(s.EndsWith("t"))x*=1-b;else if(s.EndsWith("n"))x-=b;else if(s.EndsWith("a"))x+=b;else x=b;}return x<=0;}

Це не дуже і, мабуть, не найкращий спосіб, але ось він. Вимагає введення передаватись як рядковий масив, а поради / знижки передаватись як плавці (0.15 tip замість 15 tip), оскільки це було пояснено як прийнятне в коментарях специфікації.

Пояснення:

bool a(string[] l){                         //Define method with input string array l and bool output
    var x=0f;                               //Initialize float x
    foreach(var s in l){                    //Iterate through lines
        var b=float.Parse(s.Split(' ')[0]); //Parse the number from the line and store it in float b
        if(s.EndsWith("p"))                 //If line ends with "p" then line is "tip"
            x*=b;                           //Parse number from line to float add 1 and multiply by x
        else if(s.EndsWith("t"))            //If line ends with "t" then line is "discount"
            x*=1-b;                         //Parse number from line to float, subtract from 1 and multiply by x
        else if(s.EndsWith("n"))            //If line ends with "n" then line is "coupon"
            x-=b;                           //Parse number from line to float and subtract from x
        else if(s.EndsWith("a"))            //If line ends with "a" then line is "extra"
            x+=b;                           //Parse number from line to float and add to x
        else x=b;                           //Line is base price
    }                                       //End foreach
    return x<=0;                            //Return x less than or equal to 0
}                                           //End method

Повинен бути кращий спосіб зробити це, але це принаймні працює


Якщо вам давали поради / знижки як плаваючі, то цього 100у tфілії ви не хочете .
Вай Ха Лі

@WaiHaLee На жаль, забув змінити це на 1
Skidsdev

Порада: покладіть float.Parse(s.Split(' ')[0])щось, щоб зменшити дублювання. Це дозволить заощадити близько 80 символів.
Вай Ха Лі

о, вау, я жахливий гольфіст, я навіть не видалив зайвий пробіл. Я звинувачую Visual Studio.
Skidsdev

Зовсім не погані зусилля!
Вай Ха Лі

1

PowerShell , 218 156 143 байт

($n=$args)|%{[float]$v,$w=$_-split' ';switch -w($w){"t*"{$t+=$v}"d*"{$d+=$v}"e*"{$e+=$v}"c*"{$c+=$v}}};($n[0]*(1+$t/100)*(1-$d/100)+$e-$c)-lt 0

Спробуйте в Інтернеті!

EDIT Збережені байти, попередньо розділивши змінну трубку

EDIT 2 Зберігається друга частина рядка, щоб я міг робити кращі викликові дзвінки


Здається, це працює, і ваш формат введення чудово.
програміст5000

1

Python 133 байт

def f(b):
 t=float(b.pop(0))
 for l in b:
  v,a=l.split(' ');v=float(v);t+={'t':t*v/100,'d':-t*v/100,'c':-v,'e':v}[a[0]]
 return t<=0

Подібно до версії JavaScript ES6. Але перетворення типів потрібно дляfloat значень в Python .

Пояснення:

Витягніть перше значення і перетворіть його в плаваючий.

Для кожного іншого рядка в рахунку:

  1. розділити і перетворити значення в float
  2. Використовуйте a dict щоб вибрати правильну операцію відповідно до першої літери
  3. Накопичуйте значення

Використання:

print(f([
'12.34',
'15 tip',
'25 discount',
'1.5 extra',
'2 coupon'
]))

print(f([
'10',
'20 tip',
'20 discount',
'2 coupon',
'2 coupon',
'1 coupon',
'50 discount',
'2.55 coupon'
]))

Ласкаво просимо на сайт!
DJMcMayhem

1

Java 227 байт

Був певний час і досі немає відповіді Java, яку я бачу, тож ось мій відповідь C #, перенесений на Java, вартістю 8 байт

boolean a(String[] l){Float x=0f;for(String s:l){Float b=Float.parseFloat(s.split(" ")[0]);if(s.endsWith("p"))x*=b;else if(s.endsWith("t"))x*=1-b;else if(s.endsWith("n"))x-=b;else if(s.endsWith("a"))x+=b;else x=b;}return x<=0;}

Пояснення та інше дивіться у моїй відповіді C #

Подібно до цієї відповіді, ця відповідь очікує, що чайові та знижки будуть передані як плаваючі ( 0.15не 15)


Досить добре ... для Java!
програміст5000

1
@ programmer5000, щоб бути справедливим, C # є лише дещо менш багатослівним, ніж Java, основними перевагами є такі речі, як підтримка C # у varродовому типі та лямбдаси (я знаю, що у них є Java, але C # - це гольфіст)
Skidsdev

1

Jq 1,5 , 129 119 114 112 байт

reduce (.[]/" "|.[0]|=tonumber|.[1]|=length)as[$n,$c](0;[$n,0,0,.+.*($n/100),0,.+$n,.-$n,0,.-.*($n/100)][$c])<=0

Розширено

  reduce (
      .[]/" "             # split each element into [value,command] 
    | .[0]|=tonumber      # convert value to number    
    | .[1]|=length        # convert command to length
  ) as [$n,$c]
  (  0
   ; [ $n                 # "" -> set base
     , 0
     , 0
     , .+.*($n/100)       # "tip"
     , 0
     , .+$n               # "extra"
     , .-$n               # "coupon"
     , 0                  
     , .-.*($n/100)       # "discount"
     ][$c]                # ... depending on command length
  ) <=0                   # true if lunch was free

Спробуйте в Інтернеті!

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