Non esiste un pranzo gratis


17

... o c'è?

La tua sfida è di analizzare il conto del mio pranzo, che contiene il prezzo base, i consigli, gli sconti, i coupon e gli extra e scoprire se il mio pranzo è stato di $ 0 o meno . Se questo è l'input:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Quindi l'output potrebbe essere false. Ecco come funziona:

12.34 è il prezzo base.

15 tipsignifica aggiungere il 15% al ​​totale.

25 discountsignifica sottrarre il 25% dal totale.

1.5 extrasignifica aggiungere 1,5 al totale.

2 couponsignifica sottrarre 2 dal totale.

Potrebbero esserci quantità di suggerimenti, sconti, coupon ed extra, ma ci sarà sempre un prezzo base.

Quindi facciamo (12.34 * 1.15) * 0.75 + 1.5 - 2per un output di 10.14. 10.14 è maggiore di 0, quindi produciamo false. Il mio pranzo non è stato gratuito.

Regole

numero tip significa aggiungere il numero percentuale al totale.

numero discount significa sottrarre il numero percentuale dal totale

numero extra significa aggiungere un numero al totale

numero coupon significa sottrarre il numero dal totale

Un altro esempio:

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

Il prezzo è -0.24((10 * 1,20 * 0,80 - 2 - 2 - 1) * 0,5 - 2,55), quindi l'output è vero (il mio pranzo era gratuito.)

Appunti:

  • La precisione deve essere di almeno 2 decimali.
  • Puoi prendere l'input come una stringa con newline (trailing newline opzionale) o un altro carattere di separazione, o un array / elenco degli input.

5
L'input deve avere il nome o possiamo assumere l'ordine se inseriamo semplicemente un array di numeri [12.34,15,25,1,5,2]?
Sinusoide,

@StewieGriffin Non puoi scegliere l'ordine. Possono esserci più di 5 righe o forse meno. Puoi prendere 2 coupon come 2,00 coupon e 15 tipcome0.15 tip
programmatore5000

Questo input fa distinzione tra maiuscole e minuscole? Sono tutte le parole che dobbiamo sostenere?
Rɪᴋᴇʀ

@Riker sono tutte le parole necessarie e l'input sarà sempre in minuscolo.
programmatore

5
Come funziona l'ordine di valutazione? Ad esempio, se abbiamo uno sconto, quindi un suggerimento, il suggerimento si applica all'importo originale o all'importo scontato?

Risposte:


2

05AB1E , 37 33 34 byte

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

Provalo online!

Spiegazione

Prende in prestito il mod 7trucco dalla risposta Jelly di 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

Ottengo 1quando il valore è <1.
12431234123412341234123,

@ 12431234123412341234123: buona cattura. Il confronto sembra apparentemente intero: /
Emigna,

9

JavaScript (ES6), 88 85 byte

Accetta input come una matrice di stringhe. Restituisce 0gratuitamente o 1gratuitamente.

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

Come funziona

Ogni riga è divisa nello spazio per ottenere a= importo, b= tipo di operazione. Se non è presente alcuna operazione (come nella prima riga), bper impostazione predefinita è impostato "e"su "extra".

Per aggiungere la quantità corretta al totale t, utilizziamo un oggetto le cui chiavi sono la prima lettera dell'operazione:

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

Nota : se il conto fosse costituito da un solo elemento, map()restituirebbe un array a singolo elemento che verrebbe costretto a un numero intero quando applicato |all'operatore, facendo fallire il test finale. Ma l'OP ha confermato che ciò non può accadere. (Le matrici di 2 o più elementi sono costrette a 0.)

dimostrazione


3

CJam , 45 42 byte

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

Prendi l'input come una matrice di stringhe e accetta la punta e lo sconto come decimali.

Provalo online!

Spiegazione

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.

Il codice che viene valutato in base alle prime lettere:

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

Gelatina ,  42 39 byte

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

