가장 적은 수의 동전을 사용하여 팁 계산


23

대부분의 팁 계산기 앱은 단순히 식사 가격의 일정 비율을 차지합니다. 예를 들어 식사가 $ 23.45 인 경우 15 % 팁 = $ 3.52 또는보다 관대 한 20 % 팁 = $ 4.69를 남길 수 있습니다.

신용 카드 사용자에게 충분히 편리합니다. 그러나 현금 팁을 남기기를 선호한다면 홀수 센트 금액이 방해가됩니다. 따라서 현금 사용자에게 더 편리하도록 아이디어를 수정합시다.

당신의 임무

입력으로 사용 되는 프로그램 또는 함수 를 가능한 한 적은 바이트로 작성하십시오 .

  • 식사 가격
  • 최소 팁 비율
  • 최대 팁 비율

그리고 필요한 청구서 / 은행권 및 동전의 수를 최소화하는 [price * min_percentage / 100, price * max_percentage / 100] 범위 내의 모든 팁 금액을 출력하십시오.

미국 화폐 단위가 1 ¢, 5 ¢, 10 ¢, 25 ¢, $ 1, $ 5, $ 10, $ 20, $ 50 및 $ 100이라고 가정합니다.

다음은 파이썬에서 골프가 아닌 예제 프로그램입니다.

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
신용 카드를 사용하지 않는다면 현금으로 지불하고 있습니까? 그렇다면 팁뿐만 아니라 총 check + tip이 관련 금액이 아닙니까?
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.513.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)


4

자바 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는 명확하지 않습니다.
OUurous

1
OP는 이제 명확한 기능이 허용되었으므로 크기를 두 배로 늘릴 염려가 없습니다.
OUurous

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에서 비쌉니다!
OUurous

2

파이썬 ( 264222 바이트)

약간 더 골프.

m=[.01,.05,.1,.25,.5,1,5,10,20,50,100]
def f(a,i,j):
 t,u=9**9,a*j
 def g(s,d,c):
  nonlocal t
  if(a*i<s<u)+(c>t):t=min(c,t);return c,s
  return(t+1,s)if(s>u)+(d>9)else min(g(s+m[d],d,c+1),g(s,d+1,c))
 return g(0,0,0)[1]

온라인으로 사용해보십시오!


2

펄 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$ÞḢ

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

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.