Não existe almoço grátis


17

... ou existe?

Seu desafio é analisar minha fatura de almoço, que contém o preço base, dicas, descontos, cupons e extras e descobrir se meu almoço foi de US $ 0 ou menos . Se esta é a entrada:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Então a saída pode ser false. Veja como funciona:

12.34 é o preço base.

15 tipsignifica adicionar 15% ao total.

25 discountsignifica subtrair 25% do total.

1.5 extrasignifica adicionar 1,5 ao total.

2 couponsignifica subtrair 2 do total.

Pode haver várias dicas, descontos, cupons e extras, mas sempre haverá um preço base.

Então fazemos (12.34 * 1.15) * 0.75 + 1.5 - 2para uma saída de 10.14. 10.14 é maior que 0, então produzimos false. Meu almoço não foi de graça.

Regras

number tip significa adicionar porcentagem do número ao total.

number discount significa subtrair por cento do número do total

number extra significa adicionar número ao total

number coupon significa subtrair número do total

Outro exemplo:

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

O preço é -0.24((10 * 1,20 * 0,80 - 2 - 2 - 1) * 0,5 - 2,55), portanto a saída é verdadeira (meu almoço foi grátis.)

Notas:

  • A precisão deve ter pelo menos 2 casas decimais.
  • Você pode receber a entrada como uma sequência de caracteres com novas linhas (nova linha à direita opcional) ou outro caractere de separação, ou uma matriz / lista das entradas.

5
A entrada precisa ter o nome ou podemos assumir a ordem se apenas inserirmos uma matriz de números [12.34,15,25,1,5,2]?
Sinusoid

@StewieGriffin Você não pode escolher o pedido. Pode haver mais de 5 linhas ou talvez menos. Você pode pegar 2 cupons como cupom 2,00 e 15 tipcomo0.15 tip
programmer5000

Esta entrada diferencia maiúsculas de minúsculas? Essas são todas as palavras que precisamos apoiar?
Rɪᴋᴇʀ

@Riker são todas as palavras necessárias e a entrada sempre será minúscula.
programmer5000

5
Como funciona a ordem de avaliação? Por exemplo, se tivermos um desconto, uma dica será aplicada ao valor original ou ao valor com desconto?

Respostas:


2

05AB1E , 37 33 34 bytes

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

Experimente online!

Explicação

Empresta o mod 7truque da resposta de Jonathan Allan Jelly

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

Recebo 1quando o valor é <1.
12431234123412341234123

@ 12431234123412341234123: Boa captura. A comparação aparentemente foi convertida para inteiro: /
Emigna 28/04

9

JavaScript (ES6), 88 85 bytes

Recebe entrada como uma matriz de seqüências de caracteres. Retorna 0para não grátis ou 1de graça.

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

Como funciona

Cada linha é dividida no espaço para obter a= quantidade, b= tipo de operação. Se não houver nenhuma operação (como é o caso na primeira linha), bé definido por padrão como "e""extra".

Para adicionar a quantidade correta ao total t, usamos um objeto cujas chaves são a primeira letra da operação:

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

Nota : Se a conta consistisse em apenas um elemento, map()retornaria uma matriz de elemento único que seria coagida a um número inteiro quando aplicado o |operador, fazendo com que o teste final falhasse. Mas o OP confirmou que isso não pode acontecer. (Matrizes de 2 ou mais elementos são coagidas a 0.)

Demo


3

CJam , 45 42 bytes

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

Tome a entrada como uma matriz de seqüências de caracteres e use a dica e o desconto como decimais.

Experimente online!

Explicação

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.

O código que é avaliado dependendo das primeiras letras:

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

Geléia ,  42 39 bytes

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

Recebe uma lista de strings com números decimais formatado
(Zeros irá funcionar, mas têm o efeito secundário de impressão zeros para stdOut antes de o resultado final).

Experimente online! - não é grátis; ou grátis .

Quão?

⁾_@ - 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

Consistentemente saídas 0 para mim ...
programmer5000

Ah, talvez eu deva dizer que o formato usa decimal?
Jonathan Allan

Oh. Sim você deveria.
programmer5000

Estou escrevendo a explicação no momento, aqui está um exemplo de almoço grátis.
Jonathan Allan

3

GNU sed + dc, 117 111 107 bytes

Usando o -zsinalizador de intérprete (incluído na pontuação como 1 byte):

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 /

