最小数のコインを使用してチップを計算します


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
クレジットカードを使用していない場合は、現金で支払いますか?その場合、check + tipの合計は、単なるチップではなく、関連する量ではないでしょうか?
スパー

4
a program that takes as input (stdin, command-line arguments, or GUI input box, whichever is most convenient in your language)これは、入力および出力のデフォルトをオーバーライドすることを意図していますか?つまり、たとえば、3つの数値を取り、結果を返す関数は許可されますか?
ライコニ

3
アム私はと言うに修正3.51して3.75も、テストケースのための有効な出力ですか23.45 15 17?同じ量のコインを使用し、範囲内にあります。
ケビンCruijssen

3
@Sparrカードで請求書を支払う人でさえ、現金チップを預けるのが好きです。これにはさまざまな理由がありますので、ここでは繰り返しません。
ニール

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、3文字のグループに分割され、フロートにキャストされて展開されます。

W‹θη≧⁺ιθ

最小チップに到達するために必要な数の現在の金種を追加します。

¿›θζ≧⁻ιθ»

最大チップを超えている場合は、1つの単位を削除します。

﹪%.2fθ

表示用にヒントをフォーマットします。


1
書式設定は必須ではないと思います(むしろ、サンプルコードが行うことだけです)。
ジョナサンアラン

@JonathanAllanまあ、その場合、の代わりにを使用して4バイト節約できます﹪%.2f
ニール

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

オンラインでお試しください!

どうやって?

許容範囲内に収まるまで、法案/コインの値の合計を再帰的に計算し、常に最高値を最初に試します。

{b0bn}

  • b0bn{b0bk1バツ}バツbk0k<n
  • 0k<nバツbn{b0bk1bkバツbk+1bn}{b0bn1}
  • 0<バツ<bn{b0bn1バツ}

cn

{c0=10000cn+1=cndn+1/2

d0d9=1343397439

 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

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は明確になっていない。
18

1
OPで関数が許可されるようになったため、サイズを2倍にすることを心配する必要はありません。
18

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私に知らせてくれてありがとう:)多くのバイトを節約します-完全なプログラムはCleanで高価です!
Οurous





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)

ゼロに達するために必要な呼び出しの数は、チップ量の範囲をソートするために使用され、その後、左端が生成されます。

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.