O problema de troca de moedas está muito bem documentado. Dada uma fonte infinita de moedas de denominações x_1
para x_m
você precisa encontrar o número de combinações que somam y
. Por exemplo, dado x = {1,2,3}
e y = 4
temos quatro combinações:
{1,1,1,1}
{1,1,2}
{1,3}
{2,2}
Introdução
Existem várias variações do problema de troca de moedas. Nesta variação, temos duas restrições adicionais:
- Toda denominação deve ser usada pelo menos uma vez.
- Exatamente um número fixo de moedas deve ser usado no total.
Por exemplo, dada x = {1,2,3}
, y = 36
e n = 15
onde n
é o número total de moedas que devem ser usados, temos quatro combinações:
{1,2,2,2,2,2,2,2,3,3,3,3,3,3,3}
(1, 7, 7){1,1,2,2,2,2,2,3,3,3,3,3,3,3,3}
(2, 5, 8){1,1,1,2,2,2,3,3,3,3,3,3,3,3,3}
(3, 3, 9){1,1,1,1,2,3,3,3,3,3,3,3,3,3,3}
(4, 1, 2, 3)
Desafio
O desafio é escrever uma função enumerate
no idioma de sua escolha que enumere todas as combinações conforme descrito acima:
- A lista de denominações. Por exemplo
{1,5,10,25}
. Você pode usar listas ou matrizes. - Um número inteiro não negativo
y
que indica a soma de todas as combinações. - Um número inteiro não negativo
n
que indica o número total de moedas.
A ordem dos argumentos não importa. Funções pointfree são permitidas.
A saída da enumerate
função deve ser uma lista de combinações. Cada combinação deve ser única e deve ser uma lista de n
números inteiros que somam y
. Toda denominação deve aparecer pelo menos uma vez em cada combinação e nenhuma combinação deve estar faltando. A ordem dos números inteiros e as combinações não importa. Você pode usar listas ou matrizes para a saída.
Lembre-se dos seguintes casos extremos:
- Se ambos
y
en
são iguais a zero e a lista de denominações está vazia, então a saída é uma lista de uma combinação, a combinação vazio (ou seja{{}}
). - Caso contrário, se
y
for zero,n
for zero ou a lista de denominações estiver vazia, a saída será uma lista de combinações zero (ou seja{}
). - De um modo mais geral, se
y
for menor que a soma das denominações oun
menor que o número de denominações, a saída será uma lista de combinações zero.
A pontuação será baseada no tamanho do programa inteiro em bytes. Observe que isso inclui a enumerate
função, funções auxiliares, instruções de importação, etc. Não inclui casos de teste.
fonte
y
for menor que a soma das denominações, em algum momento da sua solução recursiva, você alcançará o caso base em que a lista de denominações está vazia. Portanto, a resposta será{}
(ou seja, nenhuma solução encontrada). Sen
for menor que o número de denominações, você finalmente alcançará o caso base onden = 0
masy != 0
. Portanto, a resposta será novamente{}
.Respostas:
05AB1E, 20 bytes
A entrada é na ordem:
list of values
,nr of coins
,sum to reach
.Explicação resumida
final length - length of unique coin list
Experimente online
O compilador online não pode lidar com um grande número de moedas.
fonte
MATL , 22 bytes
A ordem de entrada é: matriz de denominações, número de moedas retiradas (
n
), soma desejada (y
).Cada combinação é exibida em uma linha diferente. Saída vazia é exibida como uma sequência vazia (então nada).
Experimente online!
O código fica sem memória no compilador online, por exemplo, no desafio, mas funciona offline com um computador padrão e razoavelmente moderno:
Explicação
fonte
Python 3,
120106 bytesUma função anônima que recebe uma tupla de denominações do formulário
(x_1, x_2, x_3 ... , x_k)
, um valor de destino e um número de moedas via argumento e retorna uma lista de tuplas do formulário[(solution_1), (solution_2), (solution_3), ... (solution_k)]
.Como funciona
Itertools
Acombinations_with_replacement
função de é usada para gerar todas asl-len(d)
combinações, com substituição, das denominações. Ao anexard
a cada uma dessas combinações, é garantido que cada denominação apareça pelo menos uma vez e que a nova combinação tenha comprimentol
. Se os elementos de uma combinação somaremt
, a combinação será adicionada à lista de retorno como uma tupla.Experimente no Ideone
Um método alternativo para 108 bytes
Função anônima que recebe entrada de uma tupla de denominações do formulário
(x_1, x_2, x_3 ... , x_k)
, um valor de destino e um número de moedas via argumento e retorna um conjunto de tuplas do formulário{(solution_1), (solution_2), (solution_3), ... (solution_k)}
.Como funciona (outra versão)
Isso usa a
product
função deitertools
para gerar todos osl-len(d)
arranjos das denominações. Ao anexard
a cada uma dessas combinações, é garantido que cada denominação apareça pelo menos uma vez e que a nova combinação tenha comprimentol
. Se os elementos de uma combinação somamt
, a combinação é classificada, convertida de uma lista em uma tupla e adicionada às tuplas de retorno. Por fim, a chamadaset
remove as duplicatas.Experimente no Ideone (outra versão)
fonte
JavaScript (ES6), 135 bytes
fonte