Es gibt kein kostenloses Mittagessen


17

... oder ist da?

Ihre Herausforderung besteht darin, meine Rechnung für das Mittagessen zu analysieren, die den Grundpreis, Tipps, Rabatte, Gutscheine und Extras enthält, und herauszufinden, ob mein Mittagessen 0 USD oder weniger betrug . Wenn dies die Eingabe ist:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Dann könnte die Ausgabe sein false. So funktioniert das:

12.34 ist der Grundpreis.

15 tipbedeutet, 15% zur Gesamtsumme hinzuzufügen.

25 discountbedeutet, 25% von der Gesamtsumme abzuziehen.

1.5 extrabedeutet, 1,5 zur Gesamtsumme hinzuzufügen.

2 couponbedeutet, 2 von der Summe abzuziehen.

Es kann eine beliebige Anzahl von Trinkgeldern, Rabatten, Gutscheinen und Extras geben, aber es wird immer einen Grundpreis geben.

Dann machen wir (12.34 * 1.15) * 0.75 + 1.5 - 2für eine Ausgabe von 10.14. 10.14 ist größer als 0, daher geben wir false aus. Mein Mittagessen war nicht frei.

Regeln

Zahl tip bedeutet, der Gesamtzahl Prozent hinzuzufügen .

Zahl discount bedeutet, die Zahl in Prozent von der Gesamtsumme abzuziehen

Zahl extra bedeutet , der Gesamtsumme eine Zahl hinzuzufügen

Zahl coupon bedeutet, die Zahl von der Gesamtsumme zu subtrahieren

Ein anderes Beispiel:

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

Der Preis ist -0.24((10 * 1,20 * 0,80 - 2 - 2 - 1) * 0,5 - 2,55), so dass die Ausgabe wahr ist (mein Mittagessen war frei.)

Anmerkungen:

  • Die Genauigkeit muss mindestens 2 Dezimalstellen betragen.
  • Sie können Eingaben als Zeichenfolge mit Zeilenumbrüchen (optional mit Zeilenumbrüchen am Ende) oder einem anderen Trennzeichen oder einem Array / einer Liste der Eingaben übernehmen.

5
Muss die Eingabe den Namen haben, oder können wir die Reihenfolge übernehmen, wenn wir nur ein Array von Zahlen eingeben [12.34,15,25,1.5,2]?
Sinusoid

@StewieGriffin Sie können die Bestellung nicht auswählen. Es können mehr als 5 Zeilen oder weniger vorhanden sein. Sie können 2 Coupons als 2,00 Coupons nehmen und 15 tipals0.15 tip
programmer5000

Unterscheidet diese Eingabe zwischen Groß- und Kleinschreibung? Sind das alle Wörter, die wir unterstützen müssen?
27.

@Riker das sind alle Wörter, die benötigt werden, und die Eingabe wird immer in Kleinbuchstaben erfolgen.
programmer5000

5
Wie funktioniert die Evaluierungsreihenfolge? Wenn wir zum Beispiel einen Rabatt haben, dann ein Trinkgeld, gilt das Trinkgeld für den ursprünglichen Betrag oder den ermäßigten Betrag?

Antworten:


2

05AB1E , 37 33 34 Bytes

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

Probieren Sie es online!

Erläuterung

Leiht sich den mod 7Trick von Jonathan Allans Gelee-Antwort

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

Ich bekomme, 1wenn der Wert <1 ist.
12431234123412341234123

@ 12431234123412341234123: Guter Fang. Der Vergleich anscheinend auf Ganzzahl umgewandelt: /
Emigna

9

JavaScript (ES6), 88-85 Byte

Nimmt Eingaben als ein Array von Zeichenfolgen. Rückgabe 0kostenlos oder 1unfrei.

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

Wie es funktioniert

Jede Zeile wird auf das Leerzeichen aufgeteilt, um a= Betrag, b= Art der Operation zu erhalten. Wenn überhaupt keine Operation ausgeführt wird (was in der ersten Zeile der Fall ist), bist standardmäßig "e""extra" eingestellt.

Um den korrekten Betrag zur Gesamtsumme hinzuzufügen t, verwenden wir ein Objekt, dessen Schlüssel der erste Buchstabe der Operation sind:

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

Hinweis : Wenn die Rechnung nur aus einem Element besteht, wird map()ein Array mit einem einzelnen Element zurückgegeben, das beim Anwenden des |Operators in eine Ganzzahl umgewandelt wird , wodurch der endgültige Test fehlschlägt. Aber das OP hat bestätigt, dass dies nicht passieren kann. (Arrays aus 2 oder mehr Elementen werden zu 0 gezwungen.)

Demo


3

CJam , 45 42 Bytes

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

Nehmen Sie die Eingabe als eine Reihe von Zeichenfolgen und nehmen Sie die Spitze und den Rabatt als Dezimalstellen.

Probieren Sie es online!

Erläuterung

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.

Der Code, der abhängig von den Anfangsbuchstaben ausgewertet wird:

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

Jelly ,  42 39 Bytes

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

Nimmt eine Liste von Strings mit dezimal formatierten Zahlen
(Führende Nullen werden arbeiten, haben aber den Nebeneffekt des Druckens Null auf STDOUT vor dem endgültigen Ergebnis).

Probieren Sie es online! - nicht frei; oder kostenlos .

Wie?

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

Konsequent gibt 0 für mich ...
programmer5000

Ah, vielleicht sollte ich sagen, dass das Format Dezimalzahl verwendet?
Jonathan Allan

