Nie ma czegoś takiego jak darmowy lunch


17

... czy jest tam?

Wyzwanie polega na przeanalizowaniu rachunku za lunch, który zawiera cenę podstawową, porady, rabaty, kupony i dodatki oraz sprawdzenie, czy mój lunch wynosił 0 USD lub mniej . Jeśli to jest dane wejściowe:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Wtedy wyjście może być false. Oto jak to działa:

12.34 to cena bazowa.

15 tipoznacza dodanie 15% do całości.

25 discountoznacza odjęcie 25% od całości.

1.5 extraoznacza dodanie 1,5 do całości.

2 couponoznacza odjęcie 2 od sumy.

Może być dowolna liczba porad, rabatów, kuponów i dodatków, ale zawsze będzie jedna cena bazowa.

Następnie robimy (12.34 * 1.15) * 0.75 + 1.5 - 2dla wyniku 10.14. 10.14 jest większe niż 0, więc wyprowadzamy false. Mój lunch nie był darmowy.

Zasady

liczba tip oznacza dodanie liczby procentowej do sumy.

liczba discount oznacza odjęcie procentu liczbowego od sumy

liczba extra oznacza dodanie liczby do sumy

liczba coupon oznacza odjęcie liczby od sumy

Inny przykład:

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

Cena wynosi -0.24((10 * 1,20 * 0,80 - 2 - 2 - 1) * 0,5 - 2,55), więc wynik jest prawdziwy (mój lunch był bezpłatny).

Uwagi:

  • Dokładność musi wynosić co najmniej 2 miejsca po przecinku.
  • Możesz przyjmować dane wejściowe jako ciąg znaków z nowymi liniami (opcjonalny znak nowej linii) lub inny znak separacji albo tablicę / listę danych wejściowych.

5
Czy dane wejściowe muszą mieć nazwę, czy możemy przyjąć kolejność, jeśli wprowadzimy tablicę liczb [12.34,15,25,1, 5,2]?
Sinusoid

@StewieGriffin Nie możesz wybrać zamówienia. Może być więcej niż 5 rzędów lub może mniej. Możesz wziąć 2 kupony jako kupon 2.00, a 15 tipjako0.15 tip
programator5000

Czy w danych wejściowych rozróżniana jest wielkość liter? Czy to wszystkie słowa, które musimy wesprzeć?
Rɪᴋᴇʀ

@Riker to wszystkie potrzebne słowa, a dane wejściowe zawsze będą pisane małymi literami.
programator5000

5
Jak działa kolejność oceny? Na przykład, jeśli mamy zniżkę, to napiwek, czy napiwek dotyczy pierwotnej kwoty lub kwoty obniżonej?

Odpowiedzi:


2

05AB1E , 37 33 34 bajtów

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

Wypróbuj online!

Wyjaśnienie

Pożycza mod 7sztuczkę od odpowiedzi Jelly'ego Allana

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

Otrzymuję, 1gdy wartość wynosi <1.
12431234123412341234123 28.04.17

@ 12431234123412341234123: Dobry połów. Porównanie najwyraźniej zostało
przeniesione

9

JavaScript (ES6), 88 85 bajtów

Pobiera dane wejściowe jako tablicę ciągów. Zwraca 0za darmo lub 1za darmo.

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

Jak to działa

Każda linia jest podzielona na spację, aby uzyskać a= ilość, b= rodzaj operacji. Jeśli w ogóle nie ma żadnej operacji (co ma miejsce w pierwszym wierszu), bdomyślnie jest ustawione "e"na „dodatkowe”.

Aby dodać poprawną kwotę do sumy t, używamy obiektu, którego klucze są pierwszą literą operacji:

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

Uwaga : Gdyby rachunek składał się tylko z jednego elementu, map()zwróciłby tablicę jednoelementową, która byłaby wymuszona na liczbę całkowitą po zastosowaniu |operatora, co spowodowałoby niepowodzenie ostatniego testu. Ale PO potwierdziło, że tak się nie stanie. (Tablice 2 lub więcej elementów są wymuszane na 0.)

Próbny


3

CJam , 45 42 bajtów

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

Weź dane wejściowe jako tablicę ciągów, a wskazówkę i zniżkę jako dziesiętne.

Wypróbuj online!

Wyjaśnienie

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.

Kod oceniany w zależności od pierwszych liter:

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

Galaretka ,  42 39 bajtów

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

Pobiera listę ciągów liczb dziesiętnych sformatowanych
(zera wiodące będą działać, ale będą miały efekt uboczny drukowania zer na STDOUT przed końcowym wynikiem).

Wypróbuj online!- nie darmowy; lub za darmo .

W jaki sposób?

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

Konsekwentnie wyprowadza dla mnie 0 ...
programmer5000

Ach, może powinienem powiedzieć, że format używa dziesiętnych?
Jonathan Allan

O. Tak, powinieneś.
programator5000

Wyjaśniam wyjaśnienie w poniedziałek, oto przykład darmowego lunchu.
Jonathan Allan

3

GNU sed + dc, 117 111 107 bajtów

Używając -zflagi interpretera (zawartej w wyniku jako 1 bajt):

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 /

Wyjaśnienie

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

