Il n'y a rien de tel qu'un déjeuner gratuit

17

... ou y en a-t-il?

Votre défi consiste à analyser ma facture de déjeuner, qui contient le prix de base, les pourboires, les remises, les coupons et les extras et à savoir si mon déjeuner était de 0 $ ou moins . S'il s'agit de l'entrée:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Ensuite, la sortie pourrait être false. Voici comment ça fonctionne:

12.34 est le prix de base.

15 tipsignifie ajouter 15% au total.

25 discountsignifie soustraire 25% du total.

1.5 extrasignifie ajouter 1,5 au total.

2 couponsignifie soustraire 2 du total.

Il peut y avoir n'importe quel nombre de pourboires, de remises, de coupons et d'extras, mais il y aura toujours un prix de base.

Ensuite, nous faisons (12.34 * 1.15) * 0.75 + 1.5 - 2pour une sortie de 10,14. 10.14 est supérieur à 0, donc nous sortons false. Mon déjeuner n'était pas gratuit.

Règles

nombre tip moyen d'ajouter le numéro pour cent au total.

nombre discount signifie soustraire le nombre pour cent du total

nombre extra signifie ajouter un nombre au total

nombre coupon signifie soustraire le nombre du total

Un autre exemple:

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

Le prix est -0.24((10 * 1,20 * 0,80 - 2 - 2 - 1) * 0,5 - 2,55), donc la sortie est vraie (mon déjeuner était gratuit.)

Remarques:

  • La précision doit être d'au moins 2 décimales.
  • Vous pouvez prendre l'entrée comme une chaîne avec des sauts de ligne (retour à la ligne en option) ou un autre caractère de séparation, ou un tableau / liste des entrées.
programmer5000
la source
5
L'entrée doit-elle avoir le nom, ou pouvons-nous assumer l'ordre si nous entrons simplement un tableau de nombres [12.34,15,25,1.5,2]?
Sinusoid
@StewieGriffin Vous ne pouvez pas choisir la commande. Il peut y avoir plus de 5 lignes ou peut-être moins. Vous pouvez prendre 2 coupon en tant que coupon de 2,00 et en 15 tiptant que0.15 tip
programmer5000
Cette entrée est-elle sensible à la casse? Est-ce tous les mots que nous devons soutenir?
Rɪᴋᴇʀ
@Riker c'est tous les mots nécessaires, et l'entrée sera toujours en minuscules.
programmer5000
5
Comment fonctionne l'ordonnance d'évaluation? Par exemple, si nous avons un rabais, puis un pourboire, le pourboire s'applique-t-il au montant original ou au montant réduit?

Réponses:

2

05AB1E , 37 33 34 octets

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

Essayez-le en ligne!

Explication

Emprunte l' mod 7astuce de la réponse Jelly de Jonathan Allan

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
la source
J'obtiens 1lorsque la valeur est <1.
12431234123412341234123
@ 12431234123412341234123: Bonne capture. La comparaison a apparemment été
convertie
9

JavaScript (ES6), 88 85 octets

Prend l'entrée comme un tableau de chaînes. Retours 0non gratuits ou 1gratuits.

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

Comment ça fonctionne

Chaque ligne est divisée sur l'espace pour obtenir a= montant, b= type d'opération. S'il n'y a aucune opération (ce qui est le cas sur la première ligne), best défini par défaut sur "e""extra".

Pour ajouter le montant correct au total t, nous utilisons un objet dont les clés sont la première lettre de l'opération:

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

Remarque : Si la facture ne comprenait qu'un seul élément, map()elle renverrait un tableau à un seul élément qui serait contraint à un entier lors de l'application par l' |opérateur, ce qui ferait échouer le test final. Mais l'OP a confirmé que cela ne pouvait pas arriver. (Les tableaux de 2 éléments ou plus sont contraints à 0.)

Démo

Arnauld
la source
3

CJam , 45 42 octets

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

Prenez l'entrée comme un tableau de chaînes, et prenez la pointe et l'escompte en décimales.

Essayez-le en ligne!

Explication

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.

Le code qui est évalué en fonction des premières lettres:

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.
Chat d'affaires
la source
3

Gelée ,  42 39 octets

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

Prend une liste de chaînes avec des nombres au format décimal
(zéros de tête vont travailler, mais ont l'effet secondaire de zéros à l' impression STDOUT avant le résultat final).

Essayez-le en ligne! - pas libre; ou gratuit .

Comment?

⁾_@ - 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
la source
Génère systématiquement 0 pour moi ...
programmer5000
Ah, peut-être devrais-je dire que le format utilise des décimales?
Jonathan Allan
Oh. Oui tu devrais.
programmer5000
J'écris l'explication au mo, voici un exemple de déjeuner gratuit.
Jonathan Allan
3

GNU sed + dc, 117 111 107 octets

Utilisation du -zdrapeau d'interprète (inclus dans le score sous la forme d'un octet):

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 /

