Гольф мне немного наличных в банкомате

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/

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

hoffmale
источник
Попробуй g(5,1,1). Одно лучшее решение: 5600.
jimmy23013
должно быть исправлено сейчас
hoffmale
g(5,1,0), Решение: 5500.
jimmy23013
теперь это также должно быть исправлено ^^ спасибо за указание на это, я должен быть слишком сонным
hoffmale
g(5,2,0), Решение: 6000.
jimmy23013
1

Perl 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
nutki
источник
Попробуй 10 0 0. Лучшее решение: 10100.
jimmy23013
@ user23013 Ой, я неправильно понял вопрос. Я предположил, что 7k - это максимальная сумма :( Надеюсь, я смогу это исправить.
nutki