คำนวณทิปโดยใช้จำนวนเหรียญที่น้อยที่สุด


23

แอพเครื่องคิดเลขทิปส่วนใหญ่คิดราคาอาหารเพียงเล็กน้อย ตัวอย่างเช่นหากมื้ออาหารของคุณคือ 23.45 เหรียญคุณสามารถฝาก 15% เคล็ดลับ = $ 3.52 หรืออีก 20% เคล็ดลับ = $ 4.69

สะดวกเพียงพอสำหรับผู้ใช้บัตรเครดิต แต่ไม่เป็นเช่นนั้นหากคุณต้องการฝากเคล็ดลับเงินสดซึ่งในกรณีนี้จำนวนเงินที่ได้จากการจับคู่ลูกบอลเหล่านี้จะเข้าทาง ดังนั้นขอแก้ไขความคิดให้สะดวกยิ่งขึ้นสำหรับผู้ใช้เงินสด

การมอบหมายของคุณ

เขียนโปรแกรมหรือฟังก์ชั่นที่รับเป็นอินพุต: ในไม่กี่ไบต์

  • ราคาของอาหาร
  • เปอร์เซ็นต์เคล็ดลับขั้นต่ำ
  • เปอร์เซ็นต์เคล็ดลับสูงสุด

และส่งออกจำนวนเงินทิปใด ๆ ในช่วง [ราคา * min_percentage / 100, ราคา * max_percentage / 100] ที่ลดจำนวนตั๋วเงิน / ธนบัตรและเหรียญที่ต้องการให้น้อยที่สุด

สมมติว่าสกุลเงินของสหรัฐฯคือ 1 ¢, 5 ¢, 10 ¢, 25 ¢, $ 1, $ 5, $ 10, $ 20, $ 50, และ $ 100

ตัวอย่าง

นี่คือตัวอย่างโปรแกรมที่ไม่ใช่กอล์ฟใน Python:

import math
import sys

# Do the math in cents so we can use integer arithmetic
DENOMINATIONS = [10000, 5000, 2000, 1000, 500, 100, 25, 10, 5, 1]

def count_bills_and_coins(amount_cents):
    # Use the Greedy method, which works on this set of denominations.
    result = 0
    for denomination in DENOMINATIONS:
        num_coins, amount_cents = divmod(amount_cents, denomination)
        result += num_coins
    return result

def optimize_tip(meal_price, min_tip_percent, max_tip_percent):
    min_tip_cents = int(math.ceil(meal_price * min_tip_percent))
    max_tip_cents = int(math.floor(meal_price * max_tip_percent))
    best_tip_cents = None
    best_coins = float('inf')
    for tip_cents in range(min_tip_cents, max_tip_cents + 1):
        num_coins = count_bills_and_coins(tip_cents)
        if num_coins < best_coins:
            best_tip_cents = tip_cents
            best_coins = num_coins
    return best_tip_cents / 100.0

# Get inputs from command-line
meal_price = float(sys.argv[1])
min_tip_percent = float(sys.argv[2])
max_tip_percent = float(sys.argv[3])
print('{:.2f}'.format(optimize_tip(meal_price, min_tip_percent, max_tip_percent)))

ตัวอย่างอินพุตและเอาต์พุตบางตัวอย่าง:

~$ python tipcalc.py 23.45 15 20
4.00
~$ python tipcalc.py 23.45 15 17
3.55
~$ python tipcalc.py 59.99 15 25
10.00
~$ python tipcalc.py 8.00 13 20
1.05

8
หากคุณไม่ได้ใช้บัตรเครดิตแสดงว่าคุณจ่ายเป็นเงินสดใช่ไหม? ยอดรวมเช็ค + ทิปนั้นจะเป็นจำนวนเงินที่เกี่ยวข้องใช่หรือไม่ไม่ใช่แค่ทิป
Sparr