Prende un elenco di stringhe con numeri in formato decimale
(lo faranno gli zeri iniziali lavorare, ma hanno l'effetto collaterale di stampa di zeri a STDOUT prima il risultato finale).

Provalo online! - non gratis; o gratis .

Come?

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

Emette costantemente 0 per me ...
programmatore

Ah, forse dovrei dire che il formato usa il decimale?
Jonathan Allan,

Oh. Si, dovresti.
programmatore

Sto scrivendo la spiegazione al mese, ecco un esempio di pranzo gratis.
Jonathan Allan,

3

GNU sed + dc, 117 111 107 byte

Usando il -zflag interprete (incluso nel punteggio come 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 /

Spiegazione

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

Dato che l'input è già molto vicino alla notazione polacca inversa, è una questione semplice da trasformare extrae couponin +e -, e non molto altro, per modificare le percentuali in moltiplicatori. Quindi invoca dce produce un risultato leggibile a seconda che- venga trovato (dobbiamo negare il risultato, quindi un -implica "non libero", altrimenti 0 sarebbe un caso speciale che avrebbe bisogno della sua gestione).

Esempio

Il secondo caso della domanda è:

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

Questo diventa questo dcprogramma:

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

Con il risultato di:

free

2

JavaScript, 173 169 145 byte

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

Dovrebbe esserci ancora molto da giocare a golf

Provalo online!(145 byte attualmente)

Provalo:

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

Grazie a programmer5000 per tutti i suoi consigli sul golf


Perché è richiesto il nodo?
programmatore

1
Inoltre, puoi fare {w=i.split`<nl>`dove <nl> è letteralmente una nuova riga
programmatore

Il nodo non è richiesto. L'ho appena usato per i test su TIO
Alberto Rivera il

Ho aggiunto uno snippet di stack per provarlo. Sentiti libero di tornare indietro se non ti piace.
programmatore

1
Puoi rimuovere la f=parte, è consentita dalle regole e puoi sostituirla $.split(' ')con $.split` `.
programmatore

2

JavaScript (ES6), 97 107

Input come una stringa multilinea con una nuova riga finale.

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 divide la parte di testo numerica e facoltativa per ciascuna riga in d e b .
I calcoli dovrebbero essere più o meno ovvi. Solo una nota:
- usando -=per evitare problemi nel mescolare il numero con le stringhe
- la somma viene negata per salvare 1 byte, quindi l'ultimo controllo è >= 0invece di<= 0

PS è ancora molto più lungo di @ Arnauld. Ratti.

Test

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 byte

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

Non è carino, e probabilmente non è il modo migliore, ma eccolo qui. Richiede l'input da passare come array di stringhe e suggerimenti / sconti passati come float ( 0.15 tipanziché15 tip ) in quanto ciò è stato chiarito come accettabile nei commenti della specifica.

spiegazione:

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 esserci un modo migliore per farlo, ma questo funziona almeno


Se ti sono stati dati consigli / sconti come galleggianti, non lo vuoi 100nel tramo.
Wai Ha Lee,

@WaiHaLee oops, buon punto, ho dimenticato di cambiarlo in 1
Skidsdev

Suggerimento: inserisci float.Parse(s.Split(' ')[0])qualcosa per ridurre la duplicazione. Ciò farà risparmiare circa 80 caratteri.
Wai Ha Lee,

oh wow sono un giocatore di golf terribile che non ho nemmeno rimosso gli spazi bianchi non necessari. Incolpo Visual Studio.
Skidsdev,

Non è affatto un brutto sforzo!
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

Provalo online!

MODIFICA byte salvati suddividendo in anticipo la variabile convogliata

EDIT 2 Memorizzato la seconda parte della stringa in modo da poter effettuare chiamate con caratteri jolly migliori


Sembra funzionare e il tuo formato di input va bene.
programmatore

1

Python 133 byte

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

Simile alla versione JavaScript ES6. Ma la conversione del tipo è richiesta per i floatvalori in Python.

Spiegazione:

Estrarre il primo valore e convertirlo in float.

Per ogni altra riga del conto:

  1. dividere e convertire il valore in float
  2. Utilizzare a dictper selezionare l'operazione corretta in base alla prima lettera
  3. Accumula il valore

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

Benvenuti nel sito!
DJMcMayhem

1

Java 227 byte

Sono stato un po 'e ancora nessuna risposta Java che posso vedere, quindi ecco la mia risposta C # trasferita su Java, al costo di 8 byte

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

Per una spiegazione e simili, vedi la mia risposta in C #

Come quella risposta, questa risposta prevede che la punta e lo sconto vengano passati come float ( 0.15non 15)


Abbastanza buono ... per Java!
programmatore

1
@programmer5000 per essere onesti C # è solo leggermente meno dettagliato di Java, i principali vantaggi sono cose come il supporto di C # di vartipo generico e lambdas (so che Java li ha, ma C # sono più golfisti)
Skidsdev

1

Jq 1,5 , 129 119 114 112 byte

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

allargato

  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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.