Гольф мені трохи грошей в банкоматі


26

Завдання проста. Дайте мені кілька 1000, 500і 100замітки.

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

Виклик

З огляду на кількість 1000, 500і 100потрібно ноти, розрахувати конкретні вилучення , необхідні для отримання по крайней мере , ті багато нотаток. Під час кожного зняття банкомат може виплюнути кожну купюру за такими правилами:

  • Вилучена сума ( A) менша5000
    • Якщо A%1000 == 0, то банкомат прописує 1 500банкноту, 5 100нотаток та 1000нотатки про відпочинок
    • Інакше, якщо A%500 == 0банкомат прописує 5 100нотаток, 1000нотатки про відпочинок
    • Інакше , якщо A%1000 < 500банкомат випльовує floor(A/1000) 1000замітки і відпочинок 100замітки
    • Інакше, якщо A%1000 > 500банкомат прописує floor(A/1000) 1000нотатки, 1 500та 100нотатки про відпочинок
  • Вилучена сума більша, ніж дорівнює 5000
    • Якщо A%1000 == 0, то банкомат прописує 2 500нотатки та 1000нотатки про відпочинок
    • В іншому випадку, A%500 == 0банкомат прописує 1 500банкноту та 1000нотатки про відпочинок
    • Інакше , якщо A%1000 < 500банкомат випльовує floor(A/1000) 1000замітки і відпочинок 100замітки
    • Інакше, якщо A%1000 > 500банкомат прописує floor(A/1000) 1000нотатки, 1 500та 100нотатки про відпочинок

Для уточнення, ось повна таблиця вилучених банкнот на всі можливі суми до 7000(ви можете зняти більше, але згодом шаблон не змінюється). Замовлення таке <1000> <500> <100>:

 100 => 0 0 1                  2500 => 2 0 5                   4800 => 4 1 3
 200 => 0 0 2                  2600 => 2 1 1                   4900 => 4 1 4
 300 => 0 0 3                  2700 => 2 1 2                   5000 => 4 2 0
 400 => 0 0 4                  2800 => 2 1 3                   5100 => 5 0 1
 500 => 0 0 5                  2900 => 2 1 4                   5200 => 5 0 2
 600 => 0 1 1                  3000 => 2 1 5                   5300 => 5 0 3
 700 => 0 1 2                  3100 => 3 0 1                   5400 => 5 0 4
 800 => 0 1 3                  3200 => 3 0 2                   5500 => 5 1 0
 900 => 0 1 4                  3300 => 3 0 3                   5600 => 5 1 1
1000 => 0 1 5                  3400 => 3 0 4                   5700 => 5 1 2
1100 => 1 0 1                  3500 => 3 0 5                   5800 => 5 1 3
1200 => 1 0 2                  3600 => 3 1 1                   5900 => 5 1 4
1300 => 1 0 3                  3700 => 3 1 2                   6000 => 5 2 0
1400 => 1 0 4                  3800 => 3 1 3                   6100 => 6 0 1
1500 => 1 0 5                  3900 => 3 1 4                   6200 => 6 0 2
1600 => 1 1 1                  4000 => 3 1 5                   6300 => 6 0 3
1700 => 1 1 2                  4100 => 4 0 1                   6400 => 6 0 4
1800 => 1 1 3                  4200 => 4 0 2                   6500 => 6 1 0
1900 => 1 1 4                  4300 => 4 0 3                   6600 => 6 1 1
2000 => 1 1 5                  4400 => 4 0 4                   6700 => 6 1 2
2100 => 2 0 1                  4500 => 4 0 5                   6800 => 6 1 3
2200 => 2 0 2                  4600 => 4 1 1                   6900 => 6 1 4
2300 => 2 0 3                  4700 => 4 1 2                   7000 => 6 2 0
2400 => 2 0 4

Список надав Мартін

Ловля

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

Вхідні дані

Введення може бути у будь-якому сприятливому форматі для трьох чисел, що відповідають кількості нотаток, необхідних для значення 1000, 500і 100. Не обов'язково в тому порядку.

Вихідні дані

Вихід - це сума, яка повинна бути знята в кожній транзакції, розділена новим рядком.

Приклади

Введення (формат <1000> <500> <100>):

3 4 1

Вихід:

600
600
600
3600

ще кілька:

7 2 5
5000
3500

1 2 3
600
1700