4
a program that takes as input (stdin, command-line arguments, or GUI input box, whichever is most convenient in your language)สิ่งนี้มีวัตถุประสงค์เพื่อแทนที่ค่าเริ่มต้นของเราสำหรับอินพุตและเอาต์พุตหรือไม่ นั่นคือเช่นจะใช้ฟังก์ชันที่ใช้ตัวเลขสามตัวและส่งคืนผลลัพธ์ที่ได้หรือไม่
Laikoni

3
ฉันถูกต้องในการบอกว่า3.51และ3.75ยังเป็นผลลัพธ์ที่ถูกต้องสำหรับกรณีทดสอบ23.45 15 17หรือไม่ พวกเขาใช้เหรียญจำนวนเท่ากันและอยู่ในขอบเขต
Kevin Cruijssen

3
@ Sparr แม้แต่คนที่จ่ายบิลด้วยบัตรก็อยากฝากทิปไว้ มีหลายเหตุผลสำหรับสิ่งนี้ดังนั้นฉันจะไม่พูดซ้ำอีก
Neil

3
@Laikoni: ฉันได้แก้ไขข้อกำหนดในการใช้ "โปรแกรมหรือฟังก์ชั่น" ที่เป็นค่าเริ่มต้นของไซต์ดังนั้นฉันจึงยอมรับคำตอบเฉพาะฟังก์ชันที่มีอยู่ย้อนหลัง
dan04

คำตอบ:


3

ถ่าน 60 ไบต์

Nθ≔×θNη≔×θNζ≔⁰θFI⪪”;‴üφ↷Σ↗SEX&¿h'⊟”³«W‹θη≧⁺ιθ¿›θζ≧⁻ιθ»﹪%.2fθ

ลองออนไลน์! รับอินพุตเป็นทศนิยม การเชื่อมโยงคือการสร้างรหัสเวอร์ชัน คำอธิบาย:

Nθ

ใส่บิล

≔×θNη≔×θNζ

ป้อนเศษส่วนทศนิยมของทิปและคำนวณค่าตะกั่วแดงและทิปสูงสุด

≔⁰θ

เริ่มต้นด้วยศูนย์ทิป

FI⪪”;‴üφ↷Σ↗SEX&¿h'⊟”³«

สตริง SEXy ขยายออก10050.20.10.5.01.0.250.1.05.01ซึ่งแบ่งออกเป็นกลุ่มของอักขระสามตัวและร่ายเพื่อลอย

W‹θη≧⁺ιθ

เพิ่มหน่วยเงินปัจจุบันให้มากเท่าที่จำเป็นเพื่อให้ถึงเคล็ดลับขั้นต่ำ

¿›θζ≧⁻ιθ»

ลบหนึ่งชื่อออกหากเกินคำแนะนำสูงสุด

﹪%.2fθ

จัดรูปแบบเคล็ดลับสำหรับการแสดงผล


1
ฉันไม่คิดว่าการจัดรูปแบบเป็นสิ่งที่ต้องการ (แทนที่จะเป็นเพียงบางอย่างที่โค้ดตัวอย่างทำ)
Jonathan Allan

@JonathanAllan ดีในกรณีที่คุณจะสามารถประหยัด 4 ไบต์โดยใช้แทน ﹪%.2f
Neil

6

JavaScript (ES6), 93 ไบต์

(x,m,M)=>(g=(t,c=1e4)=>t>x*M?0:t<x*m?[...'1343397439'].some(d=>g(t+(c/=-~d/2)))*r:r=t)(0)/100

ลองออนไลน์!

อย่างไร?

เราคำนวณผลรวมของมูลค่าใบเรียกเก็บเงิน / เหรียญซ้ำจนกระทั่งอยู่ในช่วงที่ยอมรับได้และพยายามหาค่าสูงสุดก่อนเสมอ

{b0,,bn}

  • b0bn{b0,,bk1,x}xbk0k<n
  • 0k<nxbn{b0,,bk1,bkx,bk+1,,bn}{b0,,bn1}
  • 0<x<bn{b0,,bn1,x}

cn

