L' algorithme du caissier est un algorithme permettant de modifier le nombre minimal de pièces qui fonctionne assez bien pour la plupart des systèmes monétaires. Cependant, comme la plupart des algorithmes gloutons, il n’est pas dépourvu de défauts. Si un système de devise est configuré correctement (ou tout simplement faux), il existe certaines valeurs pour lesquelles l'algorithme du caissier ne trouvera pas le changement optimal.
Prenons l'exemple suivant:
Nous avons des pièces de 4 ¢, 3 ¢ et 1 ¢. Nous voulons faire 6 ¢.
L'algorithme du caissier choisira d'abord autant de pièces parmi les plus grosses pièces (un 4 ¢ pour commencer), puis soustraira et répétera. Cela donnera une pièce de 4 ¢ et deux pièces de 1 ¢, pour un total de 3 pièces.
Malheureusement pour l'algorithme, il existe un moyen de faire 6 ¢ avec seulement deux pièces (deux pièces de 3 ¢).
Un système de changement sera considéré canonique ssi pour toutes les valeurs entières, l'algorithme du caissier trouvera le nombre optimal de pièces.
Tâche
Votre tâche consistera à prendre un système soit en tant que conteneur non ordonné, soit en conteneur ordonné trié et ordonné représentant des valeurs de pièces et en générant une valeur de vérité si l’entrée du système est canonique et falsy sinon.
Votre programme devrait fonctionner pour tous les systèmes pouvant créer n'importe quelle valeur. (c’est-à-dire que tous les systèmes auront une pièce de 1 ¢)
C'est le code de golf le moins d'octets gagne.
Cas de test
Cette liste n’est nullement exhaustive, votre programme devrait fonctionner pour toutes les entrées valides.
1, 3, 4 -> 0
1, 5, 10, 25 -> 1
1, 6, 10, 25 -> 0
1, 2, 3 -> 1
1, 8, 17, 30 -> 0
1, 3, 8, 12 -> 0
1, 2, 8, 13 -> 0
1, 2, 4, 6, 8 -> 1
la source
25, 9, 4, 1
(à partir de ce post math.SE ) - même si chaque pièce est plus grosse que la somme des plus petites, le non-gourmand25, 4, 4, 4
bat le gourmand25, 9, 1, 1, 1
.9, 4, 1
->4, 4, 4
être meilleur qu'un9, 1, 1, 1
exemple plus strict.Réponses:
Haskell,
948782 octetsCette solution définit une fonction
j
qui exécute l'algorithme du caissier et nous indique le nombre de pièces utilisées par le caissier. nous vérifions ensuite jusqu'à deux fois le plus grand nombre de la liste, en supposant que le système a été canonique pour tous les numéros précédents, que prendre la plus grosse pièce possible est le bon choix.cette solution suppose que l'entrée est triée.
vérifier qu'il est suffisant de vérifier jusqu'à deux fois le plus grand nombre: supposons que le système ne soit pas canonique pour un certain nombre
i
, et quek
le plus grand nombre de la liste ne soit pas supérieur ài
. supposons quei >= 2k
et que le système soit canonique pour tous les nombres inférieurs ài
.prenez un moyen optimal de fabriquer
i
des pièces de monnaie et supposez qu’elles ne contiennent pas la pièce de monnaiek
. si nous jetons l'une des pièces, la nouvelle somme de pièces doit être supérieurek
et inférieure ài
- mais l'algorithme du caissier sur ce nombre utilisera lak
pièce - et par conséquent, cet ensemble de pièces peut être remplacé par un ensemble égal de pièces. contenant la piècek
, il existe donc un ensemble de pièces contenant la piècek
pour le nombrei
et, par induction, l’algorithme du caissier renvoie le choix optimal.Cet argument montre vraiment que nous devons seulement vérifier jusqu'à la somme des deux plus gros éléments - mais c'est plus long à faire.
Edit: cinq octets de moins grâce à Ørjan Johansen!
la source
let
place dewhere
. Vous pouvez soit le mettre en|let ...
garde aprèsf s
, soit à l’intérieur de la liste de compréhension.j i=last$0:[1+j(i-k)|k<-s,k<i]
.Pyth,
18 à15 octetsSuite de tests
Une autre sorte de force brute. Cela commence par former toutes les collections de pièces avec un maximum de k, où k est la plus grande pièce, supposée être la dernière. Je crois que cela suffit toujours pour former deux jeux de pièces avec la même somme, un gourmand et un plus court, chaque fois qu'une telle paire existe.
Je localise alors une telle paire comme suit:
Les sous-ensembles sont générés par ordre de taille croissante et lexicographiquement par position dans l’entrée. Groupez les collections de pièces de monnaie par leurs sommes, de manière stable. Chaque collection de pièces étant générée par ordre décroissant, la solution gourmande sera le premier élément du groupe si et seulement si la solution gourmande est optimale et ce sera le dernier élément du groupe lexicographiquement. Ainsi, nous trouvons la solution gloutonne et filtrons sur un index non nul dans le groupe. Si le jeu de pièces est canonique, cela filtrera tout. Nous nions donc logiquement le résultat et la sortie.
Explication:
la source
/opt/tryitonline/bin/pyth: line 5: 28070 Killed ... Exit code: 137
à TIO? Juste à court de mémoire?PHP, 323 octets
De la même manière que les autres comptent les pièces jusqu’à la somme des deux derniers éléments du tableau
Ma meilleure et la plus longue réponse, je crois> 370 octets
Je ne donne qu'une version développée car il est plus long que ma réponse avant
Explication de cette réponse
Version en ligne
Définissez all dans le tableau sur false == X
Définissez tous les nombres du tableau que vous contrôlez sur S
Différences constatées entre le dernier S et l'autre S ou 0
Commence en dernier S dans le tableau
Définissez tous les nombres sur D Où Dernier S + une de toutes les différences
Commencez à tous D
SET "T" à D valeurs dans le tableau
GOTO 5 Répétez l'opération avec tous les DI trouvés ne l'ont pas fait dans le code
Si l'élément suivant du tableau contient X, il s'agit d'un faux cas, sinon, True
Étapes supplémentaires La différence est dans le cas dans l'extrait 3 Entre 1 et 4 sont 2 X Cela signifie que vous avez besoin du deuxième D d'ici l'étape 5. Après cette valeur dans ce cas, 10 sont tous les cas vrais, j'ai pu voir jusqu'à présent qu'il existe une relation entre la différence et le nombre dans le tableau que vous contrôlez pour calculer combien de D (Étape 5) vous devez obtenir le point avant de trouver le dernier faux cas.
Vous définissez plusieurs valeurs du dernier élément directement sur true. Ces points peuvent faire la différence pour décider s’il est possible que le nombre de pièces gloutonnes avec la valeur suivante soit identique au multiple du dernier dans le tableau. D'autre part, vous pouvez définir l'ennemi
Définir le premier ennemi à 1 + dernier S
A partir de ce point, ajoutez chaque valeur dans le tableau pour définir les prochains ennemis.
Commence avec le dernier ennemi Goto 2
Si vous avez maintenant des ennemis et des cas réels, la probabilité que les comptes soient identiques est de plus en plus grande. Avec plus de D, la probabilité diminue.
plus? Bytes Merci @JonathanAllan de me donner un cas de test erroné
262 octets Presque mais pas assez bon 4 mauvais test du moment
cas de test [1,16,256] avant devrait être vrai après faux
Ordre croissant du tableau
Explication
Il semble que ce que j'ai vu dans le tableau contienne les valeurs de [1,2,3,4,5,6] et que je ne modifie que le dernier élément jusqu'à 9. Pour 2to3 et 4to5, nous créons la valeur de la valeur la plus basse dans le champ. calcul modulo
la source
", "
quand vous pourriez diviser","
? pourquoi vous divisez-vous quand vous pouvez prendre une liste? pourquoi vous triez quand vous pourriez prendre une liste triée? (Je suis également toujours incertain si la méthode que vous utilisez est infaillible, avez-vous une preuve, car la littérature que j'ai parcourue semble suggérer qu'il est plus difficile que ce que votre code est en train de faire.)[1,2,5,11,17]
est canonique. Peut-être jetez un coup d'œil au document lié à ma réponse.JavaScript (ES6), 116
125 130Cela nécessite que le tableau en entrée soit trié par ordre décroissant. Pour chaque valeur comprise entre 2N et 2 (N étant la valeur de pièce maximale), il recherche le nombre de pièces de l'algorithme glouton et tente de trouver un ensemble de pièces plus petit.
Moins golfé
Tester
la source
Python,
218 211205 octets-1 octet grâce à @TuukkaX (un espace peut être supprimé entre
<3
etor
)repl.it
Entrer dans l'ordre décroissant.
Force brute horriblement. N'importe quel ensemble d'une pièce unique et d'une autre pièce est canonique. Pour les plus grandes séries, le plus petit des cas d'échec, s'il en existe une, sera supérieur ou égal à la 3ème plus petite pièce (je ne suis pas sûr de savoir comment il pourrait être égal!) Et inférieur à la somme des deux plus grandes pièces - voir le présent document (qui référence une autre mais donne également une méthode O (n ^ 3)).
g
compte les pièces utilisées par la méthode gourmande, et la fonction non nommée parcourt les candidats possibles (en réalité de 0 à une fois moins que le double de la plus grosse pièce pour enregistrer des octets) et recherche toute collection de moins de pièces équivalant à ce montant.g
fonctionne en effectuant ce qu'un caissier, il faut récursive la plus grande pièce inférieure ou égale au montant encore pour compenser,[v for v in c if v<=x][0]
loin, et compte le nombre de pièces utilisées,n
.La fonction non nommée retourne 1 si
len(c)
est inférieur à 3, et teste sinon que ce n'est pas le cas,1-...
que toute valeur dans la plage de possibilitésrange(c[0]*2)))
est possible avec moins de piècesi in range(g(x,c))
, en créant une collection de toutes les pièces,c*i
, et en examinant toutes les combinaisons dei
pièces de monnaie,combinations(c*i,i)
pour voir si des sommes ont la même valeur.la source
3or
devrait marcher.not(...)
par1-...
Gelée ( fourchette ),
15 à14 octetsCette solution utilise les bornes pour les contre-exemples de ce document . Là, l'auteur utilise une limite étroite pour le contre-exemple, mais dans l'intérêt du golf, la plage de la somme des dénominations de pièces est utilisée, ce qui est plus grand et contient cette limite.
Ce programme calcule tous les cas de test en moins d’une seconde sur ma machine.
Malheureusement, cela repose sur une branche de Jelly où je travaillais à la mise en œuvre d'un atome de résolution Frobenius, de sorte que vous ne pouvez pas l'essayer en ligne.
Usage
Les performances sont bonnes et peuvent résoudre tous les cas de test à la fois en moins d’une seconde.
Explication
la source
JavaScript (ES6),
144132124122110 octetsRequiert que le tableau soit trié par ordre décroissant. Utilise l'observation dans le papier lié que si le système n'est pas canonique, il existe au moins une valeur inférieure à 2a [0] qui prend moins de pièces lorsqu'elle est décomposée à l'aide des pièces inutilisées de l'algorithme glouton initial.
Edit: Sauvegardé 12 octets en réalisant que je pouvais vérifier toutes les pièces même si j'avais déjà atteint la valeur cible. J'ai enregistré 8 octets en commutant ma sortie intermédiaire de
[l,b]
vers[b,-l]
; cela m'a permis de passer directement le premier résultat en tant que paramètre du deuxième appel, ainsi qu'une petite sauvegarde détectant si le deuxième appel a réussi. J'ai enregistré 2 octets en déplaçant la définition deg
dans lesome
rappel, me permettant d'éviter de passer inutilement deux fois dans la variable de boucle. J'ai enregistré 12 octets en passant de ma fonction d'assistance récursive à un appel àfilter
(rendu possible par mon commutateur de sortie intermédiaire).la source
Perl, 69 octets
Comprend +2 pour
-pa
Donnez des pièces en ordre décroissant sur STDIN. Vous pouvez éventuellement laisser de côté la
1
pièce.coins.pl
:Construit le nombre de pièces utilisées par l’algorithme de la caisse
@G
pour des montants allant de 1 à deux fois la plus grosse pièce. Pour chaque montant, vérifie que si ce montant est réduit d'une valeur d'une pièce, l'algorithme du caissier a besoin d'au plus une pièce de moins. Sinon, il s'agit d'un contre-exemple (ou il y avait un contre-exemple précédent). Je pourrais m'arrêter au premier contre-exemple, mais cela prend plus d'octets. Donc, la complexité temporelle estO(max_coin * coins)
et la complexité spatiale estO(max_coin)
la source