Explication

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

Étant donné que l'entrée est déjà très proche de la notation polonaise inversée, il est simple de transformer extraet couponde +et -, et pas beaucoup plus de changer les pourcentages en multiplicateurs. Ensuite, invoquez dcet produisez un résultat lisible selon qu'il -est trouvé (nous devons annuler le résultat, donc a -implique "non libre", sinon 0 serait un cas spécial qui aurait besoin de sa propre gestion).

Exemple

Le deuxième cas de la question est:

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

Cela devient ce dcprogramme:

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

Résultant en:

free
Toby Speight
la source
2

JavaScript, 173 169 145 145 octets

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

Il devrait y avoir encore beaucoup de golf à faire

Essayez-le en ligne! (145 octets actuellement)

Essaye le:

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

Merci à programmer5000 pour tous ses conseils de golf

Alberto Rivera
la source
Pourquoi le nœud est-il requis?
programmer5000
1
En outre, vous pouvez faire {w=i.split`<nl>`où <nl> est une nouvelle ligne littérale
programmer5000
Le nœud n'est pas requis. Je viens de l'utiliser pour tester sur TIO
Alberto Rivera
J'ai ajouté un extrait de pile pour l'essayer. N'hésitez pas à revenir en arrière si vous ne l'aimez pas.
programmer5000
1
Vous pouvez supprimer la f=pièce, elle est autorisée par les règles et vous pouvez la remplacer $.split(' ')par $.split` `.
programmer5000
2

JavaScript (ES6), 97 107

Entrée sous forme de chaîne multiligne avec un retour à la ligne de fin.

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

L'expression régulière fractionne la partie texte numérique et facultative pour chaque ligne en d et b .
Les calculs devraient être plus ou moins évidents. Juste une note:
- utiliser -=pour éviter les problèmes de mélange de nombre avec des chaînes
- la somme est annulée pour économiser 1 octet, donc la dernière vérification est pour >= 0au lieu de<= 0

PS est encore bien plus long que celui d'Arnauld. Les rats.

Tester

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
la source
1

C # 324 219 octets

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

Ce n'est pas joli, et ce n'est probablement pas le meilleur moyen, mais le voici. Requiert que l'entrée soit passée sous forme de tableau de chaînes et que les pourboires / remises soient transmis sous forme de flottants ( 0.15 tipau lieu de 15 tip) car cela a été clarifié comme étant acceptable dans les commentaires de la spécification.

Explication:

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

Il doit y avoir une meilleure façon de le faire, mais cela fonctionne au moins

Skidsdev
la source
Si vous avez reçu des pourboires / remises sous forme de flotteurs, vous ne voulez pas cela 100dans la tbranche.
Wai Ha Lee
@WaiHaLee oups, bon point, j'ai oublié de changer cela en 1
Skidsdev
Astuce: mettez float.Parse(s.Split(' ')[0])quelque chose pour réduire la duplication. Cela économisera environ 80 caractères.
Wai Ha Lee
oh wow je suis un terrible golfeur, je n'ai même pas supprimé les espaces inutiles. Je blâme Visual Studio.
Skidsdev
Pas un mauvais effort du tout!
Wai Ha Lee
1

PowerShell , 218 156 143 octets

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

Essayez-le en ligne!

EDIT Octets enregistrés en divisant la variable redirigée au préalable

EDIT 2 Stocké la deuxième partie de la chaîne afin que je puisse faire de meilleurs appels génériques

Sinusoïde
la source
Semble fonctionner, et votre format d'entrée est très bien.
programmer5000
1

Python 133 octets

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

Similaire à la version JavaScript ES6. Mais la conversion de type est requise pour les floatvaleurs en Python.

Explication:

Extrayez la première valeur et convertissez-la en float.

Pour chaque autre ligne de la facture:

  1. diviser et convertir la valeur en float
  2. Utiliser un dict pour sélectionner la bonne opération en fonction de la première lettre
  3. Accumuler la valeur

Usage:

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
la source
Bienvenue sur le site!
DJMcMayhem
1

Java 227 octets

Cela fait un moment et toujours pas de réponse Java que je peux voir, alors voici ma réponse C # portée sur Java, au coût de 8 octets

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

Pour une explication et autres, voir ma réponse C #

Comme cette réponse, cette réponse s'attend à ce que le pourboire et la remise soient transmis sous forme de flotteurs ( 0.15non 15)

Skidsdev
la source
Assez bien ... pour Java!
programmer5000
1
@ programmer5000 pour être juste C # n'est que légèrement moins bavard que Java, les principaux avantages étant des choses comme la prise en charge de vartype générique par C # et les lambdas (je sais que Java en a, mais les C # sont plus golfeurs)
Skidsdev
1

Jq 1.5 , 129 119 114 112 octets

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

Étendu

  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

Essayez-le en ligne!

jq170727
la source