Tidak ada yang namanya makan siang gratis


17

... atau disana?

Tantangan Anda adalah mengurai tagihan makan siang saya, yang berisi harga dasar, tip, diskon, kupon, dan ekstra dan mencari tahu apakah makan siang saya adalah $ 0 atau kurang . Jika ini input:

12.34
15 tip
25 discount
1.5 extra
2 coupon

Maka hasilnya mungkin false. Begini cara kerjanya:

12.34 adalah harga dasar.

15 tipberarti menambahkan 15% dari total.

25 discountberarti mengurangi 25% dari total.

1.5 extraberarti menambahkan 1,5 ke total.

2 couponberarti mengurangi 2 dari total.

Mungkin ada sejumlah tips, diskon, kupon, dan ekstra, tetapi akan selalu ada satu harga dasar.

Kemudian kita lakukan (12.34 * 1.15) * 0.75 + 1.5 - 2untuk output 10.14. 10.14 lebih besar dari 0, jadi kami menampilkan false. Makan siang saya tidak gratis.

Aturan

angka tip berarti menambahkan angka persen ke total.

angka discount berarti mengurangi angka persen dari total

angka extra berarti menambahkan angka ke total

angka coupon berarti mengurangi angka dari total

Contoh lain:

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

Harganya -0.24((10 * 1,20 * 0,80 - 2 - 2 - 1) * 0,5 - 2,55), jadi hasilnya benar (makan siang saya gratis.)

Catatan:

  • Ketelitian harus minimal 2 angka desimal.
  • Anda dapat mengambil input sebagai string dengan baris baru (mengikuti baris baru opsional) atau karakter pemisahan lain, atau array / daftar input.

5
Apakah input perlu memiliki nama, atau dapatkah kita mengasumsikan pesanan jika kita hanya memasukkan array angka [12,34,15,25,1,5,2]?
Sinusoid

@StewieGriffin Anda tidak dapat memilih pesanan. Mungkin ada lebih dari 5 baris atau mungkin kurang. Anda dapat mengambil 2 kupon sebagai kupon 2,00, dan 15 tipsebagai0.15 tip
programmer5000

Apakah input ini case-sensitive? Apakah itu semua kata yang perlu kita dukung?
Rɪᴋᴇʀ

@Riker itulah kata-kata yang dibutuhkan, dan inputnya selalu huruf kecil.
programmer5000

5
Bagaimana cara kerja urutan evaluasi? Misalnya, jika kita memiliki diskon, maka tip, apakah tip berlaku untuk jumlah asli atau jumlah diskon?

Jawaban:


2

05AB1E , 37 33 34 byte

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

Cobalah online!

Penjelasan

Pinjam mod 7trik dari jawaban Jelly Jonathan Allan's

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

Saya dapatkan 1saat nilainya <1.
12431234123412341234123

@ 12431234123412341234123: Tangkapan bagus. Perbandingannya tampaknya dilemparkan ke integer: /
Emigna

9

JavaScript (ES6), 88 85 byte

Mengambil input sebagai array string. Pengembalian 0tidak gratis atau 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

Bagaimana itu bekerja

Setiap baris dibagi pada ruang untuk mendapatkan a= jumlah, b= jenis operasi. Jika tidak ada operasi sama sekali (yang merupakan kasus di baris pertama), bdiatur secara default ke "e"untuk "ekstra".

Untuk menambahkan jumlah yang benar ke total t, kami menggunakan objek yang kuncinya adalah huruf pertama dari operasi:

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

Catatan : Jika tagihan hanya terdiri dari satu elemen, map()akan mengembalikan array elemen tunggal yang akan dipaksa ke integer ketika diterapkan |operator, membuat tes akhir gagal. Tetapi OP menegaskan bahwa ini tidak bisa terjadi. (Array 2 atau lebih elemen dipaksa ke 0.)

Demo


3

CJam , 45 42 byte

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

Ambil input sebagai array string, dan ambil tip dan diskon sebagai desimal.

Cobalah online!

Penjelasan

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.

Kode yang dievaluasi tergantung pada huruf pertama:

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 byte

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

Mengambil daftar string dengan angka berformat desimal
(Leading nol akan berfungsi, tetapi memiliki efek samping mencetak nol ke STDOUT sebelum hasil akhir).

Cobalah online! - tidak gratis; atau gratis .

Bagaimana?

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

Secara konsisten menghasilkan 0 untuk saya ...
programmer5000

Ah, mungkin saya harus mengatakan formatnya menggunakan desimal?
Jonathan Allan

Oh Ya kamu harus.
programmer5000

Saya menulis penjelasan di mo, di sini adalah contoh makan siang gratis.
Jonathan Allan

3

GNU sed + dc, 117 111 107 byte

