[Question]
  [
Most tip calculator apps simply take a flat percentage of the meal price. So, for example, if your meal is $23.45, you can leave a 15% tip = $3.52, or a more generous 20% tip = $4.69.
Convenient enough for credit card users. But not so if you prefer to leave cash tips, in which case these oddball cent amounts get in the way. So let's modify the idea to be more convenient for cash users.
## Your assignment
Write, in as few bytes as possible, **[a program or function](https://codegolf.meta.stackexchange.com/questions/2419/default-for-code-golf-program-function-or-snippet)** that takes as input:
* Price of the meal
* Minimum tip percentage
* Maximum tip percentage
And output any tip amount within the range [price \* min\_percentage / 100, price \* max\_percentage / 100] that minimizes the number of bills/banknotes and coins required.
Assume the US monetary denominations of 1¢, 5¢, 10¢, 25¢, $1, $5, $10, $20, $50, and $100.
## Example
Here is a non-golfed example program in 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)))
```
Some sample input and output:
```
~$ 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
```
  
[Answer]
# JavaScript (ES6), 93 bytes
```
(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
```
[Try it online!](https://tio.run/##dcxBDoIwFATQvadg5y@WT0tLsMTCCTiBcUGgEA1QA41h5dUrie6Ii1lMXmYe9atemvn@dNFkW@M77WGlI62ILqDX4GijuZFbc8UaViXL3WUNx/KKiEcupBAqk0Idb7jY0UCrix7cCZpYR@82Tggh4ZzP2hFgJOaM@cZOix0MDraHDhKBMqUB35IwQg5/lWc7TRUq9dumOw3OyNim4vvsPw "JavaScript (Node.js) – Try It Online")
### How?
We recursively compute a sum of bill/coin values until it falls within the acceptable range, always trying the highest value first.
This is guaranteed to use the minimum amount of bills and coins because for any solution \$\{b\_0,\dots,b\_n\}\$ returned by this algorithm:
* all terms \$b\_0\$ to \$b\_n\$ are required, otherwise the algorithm would have selected \$\{b\_0,\dots,b\_{k-1},x\}\$ with \$x \ge b\_k\$ for some \$0 \le k < n\$
* for any \$0 \le k < n\$ and any \$x \le b\_n\$, \$\{b\_0,\dots,b\_{k-1},b\_k-x,b\_{k+1},\dots,b\_n\}\$ cannot be a solution, otherwise \$\{b\_0,\dots,b\_{n-1}\}\$ would have been selected
* there may exist some \$0 < x < b\_n\$ such that \$\{b\_0,\dots,b\_{n-1},x\}\$ is also valid, but that would not use less bills/coins than the selected solution
The bill/coin values \$c\_n\$ expressed in cents are computed with:
$$\begin{cases}c\_0=10000\\c\_{n+1}=\dfrac{c\_n}{(d\_n+1)/2}\end{cases}$$
where \$(d\_0,\dots,d\_9) = (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
```
[Answer]
# Python 3.x: ~~266~~ 185 bytes
A straightforward modification to my example program in the question. Note that the output is no longer formatted to require 2 decimal places.
**Edit:** Thanks to Jo King for making it smaller.
```
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)
```
[Answer]
# Java 10, ~~186~~ 185 bytes
```
(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);}
```
Takes the minimum and maximum percentages as `/100` decimals (i.e. `15%` as `0.15`).
-1 byte to fix the issue with `3.51` as potential output and golfing the way to fix rounding errors by 1 byte at the same time.
[Try it online.](https://tio.run/##lVJNb9wgEL33V4xWqgRZloA3brol5NbjRlr1GOVAMU5IF2zj8aaV5d@@ZT@qSlHVKBIwM5rHY94Mz2ZnFs/Vj73dmr6HtfFx/ADgI7pUG@vg7hACfMPk4yNYUjXD962Dlp2d8MdZU5WRU9559WjQW7iDCHpPWhbYmi5uxzM0acGQbfRqxTpVN4mEC93OuShUuFlftCrMNReSjp0WCnU4QnYmgf0S3QucSO4fRikEKwUrBJPZYZLxomQ8G5GNkBM93FN4q63Chba0m8@Vr0l3s6HjRncqZeppSg6HFGczntHBIJl95EU9Y4mqaa9Oatr8YFZzFrVrfAUhN4qcmnL/AIaeu/SrRxd4MyBvcwq3kURuSbHkVyUDweXxLASlCi4v4evP1ll0FVxxId5BIK9fEyx5WQJZ8k8CmpSj6xKG3gE@OehNcGBCM0SEpgbb@NiDiRWY5ODF45OPR1wy8dHR/1VRrnie2F8Z5esqpHhDx@ecZ3BgWP67ETLP7viLpv1v)
**Explanation:**
```
(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
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 60 bytes
```
Ｎθ≔×θＮη≔×θＮζ≔⁰θＦＩ⪪”;‴üφ↷Σ↗SEX&¿h'⊟”³«Ｗ‹θη≧⁺ιθ¿›θζ≧⁻ιθ»﹪%.2fθ
```
[Try it online!](https://tio.run/##jU/BagIxED27XzEsFCaQhuzapQdPpYdSqCLaH0g1awbi7ppkW7D022OihwpePAzDe/PmvZmNUW7TKxvjezeMYTHuv7TDA5sVL97TrsNP2muPBw7Xc8Y4mDs0x3@N5JBd297hq/IB14OlgGUlZSNFLUUlRSNkJRJIROoZlRymjDH4LSY/hqwG/ND@nGQSO1fDxXxFOxNwaUfPgS45E2oB35xWIb@TL7nRz6m7Wvgrlo66xPbb0fZYPoi6LfOIzWKsp@KpAVHleo6P3/YE "Charcoal – Try It Online") Takes input as decimals. Link is to verbose version of code. Explanation:
```
Ｎθ
```
Input the bill.
```
≔×θＮη≔×θＮζ
```
Input the tip decimal fractions and compute the minium and maximum tip.
```
≔⁰θ
```
Start with zero tip.
```
ＦＩ⪪”;‴üφ↷Σ↗SEX&¿h'⊟”³«
```
The SEXy string expands to `10050.20.10.5.01.0.250.1.05.01` which is split into groups of three characters and cast to float.
```
Ｗ‹θη≧⁺ιθ
```
Add as many of the current denomination as necessary to reach the minimum tip.
```
¿›θζ≧⁻ιθ»
```
Remove one denomination if the maximum tip has been exceeded.
```
﹪%.2fθ
```
Format the tip for display.
[Answer]
# [Clean](https://github.com/Ourous/curated-clean-linux), ~~207~~ 156 bytes
Swapping to a function saved 51 bytes, unsurprisingly.
```
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
```
[Try it online!](https://tio.run/##JY6xjgIhFEV7v4JCN4wBlkGnm@nWwmSrtWQoyDAqkfcwwpj488ti9hbnnuYmdwqzxQLRLWEmYD0WD/f4yOSU3QGfKzfoVtYw9cZbWfcvTHW1WIVZrZEsJAwJHb06mupe07SAPsfgAn3M0AB1GyqZb5rP2zjeeu4@fM81b4UwhuX4M9tAoBlH6DnYO8nxiFnjdhECt8GYumsPqpyyrd8GslY7se9I2wlJlBSy/E7nYC@p8ON3@XqhBT@lPw "Clean – Try It Online")
[Answer]
# Python (~~264~~ 222 bytes)
Slightly more golfed.
```
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]
```
[Try it Online!](https://tio.run/##bY7BboQgEIbvPAVHRicEtKRlu/oixoNBbdkobgQPfXo7tJtmDw2BYfLNx8/9K31uoT7Ptemk0iiVQUmlomJQI22FlUKj6KJ6Nk4zn8WAHm9wYTzh0diisDgUN8Yz/BARR3QZ8rCFZXPDwhM1nrTCX@P1gFK4NsElNasPwmGC931Kxx64w0iTv41IpcYIpMU2K2NrYVrixLNEKeXajX2OKjXgTyrNOwD28OknCmlBp3t23ncfEhezqGr5YpBLnY9K0fz/SL8@I2OltX@WeUZvUqlM6sd75zc)
[Answer]
# [Perl 6](https://github.com/nxadm/rakudo-pkg), ~~93 92~~ 89 bytes
```
{.01*($^a*$^b+|0...$a*$^c).min:{$!=$_;sum '✐ᎈߐϨǴd
'.ords>>.&{($!%=$_)xx$!/$_}}}
```
[Try it online!](https://tio.run/##K0gtyjH7n1upoJamYKvwv1rPwFBLQyUuUUslLkm7xkBPT08FxE7W1MvNzLOqVlG0VYm3Li7NVVB/NGfCw76O@xPOrzi@JUWSi5VRXS@/KKXYzk5PrVpDRVEVqFCzokJFUV8lvra29n9xYqVCmoaRsZ6JqY6hqY6RgaY1F5qYoTlczNRSz9ISrM4ULmahZ2CgY2gM1vofAA "Perl 6 – Try It Online")
Anonymous code block that takes three arguments (price, minimum percentage, and maximum percentage) and returns the tip.
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 105 bytes
This will give all the solutions with minimal coin count.
```
MinimalBy[NumberDecompose[#,d=100{100,50,20,10,5,1,.25,.10,.05,.01}]&/@Range[Ceiling[#2#],#3#],Tr].d/100&
```
[Try it online!](https://tio.run/##bYy9CsIwFIV3n0IIdLqkSWrQDAVRV0XELWSIbVoDTSq1DiI@e7xDhw4O54ePwwl2vLtgR1/Z1JTp6KMPttu99ekVbm44uKoPj/7pNIG65Ix9UCAZCAYcC3CgQgLFThkm41@T5duLja3Te@c7H1tNBDFACrTrYGid40WWzoOPo260KOhKwpKjBDNm8Yfz9YxLRZWa9nLGN8iK6SP9AA "Wolfram Language (Mathematica) – Try It Online")
[Answer]
# [Kotlin](https://kotlinlang.org), 215 bytes
```
{p:Double,l:Int,h:Int->val d=listOf(10000,5000,2000,1000,500,100,25,10,5,1)
var m=Int.MAX_VALUE
var r=0.0
(Math.ceil(p*l).toInt()..(p*h).toInt()).map{var a=it
var c=0
d.map{c+=a/it
a%=it}
if(c<m){m=c
r=it/100.0}}
r}
```
[Try it online!](https://tio.run/##nVfrbts4Fv6vp2AzSSOlqnxJPd0Y9QDZTnY2QNMOkHQvKIKAlmibiCRqRCqJN8g8zDzKvlj3OyQly0k6O5gAkW3y8Ny@75xDXSuTy/Lr4IC9rwU3ImMLVTOzkpqlKhNsqfIFS1c8z0W5FNNgZUylp4MBbdJeog1Pr8UdRLCfpKoY/NIIbaQq9WD0/dH47TB4z/O0yaGccWZkxRotyyVsCKYLUqwNK5tiLmqmYEvJUgfBmcIqCaf@MLziVaWZlkWVr5nh16RugR1WiToVpeFLQQpIbyF4zqpapiJh5yq2MYk7jpMiZnLB1qqpnRDi3B0fJm8mMS3CWslywW9I92iyZz2Ysd3DZDKOGbnAClUjK6IUtWo0Gw87mTfJ90dJELxX5Y0oJfxholTNcmWNp7XIpIH6OkP4otYJ@2uDsJVhWnmP4LBYIAlGeRdSrlekXcPnkt2uZLqiNUEh4qmybI70MYqd8UI1pdHwzJAwJeGWryl6KDP7Gn5ncrG2GzITnKzMhYsm3bhsfSWzzsng35QorrVclgX2g@CftTTC@sM1W4hbNl8boelHpSA2pwRzRKKWNS8oY4umTIkNsAyoCDYrLcuqMdMgYPj7mYDqQ2dXz2Qpi6aw6d0g7Lb43XNbwXGZMdUYaLaqaNvlhd1KUNqlpSaisi@WHeyAFbK86hFowEbDYcy6XX73ZPfShVKQf/I/CIe0bgg8l3muB3NeXgNdChZOWVKzWvzSSBABLDnWuikskOzzOVAoheH1mmWgDPRyWz6kbPTf32I2ocdoSM@x/b47wv@EPuHq7pgeEzzIEpaGSXDiuB4EfxfAFxznoFr5mgoWFe4roUMJifl5bVaqBB6oLlUjOG5W7Xe9Rj1@x35UDh/s0AlKiSby3gpbNSAMlo1YIgscJFkVwsg0@PHk46ez04/HF6efPp6jTL7AP0rwxD7H9jlqV2KX/PGEvmAFH5dBkAnqCkDxyqb2CmFe2YSGDtwr60o0tdT4jn12BcJ@qoXI1uATIstiXz63qr5GYkvX4TSKBUneynpi1dRCN7mBv0P7k8qiL0UJ2IrMGac/EMF5F7O@e1CVyRsU4ZbT8ZbWqFPizb@abdR5t0xTl37bZUZVxtLwCmwPqXiuLHdjS2ystfSNLZd7Cz5hrVjrJTAMCeMkFTLvKfSl0lfg/G3VPlGwyJWqH2l45ILTMMcE2FLxEfWw2XHFM0OvV9yE@7Jc7EcdKptjgMSWdrgVUfzIv1dsFD0DFtQ/T7Hu5AYcdOvNuXc9Hzd6n42q@/5UrPXhWbQfKbI9KBlSSf5kmz3aHVpxrQqEUBRw/TUmugh6iW9zh0pOeL28@TK6jIJHaD4VGpPQNmBPhQ4hBCPAfP9@mowXD/sJYAH@4Z8nJmgRnCu0R@36lA3RdjfX3NGmft1llW1ZlFW6IiTVmtk5jrGNthK8SYbD/yM1ehtgrk@el5ocJUdHVtckGA2/qewv2GGjQ7I4SoaT4GAQBIMBO7mr4C5a7Q2mKPULP9xyXswzngQYitR9U6F1aLMyRXtt7PDM1e2FrKbsFJmxLFjJ5apdiQDAPQ1N2DjOc5XSpcoqltp0w4e9ZL4D2Ybt5qg75IiGXp25cSHpanDD80ZQ38OXRyNoZjV/WoRP27Zn8e8178jqrFsXoA0xJGfH/7r6x/GHzyd@d9NridXWzb/RfY2jX7eXCso5rnESLm/dG23RkuvhWdezbEIPXB6jxCjYDKMk8f76bZ/Vbj9KCl653G5nl8MGgPYA@usEpY474@2B9uo6cBDgemWvYsbZpTj9WXRI062lfmnYGe5CJ21AktR5sZW6Ra2Ua@TBq92eXC4CF6Y7gQHirA68TdZ6sde58UBWcbTz4HTR3v9JkMakzXYduxnvoieJ9gCwce6gM4bu1LsW86jzaEOCTd56g1aagetrnU9yEfS8a0WDhzCyNXZB@Ge1RIm5a2v7kuLKq@CyDNGi9JQd1zVfvzs3aFPLH6KugD7YYuxdUJUj2Da5AGyvdDy6fvK0NYP7v5MZo2HYC/HX@2rqKzqfUimv6Pn6B1ths62asiVlK2rkf9KXGHWEMsIjCmwJzbZLxxbOjPLVZ/5B3iM8fq62@X1vaTgD8JZ7s2GQ2eX01YwTQ/ge9h4CuQjTd0V0X8zSoJ61wDw8BPXDVxvmBa6qeFvM2tc4N2VePrqP69glxTc6kixc18mkrnLuXkYcqpRJA633vjLydq7NrKEPGGhh9OJFgnPShDtsJ@oI5wQTjVHDXszYYTuozapGvZwCyiXPj@tlQy8wJ3epqAjtsDeEd05LWJRZ7xLPvbx@4S3dtC@U9oZDFr8ML5FcB3K4EQLNL@wLoZcaXbYQbET43ZbIeFvEjdOdPUxT@97C9rK9PWKn@8TJtRR5BmLvJF0UfuhuRuwFNUxnKerpzUuneacd09UmE984HPl6@VTizcGnL6a7BjCk90AA2oMYPWnBgai9SD/g1cCgl4WirlU9ZReECUfCoh7SKBfTmzT@w7@UjyY0bqK4c/Lp9uhtFLfLdmz7U5Onp2hcY/fQ6txcIsNv5M2@SZN3LaeIb44FaIsOevbyZYs51oAiFnrc8li7rU0z/JMo/0Gk/xDav4u4237UhlGgge/Hsvz6Pw "Kotlin – Try It Online")
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~33~~ 32 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
“ñṇzi;’b⁴×H¥\ɓ_>Ƈ-Ṫ
PĊ1¦r/ÇƬL$ÞḢ
```
A monadic link accepting a list `[cost in cents, [minimum ratio, maximum ratio]]` which yields a tip amount in cents.
**[Try it online!](https://tio.run/##AVQAq/9qZWxsef//4oCcw7HhuYd6aTvigJli4oG0w5c6MsmXXMmTXz7Ghy3huaoKUMSKMcKmci/Dh8asTCTDnuG4ov///1s4MDAsIFswLjEzLCAwLjIwXV0 "Jelly – Try It Online")**
### How?
The first line is a helper Link which yields the amount given less the largest denomination note/coin:
```
“ñṇ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)
```
The number of calls required in order to reach zero is used to sort the range of tip amounts, and then the leftmost is yielded:
```
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
```
]