Énumération du problème de changement de pièce en utilisant N pièces et chaque dénomination

13

Le problème de changement de pièces est très bien documenté. Compte tenu d' une offre infinie de pièces de dénominations x_1pour x_mvous devez trouver le nombre de combinaisons qui ajoutent jusqu'à y. Par exemple, étant donné x = {1,2,3}et y = 4nous avons quatre combinaisons:

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

introduction

Il existe plusieurs variantes du problème de changement de pièce. Dans cette variante, nous avons deux restrictions supplémentaires:

  1. Chaque dénomination doit être utilisée au moins une fois.
  2. Exactement, un nombre fixe de pièces doit être utilisé au total.

Par exemple, étant donné x = {1,2,3}, y = 36et n = 15nest le nombre total de pièces qui doivent être utilisées, nous obtenons quatre combinaisons:

  1. {1,2,2,2,2,2,2,2,3,3,3,3,3,3,3} (1 un, 7 deux, 7 trois)
  2. {1,1,2,2,2,2,2,3,3,3,3,3,3,3,3} (2 un, 5 deux, 8 trois)
  3. {1,1,1,2,2,2,3,3,3,3,3,3,3,3,3} (3 un, 3 deux, 9 trois)
  4. {1,1,1,1,2,3,3,3,3,3,3,3,3,3,3} (4 unités, 1 paire, 10 trois)

Défi

Le défi est d'écrire une fonction enumeratedans la langue de votre choix qui énumère toutes les combinaisons décrites ci-dessus étant donné:

  1. La liste des dénominations. Par exemple {1,5,10,25}. Vous pouvez utiliser des listes ou des tableaux.
  2. Un entier non négatif yqui représente la somme de chaque combinaison.
  3. Un entier non négatif nqui indique le nombre total de pièces.

L'ordre des arguments n'a pas d'importance. Les fonctions sans point sont autorisées.

La sortie de la enumeratefonction doit être une liste de combinaisons. Chaque combinaison doit être unique et ce doit être une liste d' nentiers qui s'additionnent y. Chaque dénomination doit apparaître au moins une fois dans chaque combinaison et aucune combinaison ne doit manquer. L'ordre des entiers et des combinaisons n'a pas d'importance. Vous pouvez utiliser des listes ou des tableaux pour la sortie.

Gardez à l'esprit les cas de bord suivants:

  1. Si les deux yet nsont nuls et que la liste des dénominations est vide, la sortie est une liste d'une combinaison, la combinaison vide (c'est-à-dire {{}}).
  2. Sinon, si yest zéro, nest nul ou la liste des dénominations est vide alors la sortie est une liste de combinaisons nulles (ie {}).
  3. Plus généralement, si yest inférieur à la somme des dénominations ou nest inférieur au nombre de dénominations, alors la sortie est une liste de combinaisons nulles.

La notation sera basée sur la taille de l'ensemble du programme en octets. Notez que cela inclut la enumeratefonction, les fonctions d'assistance, les instructions d'importation, etc. Cela n'inclut pas les cas de test.

Aadit M Shah
la source
Je suis presque sûr d'avoir vu ce défi quelque part ...
Leaky Nun
J'espère que cette question n'est pas un doublon. Je n'ai pas pu trouver la même question sur Code Golf. Par conséquent, je l'ai posté.
Aadit M Shah
@PeterTaylor Si yest inférieur à la somme des dénominations, à un moment donné de votre solution récursive, vous atteindrez le cas de base où la liste des dénominations est vide. Par conséquent, la réponse sera {}(c.-à-d. Aucune solution trouvée). Si nest inférieur au nombre de dénominations, vous finirez par atteindre le cas de base où n = 0mais y != 0. Par conséquent, la réponse sera à nouveau {}.
Aadit M Shah
@PeterTaylor En effet. J'aurais peut-être trop pensé aux détails de la mise en œuvre. Souhaitez-vous savoir comment résoudre ce problème?
Aadit M Shah
10
Je vous suggère de supprimer le drapeau "Accepté" jusqu'à ce que vous obteniez une réponse satisfaisante. Et en général, il est raisonnable d'attendre quelques jours avant d'accepter.
Peter Taylor

Réponses:

2

05AB1E, 20 octets

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

L' entrée est dans l'ordre: list of values, nr of coins, sum to reach.

Explication en bref

  1. Obtenez toutes les permutations de la liste des pièces de longueur: final length - length of unique coin list
  2. Ajoutez la liste des pièces uniques à ces listes.
  3. Si la somme est égale à la somme recherchée, enregistrez la liste
  4. Afficher toutes les listes enregistrées

Essayez-le en ligne

Le compilateur en ligne ne peut pas gérer un grand nombre de pièces.

Emigna
la source
4

MATL , 22 octets

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

L'ordre d'entrée est le suivant: tableau de coupures, nombre de pièces prises ( n), somme souhaitée ( y).

Chaque combinaison est affichée sur une ligne différente. La sortie vide est affichée sous forme de chaîne vide (donc rien).

Essayez-le en ligne!

Le code manque de mémoire dans le compilateur en ligne pour l'exemple du défi, mais fonctionne hors ligne avec un ordinateur standard assez moderne:

>> 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

Explication

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
Luis Mendo
la source
3

Python 3, 120 106 octets

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

Une fonction anonyme qui prend en entrée un tuple de dénominations du formulaire (x_1, x_2, x_3 ... , x_k), une valeur cible et un certain nombre de pièces via un argument, et renvoie une liste de tuples du formulaire [(solution_1), (solution_2), (solution_3), ... (solution_k)].

Comment ça fonctionne

ItertoolsLa combinations_with_replacementfonction est utilisée pour générer toutes les l-len(d)combinaisons, avec remplacement, des dénominations. En ajoutant dà chacune de ces combinaisons, il est garanti que chaque dénomination apparaît au moins une fois et que la nouvelle combinaison a une longueur l. Si les éléments d'une combinaison ts'additionnent à, la combinaison est ajoutée à la liste de retour en tant que tuple.

Essayez-le sur Ideone


Une méthode alternative pour 108 octets

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)

Une fonction anonyme qui prend en entrée un tuple de dénominations du formulaire (x_1, x_2, x_3 ... , x_k), une valeur cible et un certain nombre de pièces via un argument, et renvoie un ensemble de tuples du formulaire {(solution_1), (solution_2), (solution_3), ... (solution_k)}.

Comment ça marche (autre version)

Ceci utilise la productfonction from itertoolspour générer tous les l-len(d)arrangements des dénominations. En ajoutant dà chacune de ces combinaisons, il est garanti que chaque dénomination apparaît au moins une fois et que la nouvelle combinaison a une longueur l. Si les éléments d'une combinaison totalisent t, la combinaison est triée, convertie d'une liste en tuple et ajoutée aux tuples de retour. Enfin, l'appel setsupprime tous les doublons.

Essayez-le sur Ideone (autre version)

TheBikingViking
la source
0

JavaScript (ES6), 135 octets

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)
Neil
la source