Розрахуйте чайові, використовуючи найменшу кількість монет


23

Більшість додатків для підрахунків чайових просто приймають рівний відсоток від ціни на їжу. Так, наприклад, якщо ваш прийом їжі становить 23,45 долара, ви можете залишити чайову на 15% = 3,52 долара або більш щедру 20-ти чайову = 4,69 долара.

Досить зручно для користувачів кредитних карт. Але це не так, якщо ви віддаєте перевагу залишити грошові поради, і в цьому випадку ці дивні центри перешкоджають. Тож давайте модифікуємо ідею, щоб бути зручнішою для готівкових користувачів.

Ваше завдання

Напишіть у якомога менше байтах програму чи функцію, яка приймає як вхід:

  • Ціна їжі
  • Мінімальний відсоток чайових
  • Максимальний відсоток чайових

І вивести будь-яку суму чайових в межах [ціна * min_percentage / 100, ціна * max_percentage / 100], що мінімізує кількість необхідних купюр / банкнот та монет.

Припустимо грошові номінали США 1 ¢, 5 ¢, 10 ¢, 25 ¢, 1 1, 5,, 10,, 20 50, 50 and і 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
Якщо ви не користуєтесь кредитною карткою, то ви платите готівкою, правда? Тоді чи не буде загальна сума чека + підказка відповідною сумою, а не лише підказка?
Спарр

4
a program that takes as input (stdin, command-line arguments, or GUI input box, whichever is most convenient in your language)Чи призначено це замінити наші за замовчуванням входи та виходи? Тобто, чи дозволить наприклад функція, яка бере три числа і повертає результат?
Лайконі

3
Чи правильно я це кажу, 3.51а 3.75також є дійсними висновками для тестового випадку 23.45 15 17? Вони використовують однакову кількість монет, а також знаходяться в межах асортименту.
Kevin 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якого розбивається на групи з трьох символів і передається плавати.

W‹θη≧⁺ιθ

Додайте стільки поточного номіналу, скільки потрібно для досягнення мінімальної підказки.

¿›θζ≧⁻ιθ»

Видаліть одну купюру, якщо було перевищено максимальний наконечник.

﹪%.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

Спробуйте в Інтернеті!

Як?

Ми рекурсивно обчислюємо суму значень рахунків / монет, поки вона не потрапить у допустимий діапазон, завжди намагаючись найперше значення.

{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

Пітон 3.x: 266 185 байт

Відверта модифікація моєї прикладної програми у питанні. Зауважте, що вихідні дані більше не форматовані, щоб вимагати 2 знаків після коми.

Редагувати: Завдяки Джо Кінгу за те, що він зменшив розмір.

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

Я не думаю, що це технічно справедливо на даний момент, оскільки питання визначає програму, але ОП не уточнила.
Οurous

1
ОП має уточнені функції, тепер дозволені, тому вам не потрібно турбуватися про подвоєння розміру.
Οurous

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
ОП уточнила, що зараз дозволені функції.
Лайконі

@Laikoni Дякую за те, що повідомили мені :) Економить багато байтів - повні програми дорогі в Clean!
Οurous


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

Монадична посилання, що приймає список, [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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.