Перечисление проблемы изменения монет с использованием N монет и каждого номинала

13

Проблема смены монет очень хорошо задокументирована. Учитывая бесконечный запас монет номиналов x_1в x_mвам нужно найти число комбинаций , которые добавляют до y. Например, дано x = {1,2,3}и y = 4у нас есть четыре комбинации:

  1. {1,1,1,1}
  2. {1,1,2}
  3. {1,3}
  4. {2,2}

Вступление

Существует несколько вариантов проблемы с обменом монет. В этом варианте у нас есть два дополнительных ограничения:

  1. Каждая деноминация должна использоваться хотя бы один раз.
  2. Точно фиксированное количество монет должно быть использовано в общей сложности.

Например, учитывая x = {1,2,3}, y = 36и n = 15где nобщее количество монет, которые должны быть использованы, мы получаем четыре комбинации:

  1. {1,2,2,2,2,2,2,2,3,3,3,3,3,3,3} (1, 7 двойок, 7 тройок)
  2. {1,1,2,2,2,2,2,3,3,3,3,3,3,3,3} (2, 5 двойок, 8 тройок)
  3. {1,1,1,2,2,2,3,3,3,3,3,3,3,3,3} (3, 3 двойки, 9 тройок)
  4. {1,1,1,1,2,3,3,3,3,3,3,3,3,3,3} (4, 1 двойка, 10 тройка)

Вызов

Задача состоит в том, чтобы написать функцию enumerateна языке по вашему выбору, которая перечисляет все комбинации, как описано выше, с учетом:

  1. Список конфессий. Например {1,5,10,25}. Вы можете использовать списки или массивы.
  2. Неотрицательное целое число, yкоторое обозначает сумму каждой комбинации.
  3. Неотрицательное целое число, nкоторое обозначает общее количество монет.

Порядок аргументов не имеет значения. Точечные функции разрешены.

Выходные данные enumerateфункции должны быть списком комбинаций. Каждая комбинация должна быть уникальной, и это должен быть список nцелых чисел, которые складываются в y. Каждое наименование должно появляться хотя бы один раз в каждой комбинации, и ни одна комбинация не должна отсутствовать. Порядок целых чисел и комбинаций не имеет значения. Вы можете использовать списки или массивы для вывода.

Имейте в виду следующие крайние случаи:

  1. Если оба yи nравны нулю и список наименований пуст, то на выходе получается список из одной комбинации, пустой комбинации (то есть {{}}).
  2. В противном случае, если yноль, nноль или список наименований пуст, то на выходе получается список нулевых комбинаций (т.е. {}).
  3. В более общем смысле, если yменьше, чем сумма достоинств или nменьше, чем число достоинств, то результатом является список нулевых комбинаций.

Оценка будет зависеть от размера всей программы в байтах. Обратите внимание, что это включает в себя enumerateфункцию, вспомогательные функции, операторы импорта и т. Д. Оно не включает тестовые случаи.

Аадит М Шах
источник
Уверен, я где-то видел этот вызов ...
Дрянная Монахиня
Я надеюсь, что этот вопрос не является дубликатом. Я не мог найти тот же вопрос на Code Golf. Следовательно, я отправил это.
Аадит М Шах
@PeterTaylor Если yменьше суммы деноминаций, то в какой-то момент вашего рекурсивного решения вы достигнете базового случая, когда список конфессий пуст. Следовательно, ответ будет {}(т.е. решение не найдено). Если nчисло конфессий меньше, то в конечном итоге вы достигнете базового варианта, где, n = 0но y != 0. Следовательно, ответ снова будет {}.
Аадит М Шах
@PeterTaylor Действительно. Я мог бы предположить слишком много о деталях реализации. Вы знаете, как это исправить?
Аадит М Шах
10
Я предлагаю вам убрать флаг «Принят», пока не получите рабочий ответ. И вообще разумно подождать пару дней, прежде чем принять.
Питер Тейлор

Ответы:

2

05AB1E, 20 байтов

g-¹sã€{Ùvy¹«DO³Qiˆ}¯

Ввод в следующем порядке: list of values, nr of coins, sum to reach.

