Там нет такого понятия, как бесплатный обед


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, поэтому мы выводим false. Мой обед не был бесплатным.

правила

Число 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
programmer5000

Этот ввод чувствителен к регистру? Это все слова, которые мы должны поддержать?
17

@Riker это все необходимые слова, и ввод всегда будет в нижнем регистре.
programmer5000

5
Как работает порядок оценки? Например, если у нас есть скидка, то совет, относится ли этот совет к первоначальной сумме или сумме со скидкой?

Ответы:


2

05AB1E , 37 33 34 байта

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

Попробуйте онлайн!

объяснение

Занимает mod 7трюк от Jone ответа Джанатана Аллана

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: Хороший улов. Сравнение, по-видимому, приведено к целому числу: /
Emigna

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"«extra».

Чтобы добавить правильную сумму к сумме 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 для меня ...
programmer5000

Ах, может быть, я должен сказать, что формат использует десятичный?
Джонатан Аллан

Ой. Да, ты должен.
programmer5000

Я пишу объяснение в МО, вот пример бесплатного обеда.
Джонатан Аллан

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>

Спасибо programmer5000 за все его советы по игре в гольф


Зачем нужен узел?
programmer5000

1
Кроме того, вы можете сделать, {w=i.split`<nl>`где <nl> является буквальным
programmer5000

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

Я добавил фрагмент стека для его тестирования. Не стесняйтесь откат, если вам это не нравится.
programmer5000

1
Вы можете удалить f=часть, это разрешено правилами, и вы можете заменить $.split(' ')на $.split` `.
programmer5000

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 ), поскольку это было разъяснено как приемлемое в комментариях к спецификации.

Explaination:

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.
Скидсдев

Не плохое усилие на всех!
Вай Ха Ли

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

Попробуйте онлайн!

РЕДАКТИРОВАТЬ Сохраненные байты путем предварительного разделения переданной переменной

РЕДАКТИРОВАТЬ 2 Хранить вторую часть строки, чтобы я мог сделать лучше подстановочные вызовы


Кажется, работает, и ваш формат ввода в порядке.
programmer5000

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. Используйте, 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!
programmer5000

1
@ programmer5000, если быть честным, C # лишь немного менее многословен, чем Java, основные преимущества - такие, как поддержка varуниверсального типа в C # и лямбда-выражения (я знаю, что в 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.