Menggunakan -zbendera juru bahasa (termasuk dalam skor 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 /

Penjelasan

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

Karena input sudah sangat dekat dengan notasi Reverse Polish, itu masalah sederhana untuk mengubah extradan couponke +dan -, dan tidak lebih untuk mengubah persentase menjadi pengganda. Kemudian memohon dcdan menghasilkan hasil yang dapat dibaca tergantung pada apakah -ditemukan (kita harus meniadakan hasilnya, sehingga -menyiratkan "tidak gratis", jika 0 akan menjadi kasus khusus yang akan membutuhkan penanganannya sendiri).

Contoh

Kasus kedua dari pertanyaan adalah:

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

Itu menjadi dcprogram ini :

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

Yang menghasilkan:

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

Masih banyak golf yang harus dilakukan

Cobalah online! (145 byte saat ini)

Cobalah:

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

Terima kasih kepada programmer5000 untuk semua saran golfnya


Mengapa simpul dibutuhkan?
programmer5000

1
Selain itu, Anda dapat melakukannya di {w=i.split`<nl>`mana <nl> adalah baris literal
programmer5000

Node tidak diperlukan. Saya hanya menggunakannya untuk pengujian pada TIO
Alberto Rivera

Saya menambahkan cuplikan tumpukan untuk mencobanya. Jangan ragu untuk mengembalikan jika Anda tidak menyukainya.
programmer5000

1
Anda dapat menghapus f=bagian, itu diizinkan oleh aturan, dan Anda dapat menggantinya $.split(' ')dengan $.split` `.
programmer5000

2

JavaScript (ES6), 97 107

Input sebagai string multiline dengan baris baru tambahan.

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 membagi bagian teks numerik dan opsional untuk setiap baris dalam d dan b .
Perhitungannya harus lebih kurang obviuos. Hanya beberapa catatan:
- gunakan -=untuk menghindari masalah pencampuran angka dengan string
- jumlah dinegasikan untuk menghemat 1 byte, jadi cek terakhir adalah untuk >= 0bukan<= 0

PS masih jauh lebih lama dari @ Arnauld. Tikus

Uji

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

Ini tidak cantik, dan mungkin bukan cara terbaik, tapi ini dia. Membutuhkan input yang dilewatkan sebagai string array, dan tip / diskon diluluskan sebagai float ( 0.15 tipbukan 15 tip) karena ini telah diklarifikasi sebagai dapat diterima dalam komentar spec.

Penjelasan:

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

Pasti ada cara yang lebih baik untuk melakukan ini, tetapi ini setidaknya berhasil


Jika Anda telah diberi kiat / diskon sebagai pelampung maka Anda tidak menginginkannya 100di tcabang.
Wai Ha Lee

@WaiHaLee oops, poin bagus, lupa mengubahnya menjadi 1
Skidsdev

Kiat: dimasukkan float.Parse(s.Split(' ')[0])ke dalam sesuatu untuk mengurangi duplikasi. Itu akan menghemat sekitar 80 karakter.
Wai Ha Lee

oh wow saya pegolf yang mengerikan saya bahkan tidak menghapus spasi yang tidak perlu. Saya menyalahkan Visual Studio.
Skidsdev

Bukan upaya yang buruk sama sekali!
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

Cobalah online!

EDIT Bytes yang disimpan dengan memisahkan variabel yang disalurkan sebelumnya

EDIT 2 Menyimpan bagian kedua dari string sehingga saya bisa membuat panggilan wildcard yang lebih baik


Tampaknya berfungsi, dan format input Anda baik-baik saja.
programmer5000

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

Mirip dengan versi JavaScript ES6. Tetapi konversi jenis diperlukan untuk floatnilai dalam Python.

Penjelasan:

Ekstrak nilai pertama dan ubah menjadi float.

Untuk setiap baris lain dalam tagihan:

  1. pisahkan dan konversikan nilainya menjadi float
  2. Gunakan a dictuntuk memilih operasi yang tepat sesuai dengan huruf pertama
  3. Akumulasi nilainya

Pemakaian:

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

Selamat datang di situs ini!
DJMcMayhem

1

Java 227 byte

Sudah lama dan masih tidak ada jawaban Java yang bisa saya lihat, jadi inilah jawaban C # saya porting ke Jawa, dengan biaya 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;}

Untuk penjelasan dan semacamnya, lihat jawaban C # saya

Seperti jawaban itu, jawaban ini mengharapkan agar tip dan diskon diberikan sebagai float ( 0.15bukan 15)


Cukup bagus ... untuk Jawa!
programmer5000

1
@ programmer5000 agar adil C # hanya sedikit lebih sedikit bertele-tele dari Jawa, keuntungan utama adalah hal-hal seperti dukungan C # untuk vartipe generik, dan lambdas (Saya tahu Java memilikinya, tetapi C # lebih pandai golf)
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

Diperluas

  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

Cobalah online!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.