Объяснение вкратце

  1. Получить все перестановки списка монет длины: final length - length of unique coin list
  2. Добавьте список уникальных монет в эти списки.
  3. Если сумма равна искомой сумме, сохраните список
  4. Вывести все сохраненные списки

Попробуйте онлайн

Онлайн-компилятор не может обрабатывать большое количество монет.

Emigna
источник
4

MATL , 22 байта

Z^!S!Xu!tsi=Z)"1G@m?@!

Порядок ввода: массив номиналов, количество монет ( n), желаемая сумма ( y).

Каждая комбинация отображается в отдельной строке. Пустой вывод отображается в виде пустой строки (поэтому ничего).

Попробуйте онлайн!

Коду не хватает памяти в онлайн-компиляторе для примера в задаче, но работает автономно со стандартным, достаточно современным компьютером:

>> matl
 > Z^!S!Xu!tsi=Z)"1G@m?@!
 > 
> [1 2 3]
> 15
> 36
1 1 1 1 2 3 3 3 3 3 3 3 3 3 3
1 1 1 2 2 2 3 3 3 3 3 3 3 3 3
1 1 2 2 2 2 2 3 3 3 3 3 3 3 3
1 2 2 2 2 2 2 2 3 3 3 3 3 3 3

объяснение

Z^      % Implicitly input array of denomminations and number of coins n. Compute 
        % Cartesian power. This gives 2D array with each "combination"
        % on a different row
!S!     % Sort each row
Xu      % Deduplicate rows
!       % Transpose: rows become columns. Call this array A
ts      % Push a copy, compute sum of each column
i       % Input y (desired sum)
=       % Logical array that contains true if the "combination" has the desired sum
Z)      % Keep only those columns in array A
"       % For each column
  1G    %   Push array of denominations again
  @     %   Push current column
  m     %   Is each denomination present in the column?
  ?     %   If so
    @!  %     Push current column again. Transpose into a row
        %   End if
        % End for
        % Implicitly display stack contents
Луис Мендо
источник
3

Python 3, 120 106 байт

from itertools import*
lambda d,t,l:[i+d for i in combinations_with_replacement(d,l-len(d))if sum(i+d)==t]

Анонимная функция, которая принимает входной (x_1, x_2, x_3 ... , x_k)аргумент из набора деноминаций в форме , целевого значения и количества монет и возвращает список кортежей в форме [(solution_1), (solution_2), (solution_3), ... (solution_k)].

Как это устроено

Itertools«S combinations_with_replacementфункция используется для генерации всех l-len(d)комбинаций, с заменой, из номиналов. Прибавляя dк каждой из этих комбинаций, гарантируется, что каждая купюра появляется хотя бы один раз, и что новая комбинация имеет длину l. Если элементы комбинации суммируются с t, комбинация добавляется в список возврата как кортеж.

Попробуйте это на Ideone


Альтернативный метод для 108 байтов

from itertools import*
lambda d,t,l:set(tuple(sorted(i+d))for i in product(d,repeat=l-len(d))if sum(i+d)==t)

Анонимная функция, которая принимает входной (x_1, x_2, x_3 ... , x_k)аргумент из набора деноминаций формы , целевого значения и количества монет и возвращает набор кортежей формы {(solution_1), (solution_2), (solution_3), ... (solution_k)}.

Как это работает (другая версия)

При этом используется productфункция itertoolsдля создания всех l-len(d)договоренностей деноминаций. Прибавляя dк каждой из этих комбинаций, гарантируется, что каждая купюра появляется хотя бы один раз, и что новая комбинация имеет длину l. Если элементы комбинации суммируются с t, комбинация сортируется, преобразуется из списка в кортеж и добавляется в возвращаемые кортежи. Наконец, вызов setудаляет любые дубликаты.

Попробуйте это на Ideone (другая версия)

TheBikingViking
источник
0

JavaScript (ES6), 135 байт

g=(a,n,y,r)=>n>0?y>0&&a.map((x,i)=>g(a.slice(i),n-1,y-x,[...r,x])):n|y||console.log(r)
(a,n,y)=>g(a,n-a.length,a.reduce((y,x)=>y-x,y),a)
Нил
источник