{c0=10000cn+1=cn(dn+1)/2

(d0,,d9)=(1,3,4,3,3,9,7,4,3,9)

 n | c(n)  | d(n) | k = (d(n)+1)/2 | c(n+1) = c(n)/k
---+-------+------+----------------+-----------------
 0 | 10000 |   1  | (1+1)/2 = 1    |      10000
 1 | 10000 |   3  | (3+1)/2 = 2    |       5000
 2 |  5000 |   4  | (4+1)/2 = 2.5  |       2000
 3 |  2000 |   3  | (3+1)/2 = 2    |       1000
 4 |  1000 |   3  | (3+1)/2 = 2    |        500
 5 |   500 |   9  | (9+1)/2 = 5    |        100
 6 |   100 |   7  | (7+1)/2 = 4    |         25
 7 |    25 |   4  | (4+1)/2 = 2.5  |         10
 8 |    10 |   3  | (3+1)/2 = 2    |          5
 9 |     5 |   9  | (9+1)/2 = 5    |          1

4

Python 3.x: 266 185 ไบต์

การดัดแปลงโปรแกรมตัวอย่างของฉันตรงไปตรงมาในคำถาม โปรดทราบว่าผลลัพธ์จะไม่ได้รับการจัดรูปแบบอีกต่อไปเพื่อให้มีทศนิยม 2 ตำแหน่ง

แก้ไข:ขอบคุณ Jo King ที่ทำให้มันเล็กลง

import sys
p,m,M,T=*map(float,sys.argv[1:]),0
C=p*M
for t in range(-int(-p*m),int(p*M)+1):
 n,a=0,t
 for d in 1e4,5e3,2e3,1e3,500,100,25,10,5,1:n+=a//d;a%=d
 if n<C:T,C=t,n
print(T/100)

1
การเล่นกอล์ฟอย่างรวดเร็วเพื่อไปถึง185 ไบต์
Jo King

4

Java 10, 186 185 ไบต์

(p,m,M)->{double r=0,t,Q=99,q;for(m*=p+.02;m<M*p;m+=.01){q=0;t=m;for(var c:new double[]{100,50,20,10,5,1,.25,.1,.05,.01})for(;t>=c;t-=c)q++;if(q<Q){Q=q;r=m;}}return"".format("%.2f",r);}

ใช้เปอร์เซ็นต์ขั้นต่ำและสูงสุดเป็น/100ทศนิยม (เช่น15%เป็น0.15)

-1 ไบต์เพื่อแก้ไขปัญหาด้วย3.51ผลลัพธ์ที่เป็นไปได้และการเล่นกอล์ฟวิธีแก้ไขข้อผิดพลาดในการปัดเศษโดย 1 ไบต์ในเวลาเดียวกัน

ลองออนไลน์

คำอธิบาย:

(p,m,M)->{                // Method with three double parameters and String return-type
  double r=0,             //  Result-double, starting at 0
         t,               //  Temp-double
         Q=99,            //  Min amount of coins, starting at 99
         q;               //  Temp-double for the amount of coins
  for(m*=p-.02;m<M*p;     //  Loop in the range [`m*p-0.02`, `M*p`]
           m+=.01){       //  in steps of 0.01 (1 cent) per iteration
                          //  (the -0.02 (minus 2 cents) is to fix rounding errors)
    q=0;                  //   Reset `q` to 0
    t=m;                  //   Reset `t` to the current iteration `m`
    for(var c:new double[]{100,50,20,10,5,1,.25,.1,.05,.01})
                          //   Loop over the coins (largest to smallest)
      for(;t>=c;          //    As long as `t` is larger than or equal to the current coin
          t-=c)           //     Remove the coin from the value `t`
          q++;            //     And increase the quantity-counter by 1
      if(q<Q){            //   If the quantity-counter is smaller than the current smallest
        Q=q;              //    Replace the smallest with the current
        r=m;}}            //    And replace the result with the current `m`
  return"".format("%.2f",r)l;}
                          //  Return the result with 2 decimal places

ฉันไม่คิดว่ามันจะใช้งานได้ในทางเทคนิคในขณะนี้เนื่องจากคำถามระบุโปรแกรม แต่ OP ไม่ได้ชี้แจง
Julurous

1
OP ได้รับอนุญาตให้ใช้งานฟังก์ชั่นชี้แจงได้แล้วดังนั้นคุณไม่ต้องกังวลกับการเพิ่มขนาดเป็นสองเท่า
Julurous

3

ทำความสะอาด , 207 156 ไบต์

การสลับไปยังฟังก์ชันที่บันทึกไว้ที่ 51 ไบต์ไม่น่าแปลกใจ

import StdEnv
d=[10000,2000,1000,500,100,25,10,5,1]
$n u l=snd(hd(sort[(sum[foldl(rem)m(d%(0,i))/k\\k<-d&i<-[-1..]],toReal m)\\m<-map toInt[n*u..n*l]]))/1E2

ลองออนไลน์!


2
OP ชี้แจงว่าฟังก์ชั่นได้รับอนุญาตแล้ว
Laikoni

@Laikoni ขอบคุณที่แจ้งให้เราทราบ :) ประหยัดจำนวนมากไบต์ - โปรแกรมเต็มรูปแบบมีราคาแพงใน Clean!
Julurous


