没有免费的午餐


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],可以假设顺序吗?
Sinusoid

@StewieGriffin您无法选择顺序。可能多于5行或更少。你可以采取2优惠券为2.00优惠券,并15 tip0.15 tip
programmer5000

此输入是否区分大小写?这是我们需要支持的所有词语吗?
Rɪᴋᴇʀ

@Riker就是所有需要的单词,并且输入将始终为小写。
程序员

5
评估单如何工作?例如,如果我们有折扣,则有小费,小费适用于原始金额还是折扣金额?

Answers:


2

05AB1E37 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:不错。比较显然转换为整数:/
Emigna '17

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()则将返回一个单元素数组,该数组将在应用|运算符时强制为整数,从而使最终测试失败。但是OP确认不会发生这种情况。(将2个或更多元素的数组强制为0。)

演示版


3

CJam45 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

嗯,也许我应该说格式使用十进制?
乔纳森·艾伦,

哦。是的你应该。
程序员

我正在撰写说明,是免费午餐的示例。
乔纳森·艾伦,

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根据是否-找到来调用并产生可读的结果(我们必须对结果求反,因此-暗含“ not free”,否则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提供的所有高尔夫建议


为什么需要节点?
程序员

1
另外,您可以{w=i.split`<nl>`在<nl>是字面换行符的地方进行
程序员

不需要节点。我只是用它在TIO上进行了测试
Alberto Rivera

我添加了一个尝试的堆栈片段。如果您不喜欢,请随时回滚。
程序员

1
您可以删除f=零件,这是规则允许的,也可以替换$.split(' ')$.split` `
程序员

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

regexp为db中的每一行拆分数字和可选文本部分。
计算应该或多或少地避免。请注意:
- -=用于避免将数字与字符串混合的问题
-求和结果被忽略以节省1个字节,因此最后检查是为了>= 0而不是<= 0

PS仍然比@Arnauld的更长。老鼠

测试

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

一定有更好的方法可以做到这一点,但这至少有效


如果为您提供了浮动提示/折扣,那么您不希望100t分支机构中使用。
Wai Ha Lee

@WaiHaLee糟糕,好点,忘记将其更改为1
Skidsdev

提示:放入float.Parse(s.Split(' ')[0])东西以减少重复。这样可以节省大约80个字符。
Wai Ha Lee

噢,我是一个糟糕的高尔夫球手,我什至都没有删除不必要的空格。我怪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

在线尝试!

编辑通过预先分割管道变量来已保存的字节

编辑2存储字符串的第二部分,以便我可以进行更好的通配符调用


似乎可以正常工作,并且您的输入格式还可以。
程序员

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!
程序员

1
@ programmer5000公平地说,C#的详细程度仅低于Java,主要优点是诸如C#对var泛型类型的支持以及lambda(我知道Java具有它们,但C#更具高尔夫精神)
Skidsdev

1

JQ 1.5129个 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

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.