Donné:
- Un nombre naturel S .
- Une liste de N poids rationnels W qui totalisent 1.
Renvoie une liste L de N entiers non négatifs, tels que:
(1) sum(L) = S
(2) sum((S⋅W_i - L_i)^2) is minimal
En d'autres termes, rapprochez le plus possible S⋅W_i
s de nombres entiers.
Exemples:
1 [0.4 0.3 0.3] = [1 0 0]
3 [0 1 0] = [0 3 0]
4 [0.3 0.4 0.3] = [1 2 1]
5 [0.3 0.4 0.3] = [2 2 1] or [1 2 2] but not [1 3 1]
21 [0.3 0.2 0.5] = [6 4 11]
5 [0.1 0.2 0.3 0.4] = [1 1 1 2] or [0 1 2 2]
4 [0.11 0.3 0.59] = [1 1 2]
10 [0.47 0.47 0.06] = [5 5 0]
10 [0.43 0.43 0.14] = [4 4 2]
11 [0.43 0.43 0.14] = [5 5 1]
Règles:
- Vous pouvez utiliser n'importe quel format d'entrée ou simplement fournir une fonction qui accepte l'entrée comme arguments.
Contexte:
Ce problème survient lors de l'affichage de S de différents types d'articles dans différentes proportions W i en ce qui concerne les types.
Un autre exemple de ce problème est la représentation politique proportionnelle, voir le paradoxe de la répartition . Les deux derniers cas de test sont connus sous le nom de paradoxe de l'Alabama.
En tant que statisticien, j'ai reconnu ce problème comme équivalent à un problème rencontré dans l'identification des tailles d'échantillon lors de la réalisation d'un échantillon stratifié. Dans cette situation, nous voulons que la proportion de chaque strate dans l'échantillon soit égale à la proportion de chaque strate dans la population. - @tomi
la source
round(A + B) != round(A) + round(B)
, une solution courte nécessite un aperçu de ce qui se passe ici.L[i] - S*W[i]
carré, au lieu de la règle 2 et la règle 3. Ce serait approximatifS*W[i]
.[0 1 2 2]
une autre solution possible pour5 [0.1 0.2 0.3 0.4]
Réponses:
APL, 21
Ceci est une traduction de la réponse CJam d' Aditsu de 37 octets .
Testez-le en ligne .
Explication
la source
Python 2,
9583132125143Mon premier (et deuxième) (et troisième) algorithme a eu des problèmes donc après une (une autre!) Réécriture et plus de tests, voici (j'espère vraiment) une solution correcte et rapide:
La source avant le minificateur ressemble maintenant à:
Les tests renvoient:
Cet algorithme est similaire à d'autres réponses ici. C'est O (1) pour num, donc il a le même temps d'exécution pour les entiers 10 et 1000000. C'est théoriquement O (nlogn) pour le nombre de poids (à cause du tri). Si cela résiste à tous les autres cas d'entrée délicats, il remplacera l'algorithme ci-dessous dans ma boîte à outils de programmation.
Veuillez ne pas utiliser cet algorithme avec quoi que ce soit qui ne soit pas du golf. J'ai fait des compromis de vitesse pour minimiser la taille de la source. Le code suivant utilise la même logique mais est beaucoup plus rapide et plus utile:
La valeur de num n'affecte pas la vitesse de manière significative. Je l'ai testé avec des valeurs de 1 à 10 ^ 19. Le temps d'exécution varie linéairement avec le nombre de poids. Sur mon ordinateur, cela prend 0,15 seconde avec 10 ^ 5 poids et 15 secondes avec 10 ^ 7 poids. Notez que les poids ne sont pas limités aux fractions qui totalisent un. La technique de tri utilisée ici est également environ deux fois plus rapide que le
sorted((v,i) for i,v in enumerate...)
style traditionnel .Algorithme d'origine
C'était une fonction de ma boîte à outils, légèrement modifiée pour le golf. C'était à l'origine d'une réponse SO . Et c'est faux.
Il donne une approximation, mais n'est pas toujours correct, bien que la somme (outseq) == num soit maintenue. Rapide mais non recommandé.
Merci à @alephalpha et @ user23013 pour avoir repéré les erreurs.
EDIT: définissez totalw (d) sur 1 car OP spécifie que la somme des poids sera toujours 1. Maintenant 83 octets.
EDIT2: correction d'un bug trouvé pour [0.4, 0.3, 0.3], 1.
EDIT3: Algorithme défectueux abandonné. Ajout d'un meilleur.
EDIT4: Cela devient ridicule. Remplacé par un algorithme correct (j'espère vraiment).
EDIT5: Ajout d'un code non-golfique pour les autres qui aimeraient utiliser cet algorithme.
la source
a([0.4, 0.3, 0.3], 1)
renvoie[0, 1, 0]
, tandis que la bonne réponse est[1, 0, 0]
.a([0.11,0.3,0.59],4)
retourné[0, 1, 3]
. Devrait l'être[1, 1, 2]
.f([0.47,0.47,0.06],10)
retourné[5, 4, 1]
. Devrait l'être[5, 5, 0]
.Mathematica,
67504645 caractèresNon golfé:
Exemple:
la source
CJam - 37
Essayez-le en ligne
Explication:
Remarques:
Idée différente - 46
Essayez-le en ligne
C'est beaucoup plus simple et efficace, mais hélas, un peu plus long. L'idée ici est de commencer par L_i = plancher (S * W_i), de déterminer la différence (disons D) entre S et leur somme, de trouver les indices D avec la plus grande partie fractionnelle de S * W_i (en triant et en prenant D en haut) et incrémenter L_i pour ces indices. Complexité O (N * log (N)).
la source
:e<
.JavaScript (ES6) 126
130 104 115 115 156 162 194Après tous les commentaires et cas de test dans la réponse de @ CarpetPython, revenons à mon premier algorithme. Hélas, la solution intelligente ne fonctionne pas. Mise en œuvre un peu raccourcie, elle essaie toujours toutes les solutions possibles, calcule la distance au carré et garde le minimum.
Modifier Pour chaque élément de sortie de poids w, `` toutes '' les valeurs possibles ne sont que 2: trunc (w * s) et trunc (w * s) +1, il n'y a donc que (2 ** elemensts) solutions possibles à essayer.
Tester dans la console Firefox / FireBug
Production
C'est une solution plus intelligente. Un seul passage sur le tableau de poids.Pour chaque passe, je trouve la valeur maximale actuelle en w. Je change cette valeur en place avec la valeur entière pondérée (arrondie vers le haut), donc si s == 21 et w = 0,4, nous obtenons 0,5 * 21 -> 10,5 -> 11. Je stocke cette valeur niée, donc elle ne peut pas être trouvé comme max dans la boucle suivante. Ensuite, je réduis la somme totale en conséquence (s = s-11) et réduit également le total des poids dans la variable f.
La boucle se termine lorsqu'il n'y a pas de max au dessus de 0 à trouver (toutes les valeurs! = 0 ont été gérées).
Enfin, je renvoie à nouveau les valeurs changées en positif. Attention ce code modifie le tableau de poids en place, il doit donc être appelé avec une copie du tableau d'origine
Mon premier essai
Pas si une solution intelligente. Pour chaque résultat possible, il évalue la différence et garde le minimum.
Non golfé et expliqué
la source
CJam, 48 octets
Une solution simple au problème.
L'entrée va comme
Explication:
Essayez-le en ligne ici
la source
Pyth: 40 octets
Ceci définit une fonction
g
avec 2 paramètres. Vous pouvez l'appeler commeMhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4
.Essayez-le en ligne: Pyth Compiler / Executor
Explication:
Cela crée toutes les solutions possibles
L
, oùL[i] = floor(S*W[i])
ouL[i] = floor(S*W[i]+1)
. Par exemple, l'entrée4 [0.3 0.4 0.3
crée[[1, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 2], [2, 2, 1], [2, 1, 2], [1, 2, 2], [2, 2, 2]]
.Reste seulement
[[2, 1, 1], [1, 2, 1], [1, 1, 2]]
.la source
Mathematica 108
Explication
Non golfé
IntegerPartitions[s,{Length@w},0~Range~s]
renvoie toutes les partitions entiers des
, en utilisant des éléments pris dans l'ensemble{0, 1, 2, ...s}
avec la contrainte que la sortie doit contenir le même nombre d'éléments que dans l'ensemble de poids,w
.Permutations
donne tous les arrangements ordonnés de chaque partition entière.{Tr[(s *w-#)^2],#}
renvoie une liste de paires ordonnées,{error, permutation}
pour chaque permutation.Sort[...]
trie la liste des{{error1, permutation1},{error2, permutation2}...according to the size of the error.
[[1,2]]]
ouPart[<list>,{1,2}]
renvoie le deuxième élément du premier élément de la liste triée de{{error, permutation}...}
. En d'autres termes, il renvoie la permutation avec la plus petite erreur.la source
R,
858076Utilise la méthode Hare Quota.
Suppression d'un couple après avoir vu la spécification selon laquelle W sera égal à 1
Essai
la source
Python,
139128117 octetsSolution itertools précédente, 139 octets
la source
O(S^len(W))
fait: P. La nouvelle solution est beaucoup plus rapide, mais toujours lenteOctave,
8776Golfé:
Non golfé:
("Endfor" et "endfunction" fous! Je ne gagnerai jamais mais j'aime jouer au golf avec un "vrai" langage.)
la source
zeros(size(w))
par0*w
.T-SQL,
167265Parce que j'aime aussi essayer de relever ces défis dans une requête.
Le transforma en une fonction en ligne pour mieux s'adapter aux spécifications et créa un type pour les données de la table. Cela a coûté un peu, mais cela n'allait jamais être un concurrent. Chaque instruction doit être exécutée séparément.
Utilisé
la source