J'ai 15 $ en poche. De même, je suis dans un magasin qui ne donne pas de monnaie. Pendant la navigation, je repère un article qui coûte 10 $ (taxes incluses). Puis-je acheter cet article sans perdre d'argent?
Dans ce cas, la réponse est oui. Peu importe la façon dont mes 15 $ sont répartis (un 10 et un 5, ou trois 5, ou autre), j'aurai toujours les 10 $ nécessaires.
Comme deuxième exemple, j'ai 0,16 $ en poche. Quelles autres sommes d'argent dois-je pouvoir payer exactement?
Possible Divisions:
0.01, 0.05, 0.10
0.01, 0.05 x 3
0.01 x 16
Guaranteed Exact Change:
0.01, 0.05, 0.06, 0.10, 0.11, 0.15, 0.16
Et si j'ai 0,27 $ en poche?
Possible Divisions:
0.01 x 2, 0.25
0.01 x 2, 0.05, 0.10 x 2
0.01 x 2, 0.05 x 3, 0.10
0.01 x 2, 0.05 x 5
0.01 x 27
Guaranteed Exact Change:
0.01, 0.02, 0.25, 0.26, 0.27
Dans le cas ci-dessus, il n'y avait que quelques sommes d'argent pour lesquelles j'aurais toujours une monnaie parfaite.
Ta tâche
Écrivez le programme le plus court (ou la fonction nommée) qui prend A) un montant entier d'argent et B) une liste de dénominations possibles en entrée et génère une liste des montants d'argent pour lesquels je dois avoir un changement parfait. L'entrée peut être STDIN ou des arguments pour le programme ou la fonction. Je ne vais pas être super strict sur le formatage d'entrée; il peut correspondre à la façon dont vos tableaux de formats de langue.
Peut-être une explication plus détaillée
J'ai une certaine somme d'argent dans ma poche, qui est formée d'un ensemble de démonstrations possibles de monnaie. Si j'ai 8 $ et que je sais que les dénominations possibles sont de 2 $ et 3 $, alors il n'y a que beaucoup de combinaisons de factures différentes qui pourraient être dans ma poche. Ce sont 2+2+2+2
et 3+3+2
. Afin de pouvoir produire une somme exacte, je dois pouvoir produire cette quantité en utilisant les seules factures qui sont dans ma poche. Si j'avais quatre 2, je pourrais produire 2, 4, 6, or 8
. Si j'avais deux 3 et un 2, je pourrais produire 2, 3, 5, 6, or 8
Puisque je ne sais pas laquelle de ces combinaisons j'ai réellement dans ma poche, ma réponse finale est réduite à 2, 6, 8
. Ce sont les valeurs que je sais que je pourrais produire de ma poche, compte tenu du montant total et des dénominations possibles.
Exemple d'E / S calculées à la main
7 [3, 4]
3, 4, 7 //only one possible division into 3 + 4
7 [3, 2]
2, 3, 4, 5, 7 //the only division is 3 + 2 + 2
6 [2, 3, 4]
6 //divisions are 2+2+2, 3+3, 2+4
16 [1, 5, 10, 25] //this represents one of the examples above
1, 5, 6, 10, 11, 15, 16
27 [1, 5, 10, 25] //another example from above
1, 2, 25, 26, 27
1500 [1, 5, 10, 25, 100, 500, 1000, 2000]
500, 1000, 1500
600 [100, 500, 1000, 2000]
100, 500, 600
600 [200, 1, 5, 10, 25, 100, 500, 1000, 2000]
600
6 [2, 3, 4]
. Vous ne pouvez pas2+2+2
faire 3 et3+3
ne pas faire 2 et 4?Réponses:
Python 2,
200197193 193140 octets(Merci à @Nabb pour les conseils)
Voici une solution mal jouée pour l'instant pour commencer. Appel avec
g(16, [1, 5, 10, 25])
- la sortie est un ensemble avec les dénominations pertinentes.L'approche est simple et se décompose en deux étapes:
f
examine toutes les façons d'atteindre lesn
dénominationsD
(par exemple[1, 5, 10]
), et pour chacune, il calcule tous les montants qui peuvent être réalisés avec ces dénominations (par exempleset([0, 1, 5, 6, 10, 11, 15, 16])
).g
calcule les intersections des résultats def
, puis supprime 0 pour la réponse finale.Le programme résout très bien les cas 1 à 5 et 7, les débordements de pile sur 6 et dure indéfiniment sur 8.
S'il n'y a pas de solution (par exemple
g(7, [2, 4, 6])
), le programme renvoie un ensemble vide. Si une erreur est autorisée à être levée pour un tel cas, alors voici une courteg
:la source
g=lambda L,c=0:L and g(L[1:],c)|g(L,c+L.pop(0))or{c}
est un peu plus court-{0}
à g et en utilisant[L]*-~n
au lieu de[L][-n:]
JavaScript (ES6) 162
203 207Modifier Modification du mode d'intersection des jeux de résultats dans le tableau r. Un peu plus vite, mais l'algorithme pue toujours.
Une explication plus détaillée suivra.En bref: c est une fonction récursive qui énumère toutes les subdivisions possibles. k est une fonction récursive qui énumère toutes les sommes possibles sans répétitions. Tout nouvel ensemble de résultats trouvé avec la fonction k est comparé à l'ensemble précédent trouvé, seuls les résultats communs sont conservés.
Pourquoi est-ce si lent? Devoir gérer un total cible de, disons, 1500 et un seul morceau de valeur 1, énumérer toutes les sommes possibles n'est pas une bonne idée.
Non golfé
Tester dans la console Firefox / FireBug
(temps 84 ms)
(temps 147252 ms, donc pas trop rapide)
la source
Wolfram Methematica, 104 octets
Non golfé (lu de la fin):
la source