21 14 2
600
600
600
1600
5000
5000
5000
5000
5000

Припущення

  • Ви можете припустити, що банкомат має нескінченну кількість банкнот від кожної суми.
  • Ви також можете припустити, що ви можете здійснювати будь-яку кількість транзакцій.
  • Крім того, рішення деяких вхідних значень може бути не унікальним, тому ви можете вивести будь-який 1 рішення, який відповідає мінімально можливій кількості та мінімальним необхідним умовам.

Як завжди, ви можете написати повний вхід для читання програми через STDIN / ARGV і друкувати вихід на STDOUT або функцію, що приймає введення через аргументи, і повертає або список цілих чисел, що відповідають сумам, або рядок із сумами, розділеними новим рядком.

Це код-гольф, тому найкоротший код в байтах виграє.


@nutki дійсно. Відредаговано.
Оптимізатор

Чи є обмеження швидкості? Чи повинен останній тестовий випадок 21 14 2закінчитися в розумний час?
Якубе

1
@Jakube У розумний час - так (скажімо, менше ніж 5-6 годин). Але як такої немає обмежень, оскільки це код-гольф.
Оптимізатор

Отже, якщо я зніму 0, це дасть мені п'ять 100 нот?
AJMansfield

@AJMansfield звичайно ні. Ви не можете зняти 0 суму
Оптимізатор

Відповіді:


7

JavaScript, 184 148

function g(a,b,c){x=[];while(a>0||b>0||c>0){i=b<3||a<4?a:4;a-=i;if(i>3&&b>1){b-=2;i++}else{i+=(c--<b&&i>4?0:.1)+(b-->0?.5:0)}x.push(i*1e3)}return x}

http://jsfiddle.net/vuyv4r0p/2/

повертає список цілих чисел, що відповідають сумам зняття


Спробуйте g(5,1,1). Одне краще рішення: 5600.
jimmy23013

має бути виправлено зараз
hoffmale

g(5,1,0), Рішення: 5500.
jimmy23013

це тепер також має бути виправлено ^ дякую за вказівку на це, я повинен бути занадто сонним
hoffmale

g(5,2,0), Рішення: 6000.
jimmy23013

1

Перл 5: 223

Редагувати

Це рішення було зроблено з помилковим припущенням, що 7K - межа банкомату. Це насправді зробило завдання більш цікавим, оскільки воно вимагало динамічного програмування (схема переміщення була досить регулярною, але жорстке кодування, ймовірно, буде довше, ніж обчислення в прямому ефірі, як я). З будь-якою можливою сумою шаблон переміщення настільки регулярний, що жорстко кодувати його тривіально. Я не знаю, чи рішення компанії @hoffmale зараз правильне, але воно буде серед цих рядків. Тож на жаль, це буде ще одне завдання, коли спочатку хтось приходить з рішенням, а потім його переносять на мову для гольфу для виграшу.

Трохи повільніше, ніж оригінальне рішення (але все ж підсекундне для параметрів нижче 100).

#!perl -pa
$c{0,0}=$f=($a,$b,$c)=@F;for$i(0..$b){for$j(0..$a){
/.(?=.$)/>($n=$c{$i-$`,$j-$'})||${$r=\$c{$i,$j}}<($x=$n+$&)&&$$r
or$f=$$r="$x $n".($'.$&+5*$`)."00
"for 204..206,105,106,11..15,110..114}}$_=$f."100
"x($c-$f+3);s/.*\b3//

Швидше 259 розчин.

#!perl -pa
$c{0,0}=($a,$b,$c)=@F;for$i(0..$b){for$j(0..$a){
/\B./<($%=$c{$i-$&,$j-$'}+$`)&&(!${$r=\$c{$i,$j}}||$$r>$%)and$d{$i,$j}=$_,$$r=$%for
qw/024 025 026 015 016/,101..105,110..114}}
$d{$b,$a}=~/\B./,$c-=$`,$b-=$&,$a-=$',print$'.$`+5*$&,"00
"while$a+$b;$_="100
"x$c

Використовує STDIN:

$perl atm.pl <<<"21 14 2"
5000
5000
5000
5000
5000
600
600
600
1600

Спробуйте 10 0 0. Краще рішення: 10100.
jimmy23013

@ user23013 На жаль, я неправильно зрозумів питання. Я припускав, що максимальна сума - 7 к: (сподіваюся, мені вдасться це виправити.
nutki
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.