2

Perl 6 , 93 92 89 ไบต์

{.01*($^a*$^b+|0...$a*$^c).min:{$!=$_;sum '✐ᎈߐϨǴd
'.ords>>.&{($!%=$_)xx$!/$_}}}

ลองออนไลน์!

การบล็อกโค้ดแบบไม่ระบุชื่อที่รับอาร์กิวเมนต์สามครั้ง (ราคาเปอร์เซ็นต์ต่ำสุดและเปอร์เซ็นต์สูงสุด) และส่งคืนเคล็ดลับ




0

เจลลี่ ,  33  32 ไบต์

“ñṇzi;’b⁴×H¥\ɓ_>Ƈ-Ṫ
PĊ1¦r/ÇƬL$ÞḢ

ลิงก์ monadic ยอมรับรายการ [cost in cents, [minimum ratio, maximum ratio]]ที่ให้ผลเป็นจำนวนทิปในเซนต์

ลองออนไลน์!

อย่างไร?

บรรทัดแรกคือลิงก์ผู้ช่วยเหลือที่ให้จำนวนเงินที่น้อยกว่าธนบัตร / เหรียญที่ใหญ่ที่สุด:

“ñṇzi;’b⁴×H¥\ɓ_>Ƈ-Ṫ - Link 1, get next lower amount: integer, V
“ñṇzi;’             - base 250 number = 112835839060
       b⁴           - to base 16 = [1,10,4,5,8,10,4,4,5,4]
            \       - cumulative reduce with:       e.g.: 1,10   5,4   10,5   25,8
           ¥        -   last two links as a dyad:
         ×          -     multiply                        10     20    50     200
          H         -     halve                            5     10    25     100
                    - ...yielding: [1,5,10,25,100,500,1000,2000,5000,10000]
             ɓ      - start a new dyadic link with swapped arguments
              _     - subtract (vectorises) ...i.e. [V-1,V-5,V-10,...]
                Ƈ   - filter keep those which satisfy:
                 -  -   literal -1
               >    -   greater than? (i.e. if V-X > -1)
                  Ṫ - tail (tailing an empty list yields 0)

จำนวนการโทรที่ต้องใช้เพื่อให้ถึงศูนย์จะใช้เพื่อเรียงช่วงของจำนวนเงินทิปและจากนั้นจะให้ผลทางซ้ายสุด:

PĊ1¦r/ÇƬL$ÞḢ - Main Link: [cost, [min, max]]
P            - product = [cost*min, cost*max]
   ¦         - sparse application...
  1          - ...to indices: 1
 Ċ           - ...what: ceiling   -> [ceil(cost*min), cost*max]
     /       - reduce by:
    r        -   inclusive range (implicit floor of arguments)
          Þ  - sort by:
         $   -   last two links as a monad:
       Ƭ     -     repeat collecting results until a fixed point is reached:
      Ç      -       last link (1) as a monad  (e.g. 32 -> [32,7,2,1,0])
        L    -     length (i.e. coins/notes required + 1)
           Ḣ - head
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.