No hay tal cosa como un almuerzo gratis

17

... o hay?

Su desafío es analizar mi factura de almuerzo, que contiene el precio base, propinas, descuentos, cupones y extras, y averiguar si mi almuerzo fue de $ 0 o menos . Si esta es la entrada:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Entonces la salida podría ser false. Así es como funciona:

12.34 Es el precio base.

15 tipsignifica agregar 15% al ​​total.

25 discountsignifica restar el 25% del total.

1.5 extrasignifica sumar 1.5 al total.

2 couponsignifica restar 2 del total.

Puede haber cualquier cantidad de propinas, descuentos, cupones y extras, pero siempre habrá un precio base.

Luego lo hacemos (12.34 * 1.15) * 0.75 + 1.5 - 2para una salida de 10.14. 10.14 es mayor que 0, por lo que mostramos falso. Mi almuerzo no fue gratis.

Reglas

número tip significa agregar número por ciento al total.

número discount significa restar número por ciento del total

número extra significa agregar número al total

número coupon significa restar número del total

Otro ejemplo:

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

El precio es -0.24((10 * 1.20 * 0.80 - 2 - 2 - 1) * 0.5 - 2.55), por lo que la salida es cierta (mi almuerzo fue gratis).

Notas:

  • La precisión debe ser al menos 2 decimales.
  • Puede tomar la entrada como una cadena con líneas nuevas (línea posterior opcional) u otro carácter de separación, o una matriz / lista de las entradas.
programador 5000
fuente
55
¿La entrada necesita tener el nombre, o podemos asumir el orden si solo ingresamos una matriz de números [12.34,15,25,1.5,2]?
Sinusoid
@StewieGriffin No puede elegir el orden. Puede haber más de 5 filas o quizás menos. Puede tomar 2 cupones como cupón de 2.00 y 15 tipcomo0.15 tip
programmer5000
¿Es esta entrada sensible a mayúsculas y minúsculas? ¿Esas son todas las palabras que necesitamos apoyar?
Rɪᴋᴇʀ
@Riker que son todas las palabras necesarias, y la entrada siempre será en minúsculas.
programmer5000
55
¿Cómo funciona la orden de evaluación? Por ejemplo, si tenemos un descuento, entonces una propina, ¿se aplica la propina al monto original o al monto descontado?

Respuestas:

2

05AB1E , 37 33 34 bytes

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

Pruébalo en línea!

Explicación

Toma prestado el mod 7truco de la respuesta 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
Emigna
fuente
Obtengo 1cuando el valor es <1.
12431234123412341234123
@ 12431234123412341234123: Buena captura. La comparación aparentemente se
convirtió
9

JavaScript (ES6), 88 85 bytes

Toma la entrada como una matriz de cadenas. Devoluciones 0no gratis o 1gratis.

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

Cómo funciona

Cada línea se divide en el espacio para obtener a= cantidad, b= tipo de operación. Si no hay ninguna operación (que es el caso en la primera línea), bse establece de forma predeterminada en "e""extra".

Para agregar la cantidad correcta al total t, usamos un objeto cuyas claves son la primera letra de la operación:

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

Nota : Si la factura constara de un solo elemento, map()devolvería una matriz de un solo elemento que se convertiría en un número entero cuando se aplicara el |operador, haciendo que la prueba final fallara. Pero el OP confirmó que esto no puede suceder. (Las matrices de 2 o más elementos se convierten a 0.)

Manifestación

Arnauld
fuente
3

CJam , 45 42 bytes

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

Toma la entrada como un conjunto de cadenas y toma la propina y el descuento como decimales.

Pruébalo en línea!

Explicación

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.

El código que se evalúa según las primeras 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.
Gato de negocios
fuente
3

Jalea ,  42 39 bytes

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

Toma una lista de cadenas con números con formato decimal
(los ceros iniciales serán trabajará, pero tienen el efecto secundario de la impresión de ceros a la salida estándar antes del resultado final).

Pruébalo en línea! - no gratuito; o gratis .

¿Cómo?

⁾_@ - 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
Jonathan Allan
fuente
Consistentemente produce 0 para mí ...
programmer5000
Ah, ¿tal vez debería decir que el formato usa decimal?
Jonathan Allan
Oh. Si deberías.
programmer5000
Estoy escribiendo la explicación en el mes, aquí hay un ejemplo de un almuerzo gratis.
Jonathan Allan
3

