En az sayıda bozuk para kullanarak bir ipucu hesaplayın


23

Çoğu ipucu hesap makinesi uygulaması sadece yemek fiyatının sabit bir yüzdesini alır. Örneğin, yemeğiniz 23,45 dolar ise,% 15 bahşiş = 3,52 dolar veya daha cömert% 20 bahşiş = 4,69 dolar bırakabilirsiniz.

Kredi kartı kullanıcıları için yeterince uygun. Ancak, nakit ipuçlarını bırakmayı tercih ederseniz, bu durumda bu tuhaf yüzde miktarları önler. O halde, nakit kullanıcıları için daha uygun olacak fikrini değiştirelim.

Senin görevin

Giriş olarak alan bir program veya işlevi olabildiğince az sayıda bayt olarak yazın :

  • Yemek fiyatı
  • Minimum bahşiş yüzdesi
  • Maksimum uç yüzdesi

Ve gerekli olan fatura / banknot ve madeni para sayısını en aza indiren [price * min_per% / 100, price * max_per% / 100] aralığında herhangi bir ipucu miktarını çıktı alın.

ABD’nin 1 ¢, 5 ¢, 10 ¢, 25 ¢, 1, 5 $, 10 $, 20 $, 50 $ ve 100 dolar para değerlerini kabul edin.

Örnek

İşte Python'da golf oynamayan bir örnek program:

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

Bazı örnek giriş ve çıkışlar:

~$ 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
Kredi kartı kullanmıyorsanız, nakit olarak ödüyorsunuz, değil mi? Çek + ipucunun toplamı, sadece bahşişle değil, ilgili miktarla aynı olmaz mıydı?
Sparr

4
a program that takes as input (stdin, command-line arguments, or GUI input box, whichever is most convenient in your language)Bu, girişler ve çıkışlar için varsayılan ayarlarımızı geçersiz kılmak için mi tasarlandı? Yani, örneğin üç sayı alan ve sonucu döndüren bir fonksiyona izin verilebilir mi?
Laikoni,

3
Bunu söylerken doğru mu 3.51ve3.75 ayrıca test durumu için geçerli çıktılar 23.45 15 17mı? Aynı miktarda para kullanırlar ve aynı zamanda menzilde de bulunurlar.
Kevin Cruijssen

3
@ Parar Faturayı kartla ödeyen kişiler bile nakit bahşiş bırakmak ister; Bunun için verilen çeşitli sebepler var, bu yüzden onları burada tekrar etmeyeceğim.
Neil

3
@Laikoni: Site varsayılan "programı veya işlevini" kullanma gereksinimlerini düzenlemiştim ve bu nedenle yalnızca işlevsel yanıtları geriye dönük olarak kabul ediyorum.
dan04,

Yanıtlar:


3

Kömür , 60 bayt

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

Çevrimiçi deneyin! Ondalık olarak girdi alır. Bağlantı, kodun ayrıntılı bir versiyonudur. Açıklama:

Nθ

Hesabı girin.

≔×θNη≔×θNζ

Uç ondalık kesirlerini girin ve minumumu ve maksimum ucu hesaplayın.

≔⁰θ

Sıfır ucu ile başlayın.

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

SEKSI dizisi genişleyen 10050.20.10.5.01.0.250.1.05.01ve üç karakterden oluşan gruplara ayrılarak yüzer hale getirilir.

W‹θη≧⁺ιθ

Minimum uca ulaşmak için gerektiği kadar mevcut değeri ekleyin.

¿›θζ≧⁻ιθ»

Maksimum uç aşılmışsa bir mezarı kaldırın.

﹪%.2fθ

Ekran için ucu biçimlendirin.


1
Biçimlendirmenin bir gereklilik olduğunu sanmıyorum (sadece örnek kodun yaptığı bir şey).
Jonathan Allan,

@JonathanAllan Bu durumda yerine 4 bayttan tasarruf edebilirsiniz ﹪%.2f.
Neil,

6

JavaScript (ES6), 93 bayt

(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

Çevrimiçi deneyin!

Nasıl?

Her zaman ilk önce en yüksek değeri deneyerek, kabul edilebilir aralıkta olana kadar bir fatura / jeton değeri toplamını tekrar tekrar hesaplıyoruz.

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

Söz konusu örnek programda basit bir değişiklik. Çıktının artık 2 ondalık basamak gerektirecek şekilde biçimlendirilmediğini unutmayın.

Düzenleme: Jo King'e küçüldüğü için teşekkürler.

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 bayt

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

Minimum ve maksimum yüzdeleri /100ondalık olarak alır (örn . Olduğu 15%gibi 0.15).

İle sorunu gidermek için -1 bayt 3.51Potansiyel çıktı olarak ve aynı anda 1 bayt ile yuvarlama hatalarını düzeltmek için golf yolu.

Çevrimiçi deneyin.

Açıklama:

(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

Sorunun bir program belirttiğinden şu anda bunun teknik olarak geçerli olduğunu sanmıyorum, ancak OP açıklığa kavuştu.
Julurous

1
OP'nin netleştirilmiş fonksiyonlara artık izin verildiğinden, boyutu iki katına çıkarmak için endişelenmenize gerek yok.
Euro

3

Temiz , 207 156 bayt

Şaşırtıcı olmayan bir şekilde, 51 byte tasarruflu bir işleve geçiş.

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

Çevrimiçi deneyin!


2
OP, fonksiyonlara şimdi izin verildiğini açıkladı.
Laikoni,

@Laikoni Haber verdiğiniz için teşekkürler :) Çok fazla bayt kazandırır - tam programlar Temiz'te pahalıdır!
Euro

2

Python ( 264 222 bayt)

Biraz daha golf oynadı.

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]

Çevrimiçi Deneyin!


2

Perl 6 , 93 92 89 bayt

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

Çevrimiçi deneyin!

Üç bağımsız değişken (fiyat, minimum yüzde ve maksimum yüzde) alan ve ipucunu döndüren adsız kod bloğu.



0

Kotlin , 215 bayt

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

Çevrimiçi deneyin!


0

Jöle ,  33  32 bayt

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

Sentetik [cost in cents, [minimum ratio, maximum ratio]]bir ipucu miktarı veren bir listeyi kabul eden monodik bir bağlantı .

Çevrimiçi deneyin!

Nasıl?

İlk satır, verilen tutarı en büyük banknot / madeni paradan daha az veren bir yardımcı Bağlantıdır:

“ñṇ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)

Sıfıra ulaşmak için gereken çağrı sayısı, ipucu miktarlarının aralığını sıralamak için kullanılır ve ardından en soldaki sayı elde edilir:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.