Explicação

#!/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 /

Como a entrada já está muito próxima da notação polonesa reversa, é uma questão simples de transformar extrae couponpara +e -, e não muito mais, alterar as porcentagens em multiplicadores. Em seguida, invoque dce produza um resultado legível, dependendo de -sua localização (temos que negar o resultado, portanto, -implica "não livre"; caso contrário, 0 seria um caso especial que precisaria de seu próprio tratamento).

Exemplo

O segundo caso da pergunta é:

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

Isso se torna este dcprograma:

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

Resultando em:

free

2

JavaScript, 173 169 145 bytes

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;}

Ainda deve haver muito golfe para fazer

Experimente online!(145 bytes atualmente)

Experimente:

<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>

Obrigado a programmer5000 por todos os seus conselhos sobre golfe


Por que o nó é necessário?
programmer5000

11
Além disso, você pode fazer {w=i.split`<nl>`onde <nl> é um literal de nova linha
programmer5000

O nó não é necessário. Eu apenas o usei para testar no TIO
Alberto Rivera

Adicionei um trecho de pilha para testá-lo. Sinta-se à vontade para reverter se não gostar.
programmer5000

11
Você pode remover a f=peça, isso é permitido pelas regras e pode ser substituído $.split(' ')por $.split` `.
programmer5000

2

JavaScript (ES6), 97107

Insira como uma sequência multilinha com uma nova linha à direita.

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

O regexp divide a parte do texto numérico e opcional para cada linha em d e b .
Os cálculos devem ser mais ou menos óbvios. Apenas algumas notas:
- usando -=para evitar problemas misturando número com strings
- a soma é negada para salvar 1 byte; portanto, a última verificação é para em >= 0vez de<= 0

PS ainda muito mais tempo do que o @ Arnauld. Ratos.

Teste

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 bytes

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;}

Não é bonito e provavelmente não é o melhor caminho, mas aqui está. Requer que a entrada seja passada como uma matriz de seqüências de caracteres e dicas / descontos passados ​​como flutuadores (0.15 tip vez de 15 tip), pois isso foi esclarecido como aceitável nos comentários das especificações.

Explicação:

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

Deve haver uma maneira melhor de fazer isso, mas isso funciona pelo menos


Se você recebeu dicas / descontos como carros alegóricos, não deseja isso 100na tagência.
Wai Ha Lee

@WaiHaLee oops, bom ponto, se esqueceu de mudar isso para 1
Skidsdev

Dica: coloque float.Parse(s.Split(' ')[0])algo para reduzir a duplicação. Isso economizará cerca de 80 caracteres.
Wai Ha Lee

oh uau, sou um péssimo jogador de golfe, nem sequer removi espaços em branco desnecessários. Eu culpo o Visual Studio.
precisa saber é o seguinte

Não é um esforço ruim!
Wai Ha Lee

1

PowerShell , 218 156 143 bytes

($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

Experimente online!

EDITAR bytes salvos dividindo a variável canalizada previamente

EDIT 2 Armazenei a segunda parte da string para que eu pudesse fazer melhores chamadas curinga


Parece funcionar, e seu formato de entrada está correto.
programmer5000

1

Python 133 bytes

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

Semelhante à versão JavaScript ES6. Mas a conversão de tipo é necessária para floatvalores em Python.

Explicação:

Extraia o primeiro valor e converta-o para flutuar.

Para cada outra linha na fatura:

  1. dividir e converter o valor para float
  2. Use a dictpara selecionar a operação correta de acordo com a primeira letra
  3. Acumule o valor

Uso:

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'
]))

Bem vindo ao site!
DJMcMayhem

1

Java 227 bytes

Já faz um tempo e ainda não há resposta Java que eu possa ver, então aqui está minha resposta C # portada para Java, ao custo de 8 bytes

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;}

Para uma explicação e tal, veja minha resposta em C #

Assim, essa resposta espera que a gorjeta e o desconto sejam passados ​​como flutuadores ( 0.15não 15)



11
@ programmer5000 para ser justo C # é apenas um pouco menos detalhada do que Java, principais vantagens que são coisas como C # 's suporte de vartipo genérico, e lambdas (Eu sei que Java tem-los, mas C #' s são Golfier)
Skidsdev

1

Jq 1.5 , 129 119 114 112 bytes

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

Expandido

  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

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.