GNU sed + dc, 117 111 107 bytes

Usando el -zindicador de intérprete (incluido en la puntuación 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 /

Explicación

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

Dado que la entrada ya está muy cerca de la notación polaca inversa, es una simple cuestión de transformar extray couponde +y -, y no mucho más que cambiar los porcentajes en multiplicadores. Luego invoque dcy produzca un resultado legible dependiendo de si -se encuentra (tenemos que negar el resultado, entonces un- implica "no libre", de lo contrario 0 sería un caso especial que necesitaría su propio manejo).

Ejemplo

El segundo caso de la pregunta es:

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

Eso se convierte en este dcprograma:

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

Resultando en:

free
Toby Speight
fuente
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;}

Todavía debe haber mucho golf para hacer

Pruébalo en línea! (145 bytes actualmente)

Pruébalo:

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

Gracias a programmer5000 por todos sus consejos de golf.

Alberto Rivera
fuente
¿Por qué se requiere nodo?
programmer5000
1
Además, puede hacer {w=i.split`<nl>`donde <nl> es una nueva línea literal
programmer5000
No se requiere nodo. Lo acabo de usar para probar en TIO
Alberto Rivera
Agregué un fragmento de pila para probarlo. Siéntase libre de retroceder si no le gusta.
programmer5000
1
Puede eliminar la f=pieza, está permitido por las reglas y puede reemplazar $.split(' ')con $.split` `.
programmer5000
2

JavaScript (ES6), 97107

Ingrese como una cadena multilínea con una nueva línea final.

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

La expresión regular divide la parte de texto numérico y opcional para cada línea en d y b .
Los cálculos deberían ser más o menos obviuos. Solo una nota:
- -=para evitar problemas al mezclar números con cadenas
- la suma se niega para guardar 1 byte, por lo que la última comprobación es en >= 0lugar de<= 0

PD todavía mucho más que @ Arnauld's. Ratas

Prueba

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

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

No es bonito, y probablemente no sea la mejor manera, pero aquí está. Requiere que la entrada se pase como una matriz de cadenas, y los consejos / descuentos se pasen como flotantes (en 0.15 tiplugar de15 tip ) ya que esto se ha aclarado como aceptable en los comentarios de la especificación.

Explicacion:

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

Tiene que haber una mejor manera de hacer esto, pero esto funciona al menos

Skidsdev
fuente
Si le han dado propinas / descuentos como flotadores, entonces no quiere eso 100en la tsucursal.
Wai Ha Lee
@WaiHaLee oops, buen punto, olvidé cambiar eso a 1
Skidsdev
Consejo: poner float.Parse(s.Split(' ')[0])en algo para reducir la duplicación. Eso ahorrará unos 80 caracteres.
Wai Ha Lee
oh wow, soy un golfista terrible, ni siquiera eliminé espacios en blanco innecesarios. Yo culpo a Visual Studio.
Skidsdev
¡No es un mal esfuerzo en absoluto!
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

Pruébalo en línea!

EDITAR bytes guardados dividiendo la variable canalizada de antemano

EDITAR 2 Almacenado la segunda parte de la cadena para poder hacer mejores llamadas comodín

Sinusoide
fuente
Parece funcionar, y su formato de entrada está bien.
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

Similar a la versión JavaScript ES6. Pero se requiere conversión de tipo parafloat valores en Python.

Explicación:

Extraiga el primer valor y conviértalo en flotante.

Para cada otra línea en la factura:

  1. dividir y convertir el valor a float
  2. Utilizar una dict para seleccionar la operación correcta de acuerdo con la primera letra
  3. Acumula el 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'
]))
Laurent LAPORTE
fuente
Bienvenido al sitio!
DJMcMayhem
1

Java 227 bytes

Ha pasado un tiempo y todavía no puedo ver la respuesta de Java, así que aquí está mi respuesta de C # portada a Java, a un costo 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 una explicación y tal, vea mi respuesta de C #

Al igual que esa respuesta, esta respuesta espera que la propina y el descuento se pasen como flotantes ( 0.15no 15)

Skidsdev
fuente
Bastante bueno ... para Java!
programador
1
@ programmer5000 para ser justos C # es solo un poco menos detallado que Java, las principales ventajas son cosas como el soporte de vartipo genérico de C # y lambdas (sé que Java los tiene, pero C # es más golfista)
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

Pruébalo en línea!

jq170727
fuente