Oh. Ja du solltest.
programmer5000

Ich schreibe die Erklärung auf, hier ist ein Beispiel für ein kostenloses Mittagessen.
Jonathan Allan

3

GNU sed + dc, 117 111 107 Bytes

Verwenden des -zInterpreter-Flags (in der Bewertung als 1 Byte enthalten):

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 /

Erläuterung

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

Da die Eingabe der polnischen Umkehrnotation bereits sehr nahe kommt, ist es einfach , die Prozentsätze in Multiplikatoren umzuwandeln extraund couponin +und -und nicht viel mehr zu ändern. Rufen Sie dann auf dcund erzeugen Sie ein lesbares Ergebnis, je nachdem, ob -es gefunden wurde (wir müssen das Ergebnis negieren, also -impliziert a "nicht frei", sonst wäre 0 ein Sonderfall, der eine eigene Behandlung erfordern würde).

Beispiel

Der zweite Fall aus der Frage ist:

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

Das wird dieses dcProgramm:

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

Ergebend:

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

Es sollte noch viel zu golfen geben

Probieren Sie es online! (Derzeit 145 Byte)

Versuch es:

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

Vielen Dank an programmer5000 für all seine Golf-Ratschläge


Warum ist ein Knoten erforderlich?
programmer5000

1
Sie können auch tun, {w=i.split`<nl>`wo <nl> eine wörtliche Newline ist
programmer5000

Knoten ist nicht erforderlich. Ich habe es gerade zum Testen auf TIO
Alberto Rivera am

Ich habe ein Stack-Snippet hinzugefügt, um es auszuprobieren. Fühlen Sie sich frei, ein Rollback durchzuführen, wenn Sie es nicht mögen.
programmer5000

1
Sie können die entfernen f=Teil, es nach den Regeln erlaubt ist, und Sie können ersetzen $.split(' ')mit $.split` `.
programmer5000

2

JavaScript (ES6), 97 107

Eingabe als mehrzeilige Zeichenfolge mit einer nachgestellten Newline.

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

Der reguläre Ausdruck teilt den numerischen und optionalen Textteil für jede Zeile in d und b .
Die Berechnungen sollten mehr oder weniger offensichtlich sein. Nur einige Anmerkung:
- Verwendung -=zur Vermeidung von Problemen Zahl mit Streichern Mischen
- die Summe wird negiert 1 Byte zu speichern, so dass die letzte Prüfung für ist >= 0statt<= 0

PS immer noch viel länger als bei Arnauld. Ratten.

Prüfung

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

Es ist nicht schön und wahrscheinlich auch nicht der beste Weg, aber hier ist es. Erfordert die Übergabe von Eingaben als Zeichenfolgenarray und die Übergabe 0.15 tipvon Tipps / Rabatten 15 tipals Gleitkommazahl ( anstelle von ), da dies in den Kommentaren der Spezifikation als akzeptabel erklärt wurde.

Erklärung:

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

Es muss einen besseren Weg geben, dies zu tun, aber das funktioniert zumindest


Wenn Sie als Float Tipps / Rabatte erhalten haben, möchten Sie das 100in der tFiliale nicht.
Wai Ha Lee

@WaiHaLee oops, guter Punkt, vergessen, das zu ändern 1
Skidsdev

Tipp: Legen Sie float.Parse(s.Split(' ')[0])etwas ein, um Doppelarbeit zu vermeiden. Das spart ungefähr 80 Zeichen.
Wai Ha Lee

oh wow, ich bin ein schrecklicher Golfer, ich habe nicht einmal unnötige Leerzeichen entfernt. Ich beschuldige Visual Studio.
Skidsdev

Gar keine schlechte Anstrengung!
Wai Ha Lee

1

PowerShell , 218 156 143 Byte

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

Probieren Sie es online!

EDIT Gespeicherte Bytes durch vorheriges Aufteilen der Pipe-Variablen

BEARBEITEN 2 Der zweite Teil der Zeichenfolge wurde gespeichert, damit ich bessere Platzhalteranrufe ausführen kann


Scheint zu funktionieren und Ihr Eingabeformat ist in Ordnung.
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

Ähnlich der JavaScript ES6-Version. Für floatWerte in Python ist jedoch eine Typkonvertierung erforderlich .

Erläuterung:

Extrahieren Sie den ersten Wert und konvertieren Sie ihn in float.

Für jede andere Zeile in der Rechnung:

  1. Teilen und konvertieren Sie den Wert in float
  2. Verwenden Sie a dict, um die richtige Operation gemäß dem ersten Buchstaben auszuwählen
  3. Akkumulieren Sie den Wert

Verwendung:

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

Willkommen auf der Seite!
DJMcMayhem

1

Java 227 Bytes

Schon eine Weile und immer noch keine Java-Antwort, die ich sehen kann, also ist hier meine nach Java portierte C # -Antwort zum Preis von 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;}

Eine Erklärung und dergleichen finden Sie in meiner C # -Antwort

Wie diese Antwort erwartet diese Antwort, dass Trinkgeld und Rabatt als Float ( 0.15nicht 15) übergeben werden.


Ziemlich gut ... für Java!
programmer5000

1
@ programmer5000 um fair zu sein C # ist nur etwas weniger ausführlich als Java. Die Hauptvorteile sind die Unterstützung von vargenerischen C # -Typen und Lambdas (ich weiß, Java hat sie, aber C # ist Golfspieler)
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

Erweitert

  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

Probieren Sie es online!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.