Ponieważ wejście jest już bardzo blisko do notacji polskiej tyłu, jest to prosta sprawa, aby przekształcić extrai couponna +i -, a nie o wiele więcej do zmiany procentowe w mnożników. Następnie wywołaj dci wygeneruj czytelny wynik w zależności od tego, czy -zostanie znaleziony (musimy zanegować wynik, więc -implikuje „nie za darmo”, w przeciwnym razie 0 byłoby szczególnym przypadkiem, który wymagałby własnej obsługi).

Przykład

Drugi przypadek z pytania to:

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

To staje się tym dcprogramem:

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

Wynikające z:

free

2

JavaScript, 173 169 145 bajtów

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

W golfa powinno być jeszcze wiele do zrobienia

Wypróbuj online!(Obecnie 145 bajtów)

Wypróbuj to:

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

Dzięki programmer5000 za wszystkie porady dotyczące gry w golfa


Dlaczego wymagany jest węzeł?
programator5000

1
Możesz także zrobić, {w=i.split`<nl>`gdzie <nl> jest dosłownie nową linią
programista

Węzeł nie jest wymagany. Właśnie użyłem go do testowania na TIO
Alberto Rivera

Do wypróbowania dodałem fragment kodu stosu. Zapraszam do wycofania, jeśli Ci się nie podoba.
programator5000

1
Można usunąć f=część, jest to dozwolone przez przepisy, a można zastąpić $.split(' ')z $.split` `.
programator5000

2

JavaScript (ES6), 97 107

Wprowadź jako ciąg multilinii z końcowym znakiem nowej linii.

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

Tego wyrażenia rozdziela numerycznych opcjonalną część tekstu dla każdej linii d i b .
Obliczenia powinny być mniej lub bardziej obviuos. Tylko kilka uwag:
- używając, -=aby uniknąć problemów z pomieszaniem liczb z łańcuchami
- suma jest negowana, aby zapisać 1 bajt, więc ostatnia kontrola dotyczy>= 0 zamiast<= 0

PS wciąż znacznie dłużej niż @ Arnauld's. Szczury

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 bajtów

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

To nie jest ładne i prawdopodobnie nie najlepszy sposób, ale oto jest. Wymaga, aby dane wejściowe były przekazywane jako tablica ciągów, a porady / rabaty przekazywane jako zmiennoprzecinkowe (0.15 tip zamiast 15 tip), ponieważ zostało to wyjaśnione jako akceptowalne w komentarzach specyfikacji.

Wyjaśnienie:

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

Musi być lepszy sposób, aby to zrobić, ale to przynajmniej działa


Jeśli otrzymałeś porady / rabaty w postaci liczb zmiennoprzecinkowych, to nie chcesz tego 100w toddziale.
Wai Ha Lee

@WaiHaLee ups, dobra uwaga, zapomniałem zmienić to na 1
Skidsdev 28.04.17

Wskazówka: włóż float.Parse(s.Split(' ')[0])coś, aby zmniejszyć powielanie. Dzięki temu zaoszczędzisz około 80 znaków.
Wai Ha Lee

och wow, jestem okropnym golfistą, nawet nie usunąłem niepotrzebnych białych znaków. Obwiniam Visual Studio.
Skidsdev,

Niezły wysiłek!
Wai Ha Lee

1

PowerShell , 218 156 143 bajtów

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

Wypróbuj online!

EDYCJA Zapisane bajty poprzez wcześniejsze podzielenie zmiennej potokowej

EDYCJA 2 Zapisano drugą część ciągu, aby móc wykonywać lepsze połączenia z użyciem symboli wieloznacznych


Wydaje się, że działa, a Twój format wejściowy jest w porządku.
programator5000

1

Python 133 bajty

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

Podobne do wersji JavaScript ES6. Ale dla typu wymagana jest konwersja typufloat wartości w Pythonie.

Wyjaśnienie:

Wyodrębnij pierwszą wartość i przekonwertuj ją na liczbę zmiennoprzecinkową.

Dla każdej innej linii w rachunku:

  1. podzielić i przekonwertować wartość na float
  2. Użyj a, dictaby wybrać właściwą operację zgodnie z pierwszą literą
  3. Zsumuj wartość

Stosowanie:

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

Witamy na stronie!
DJMcMayhem

1

Java 227 bajtów

Minęło trochę czasu i nadal nie widzę odpowiedzi w Javie, więc oto moja odpowiedź w języku C # przeniesiona do Javy, kosztem 8 bajtów

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

Aby uzyskać wyjaśnienie i tym podobne, zobacz moją odpowiedź w języku C #

Podobnie jak ta odpowiedź, ta odpowiedź oczekuje, że napiwek i zniżka zostaną przekazane jako zmiennoprzecinkowe ( 0.15nie 15)


Całkiem dobrze ... dla Javy!
programista

1
@ programmer5000, aby być uczciwym C # jest tylko nieco mniej gadatliwy niż Java, główne zalety to takie, jak obsługa varstandardowego typu C # i lambdas (wiem, że Java je ma, ale C # są bardziej golfowe)
Skidsdev

1

Jq 1,5 , 129 119 114 112 bajtów

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

Rozszerzony

  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

Wypróbuj online!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.