Pourcentage entier


21

Écrivez une fonction qui prend une liste d'entiers positifs et renvoie une liste d'entiers approximativement le pourcentage du total pour l'entier correspondant dans la même position.

Tous les entiers dans la liste de retour doivent correspondre exactement à 100. Vous pouvez supposer que la somme des entiers transmis est supérieure à 0. La façon dont vous voulez arrondir ou tronquer les décimales dépend de vous tant que tout entier résultant résultant est renvoyé en pourcentage n'est pas décalé de plus de 1 dans les deux sens.

p([1,0,2])      ->  [33,0,67] or [34,0,66]
p([1000,1000])  ->  [50,50]
p([1,1,2,4])    ->  [12,12,25,51] or [13,12,25,50] or [12,13,25,50] or [12,12,26,50]
p([0,0,0,5,0])  ->  [0,0,0,100,0]

C'est le , donc le code le plus court en octets gagne!


Notre algorithme doit-il être déterministe? Doit-elle toujours se terminer dans un délai limité?
lirtosiast

Nous avons déjà eu un problème d'arrondi similaire mais plus général
edc65

1
Je vous suggère d' ajouter un autre cas de test: p([2,2,2,2,2,3]). Il a de nombreuses réponses juridiques possibles, mais toutes ne 2peuvent pas être mappées à la même valeur. Cela élimine de nombreux algorithmes trop simples qui fonctionnent sur tous les cas de test précédents car l'arrondi n'est pas trop mauvais.
Sophia Lechner

4
Peut p([1000,1000]) -> [49,51]?
l4m2

1
@ l4m2 Cela semble faux, mais les deux résultats sont décalés de 1 et pas plus, donc il suit les spécifications
edc65

Réponses:


20

Dyalog APL, 21 19 16 octets

+\⍣¯1∘⌊100×+\÷+/

Ce qui précède est un équivalent de train de

{+\⍣¯1⌊100×+\⍵÷+/⍵}

Essayez-le en ligne.

Comment ça marche

                 ⍝ Sample input: 1 1 2 4
           +\    ⍝ Cumulative sum of input. (1 2 4 8)
              +/ ⍝ Sum of input. (8)
             ÷   ⍝ Divide the first result by the second. (0.125 0.25 0.5 1)
       100×      ⍝ Multiply each quotient by 100. (12.5 25 50 100)
      ⌊          ⍝ Round the products down to the nearest integer... (12 25 50 100)
     ∘           ⍝ and ...
  ⍣¯1            ⍝ apply the inverse of...
+\               ⍝ the cumulative sum. (12 13 25 50)

9
Si seulement Fermat pouvait vous suivre des cours de golf.
TessellatingHeckler

1
@TessellatingHeckler Je vois ce que vous y avez fait. Peut-être qu'il aurait alors assez de place en marge pour sa preuve. :)
mbomb007

14

TI-BASIC, 26 23 16 octets

Pour les calculatrices de la série TI-83 + / 84 +.

ΔList(augment({0},int(cumSum(ᴇ2Ans/sum(Ans

Merci à @Dennis pour un bel algorithme! Nous prenons la somme cumulée de la liste après la conversion en pourcentages, puis au sol, clouons un 0 sur le devant et prenons les différences. ᴇ2est un octet plus court que 100.

Au même nombre d'octets:

ΔList(augment({0},int(cumSum(Ans/sum(Ans%

Fait amusant: %est un jeton de deux octets qui multiplie un nombre par 0,01, mais il n'y a aucun moyen de le saisir dans la calculatrice! Vous devez soit modifier la source à l'extérieur, soit utiliser un programme d'assemblage.

Ancien code:

int(ᴇ2Ans/sum(Ans
Ans+(ᴇ2-sum(Ans)≥cumSum(1 or Ans

La première ligne calcule tous les pourcentages au sol, puis la deuxième ligne ajoute 1 aux premiers Néléments, où Nest le pourcentage restant. cumSum(signifie "somme cumulée".

Exemple avec {1,1,2,4}:

          sum(Ans                  ; 8
int(ᴇ2Ans/                         ; {12,12,25,50}

                        1 or Ans   ; {1,1,1,1}
                 cumSum(           ; {1,2,3,4}
     ᴇ2-sum(Ans)                   ; 1
                ≥                  ; {1,0,0,0}
Ans+                               ; {13,12,25,50}

Nous n'en aurons pas N>dim([list], car aucun pourcentage n'est diminué de plus de 1 dans le revêtement de sol.


Je ne sais pas comment vous comptez les octets ici, cela me semble terriblement plus long que 23
David Arenburg

@DavidArenburg Ceci est juste la forme lisible par l'homme. Tous les jetons ( int(, sum(, Ans, etc.) occupent un seul octet.
Dennis

4
+1 C'est l'un des golfs TI-BASIC les plus impressionnants que j'ai vus sur ce site.
PhiNotPi

Thomas, cette réponse est stupéfiante!
DaveAlger

Êtes-vous sûr qu'il n'y a aucun moyen d'entrer le %symbole? J'aurais pensé qu'il pourrait être trouvé dans le catalogue de symboles ... Aussi, je devrais sortir ma TI-84 + Silver. Je ne l'ai pas utilisé depuis un moment. Block Dude est génial.
mbomb007

7

CJam, 25 23 22 octets

{_:e2\:+f/_:+100-Xb.+}

Merci à @ Sp3000 pour 25 → 24.

Essayez-le en ligne.

Comment ça marche

_                   e# Push a copy of the input.
 :e2                e# Apply e2 to each integer, i.e., multiply by 100.
    \               e# Swap the result with the original.
     :+             e# Add all integers from input.
       f/           e# Divide the product by the sum. (integer division)
        _:+         e# Push the sum of copy.
           100-     e# Subtract 100. Let's call the result d.
               Xb   e# Convert to base 1, i.e., push an array of |d| 1's.
                 .+ e# Vectorized sum; increment the first |d| integers.

5

Mathematica, 41 octets

(s=Floor[100#/Tr@#];s[[;;100-Tr@s]]++;s)&

Attendez, que se passe-t-il ici?
seequ

@Seeq L'algorithme est comme l'ancien code de la réponse TI-BASIC. Il calcule tous les pourcentages au sol, puis ajoute 1 aux premiers Néléments, où Nest le pourcentage restant.
alephalpha

5

J (8.04 bêta) , 59 octets (30 octets volés)

Port J littéral de 30 octets de la réponse APL de Dennis :

    f=.3 :'+/\^:_1<.100*(+/\%+/)y'

    f 1 1 2 4
12 13 25 50

59 octets de réponse, le mieux que je puisse faire moi-même:

f=.3 :0
p=.<.100*y%+/y
r=.100-+/p
p+((r$1),(#p-r)$0)/:\:p
)

(Sur la base du reste devant atteindre les valeurs les plus élevées, pas plus de +1 chacune, réparties sur plusieurs valeurs dans le cas d'un reste> 1 ou d'une égalité pour la valeur la plus élevée).

par exemple

   f 1 0 2
33 0 67

   f 1000 1000
50 50

   f 1 1 2 4
12 12 25 51

   f 0 0 0 5 0
0 0 0 100 0

   f 16 16 16 16 16 16
17 17 17 17 16 16

   f 0 100 5 0 7 1
0 89 4 0 7 0

Explication

  • f=.3 : 0 - 'f' est une variable, qui est un type de verbe (3), défini ci-dessous (: 0):
  • p=. variable 'p', construite à partir de:
    • y est une liste de nombres 1 0 2
    • +/y est '+' mis entre chaque valeur '/', la somme de la liste 3
    • y % (+/y) est les valeurs y originales divisées par la somme: 0.333333 0 0.666667
    • 100 * (y%+/y)est 100x ces valeurs: 33.33.. 0 0.66...pour obtenir les pourcentages.
    • <. (100*y%+/y) est l'opérateur de plancher appliqué aux pourcentages: 33 0 66
  • r=. variable 'r', construite à partir de:
    • +/p est la somme des pourcentages plancher: 99
    • 100 - (+/p) est 100 - la somme ou les points de pourcentage restants nécessaires pour faire la somme des pourcentages à 100.
  • résultat, non stocké:
    • r $ 1 est une liste de 1, tant que le nombre d'éléments que nous devons incrémenter: 1 [1 1 ..]
    • #p est la longueur de la liste de pourcentage
    • (#p - r) est le nombre d'éléments qui ne seront pas incrémentés
    • (#p-r) $ 0 est une liste de 0 tant que ce nombre compte: 0 0 [0 ..]
    • ((r$1) , (#p-r)$0) est la liste des 1 suivie de la liste des 0: 1 0 0
    • \: pest une liste d'index à partir pde laquelle le mettre en ordre décroissant.
    • /: (\:p)est une liste d'index à partir \:pde laquelle mettre en ordre croissant
    • ((r$1),(#p-r)$0)/:\:pprend les éléments du 1 1 0 0 .. .. liste de masque et le tri donc il y a 1 s dans les positions des pourcentages les plus élevés, un pour chaque numéro nous avons besoin d'incrémenter et 0s pour d' autres numéros: 0 0 1.
    • p + ((r$1),(#p-r)$0)/:\:p est les pourcentages + le masque, pour faire la liste des résultats qui résume à 100%, qui est la valeur de retour de la fonction.

par exemple

33 0 66 sums to 99
100 - 99 = 1
1x1 , (3-1)x0 = 1, 0 0
sorted mask   = 0 0 1

33 0 66
 0 0  1
-------
33 0 67

et

  • ) fin de définition.

Je ne suis pas très expérimenté avec J; Je ne serais pas trop surpris s'il y avait une "liste de tours en pourcentages du total" opération intégrée, et une manière plus propre de "incrémenter n les plus grandes valeurs" aussi. (C'est 11 octets de moins que ma première tentative).


1
Très cool. J'ai une solution python mais elle est beaucoup plus longue que celle-ci. Bon travail!
DaveAlger

1
Si vous ne l'avez pas remarqué, les règles ont changé, vous devriez donc pouvoir raccourcir considérablement cela.
lirtosiast

@DaveAlger merci! @ThomasKwa J'ai remarqué, je ne suis pas sûr que cela m'aide considérablement - première tentative, je peux obtenir -2 caractères. Je devrais changer lelist[0:100-n] + list[:-100-n] approche - et je n'ai pas pensé à une autre façon de l'aborder.
TessellatingHeckler

4

JavaScript (ES6), 81 octets

a=>(e=0,a.map(c=>((e+=(f=c/a.reduce((c,d)=>c+d)*100)%1),f+(e>.999?(e--,1):0)|0)))

Cette condition "doit être égal à 100" (plutôt que d'arrondir et d'additionner) a presque doublé mon code (de 44 à 81). L'astuce consistait à ajouter un pot pour les valeurs décimales qui, une fois qu'il atteint 1, prend 1 de lui-même et l'ajoute au nombre actuel. Le problème était alors les virgules flottantes, ce qui signifie que quelque chose comme [1,1,1] laisse un reste de .9999999999999858. J'ai donc changé le chèque pour qu'il soit supérieur à .999, et j'ai décidé d'appeler cela assez précisément.


4

Haskell, 42 27 octets

p a=[div(100*x)$sum a|x<-a]

À peu près la méthode triviale à Haskell, avec quelques espaces supprimés pour le golf.

Console (supports inclus pour être cohérent avec l'exemple):

*Main> p([1,0,2])
[33,0,66]
*Main> p([1000,1000])
[50,50]
*Main> p([1,1,2,4])
[12,12,25,50]
*Main> p([0,0,0,5,0])
[0,0,0,100,0]

Edit: pratiqué mon putting, fait des remplacements évidents.

Original:

p xs=[div(x*100)tot|x<-xs]where tot=sum xs

1
La somme de la liste doit être 100. Dans votre premier exemple, c'est 99
Damien

4

Gelée , 7 octets

-2 merci à Dennis, me rappelant d'utiliser une autre nouvelle fonctionnalité ( Ä) et d'utiliser à la :place de ce que j'avais initialement.

ŻÄ׳:SI

Essayez-le en ligne!

Gelée , 11 octets

0;+\÷S×ȷ2ḞI

Essayez-le en ligne!

Fait aux côtés de caird coinheringaahing et user202729 dans le chat .

Comment ça marche

0; + \ ÷ S × ȷ2ḞI - Programme complet.

0; - Ajoutez un 0.
  + \ - Somme cumulée.
    ÷ S - Divisé par la somme de l'entrée.
      × ȷ2 - Times 100. Remplacé par × ³ dans la version de liaison monadique.
         ḞI - Plancher chacun, calculer les incréments (deltas, différences).

3

Haskell, 63 56 55 octets

p l=tail>>=zipWith(-)$[100*x`div`sum l|x<-0:scanl1(+)l]

3

Perl, 42 octets

Basé sur l'algorithme de Dennis

Comprend +1 pour -p

Exécuter avec la liste des numéros sur STDIN, par exemple

perl -p percent.pl <<< "1 0 2"

percent.pl:

s%\d+%-$-+($-=$a+=$&*100/eval y/ /+/r)%eg


2

Python 2, 89 octets

def f(L):
 p=[int(x/0.01/sum(L))for x in L]
 for i in range(100-sum(p)):p[i]+=1
 return p

print f([16,16,16,16,16,16])
print f([1,0,2])

->

[17, 17, 17, 17, 16, 16]
[34, 0, 66]

2

Brain-Flak , 150 octets

((([]){[{}]({}<>)<>([])}{})[()])<>([]){{}<>([{}()]({}<([()])>)<>(((((({})({})({})){}){}){}{}){}){}(<()>))<>{(({}<({}())>)){({}[()])<>}{}}{}([])}<>{}{}

Essayez-le en ligne!

Partant de la fin et travaillant en arrière, ce code garantit à chaque étape que la somme des numéros de sortie jusqu'à présent est égale au pourcentage total rencontré, arrondi vers le bas.

(

  # Compute and push sum of numbers
  (([]){[{}]({}<>)<>([])}{})

# And push sum-1 above it (simulating a zero result from the mod function)
[()])

<>

# While elements remain
([]){{}

  # Finish computation of modulo from previous step
  <>([{}()]({}

    # Push -1 below sum (initial value of quotient in divmod)
    <([()])>

  # Add to 100*current number, and push zero below it
  )<>(((((({})({})({})){}){}){}{}){}){}(<()>))

  # Compute divmod
  <>{(({}<({}())>)){({}[()])<>}{}}{}

([])}

# Move to result stack and remove values left over from mod
<>{}{}

2

JavaScript (ES6) 60 63 95

Adapté et simplifié de ma (mauvaise) réponse à un autre défi
Thk à @ l4m2 pour avoir découvert que c'était faux aussi

Correction de l'enregistrement de 1 octet (et 2 octets de moins, sans compter le nom F=)

v=>v.map(x=>(x=r+x*100,r=x%f,x/f|0),f=eval(v.join`+`),r=f/2)

Testez l'exécution de l'extrait ci-dessous dans n'importe quel navigateur compatible EcmaScript 6

F=
v=>v.map(x=>(x=r+x*100,r=x%f,x/f|0),f=eval(v.join`+`),r=f/2)

console.log('[1,0,2] (exp [33,0,67] [34,0,66])-> '+F([1,0,2]))
console.log('[1000,1000] (exp [50,50])-> '+F([1000,1000]))
console.log('[1,1,2,4] (exp[12,12,25,51] [13,12,25,50] [12,13,25,50] [12,12,26,50])-> '+F([1,1,2,4]))
console.log('[0,0,0,5,0] (exp [0,0,0,100,0])-> '+F([0,0,0,5,0]))
console.log('[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980] -> '+F([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980]))
console.log('[2,2,2,2,2,3] -> ' + F([2,2,2,2,2,3]))
<pre id=O></pre>


Échec[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,980]
l4m2

@ l4m2 a échoué pourquoi? La somme est de 100 etany single resulting integer returned as a percentage is off by no more than 1 in either direction.
edc65

Le dernier devrait être au plus un avant 98, mais c'est 100
l4m2

@ l4m2 euh, à droite, merci. Il est temps de réfléchir à nouveau
edc65

@ l4m2 devrait être corrigé maintenant
edc65

1

Rouille, 85 octets

Cela utilise des vecteurs au lieu de tableaux car, à ma connaissance, il n'y a aucun moyen d'accepter des tableaux de plusieurs longueurs différentes.

let a=|c:Vec<_>|c.iter().map(|m|m*100/c.iter().fold(0,|a,x|a+x)).collect::<Vec<_>>();

1

JavaScript, 48 octets

F=

x=>x.map(t=>s+=t,y=s=0).map(t=>-y+(y=100*t/s|0))

// Test 
console.log=x=>O.innerHTML+=x+'\n';


console.log('[1,0,2] (exp [33,0,67] [34,0,66])-> '+F([1,0,2]))
console.log('[1000,1000] (exp [50,50])-> '+F([1000,1000]))
console.log('[1,1,2,4] (exp[12,12,25,51] [13,12,25,50] [12,13,25,50] [12,12,26,50])-> '+F([1,1,2,4]))
console.log('[0,0,0,5,0] (exp [0,0,0,100,0])-> '+F([0,0,0,5,0]))
<pre id=O></pre>


0

Jq 1,5 , 46 octets

add as$s|.[1:]|map(100*./$s|floor)|[100-add]+.

Étendu

  add as $s               # compute sum of array elements
| .[1:]                   # \ compute percentage for all elements 
| map(100*./$s|floor)     # / after the first element
| [100-add] + .           # compute first element as remaining percentage

Essayez-le en ligne!


0

PHP, 82 octets

for(;++$i<$argc-1;$s+=$x)echo$x=$argv[$i]/array_sum($argv)*100+.5|0,_;echo 100-$s;

prend l'entrée des arguments de la ligne de commande, imprime les pourcentages délimités par un trait de soulignement.

Courez avec -nrou essayez-le en ligne .


Cela sort 15_15_15_15_15_25quand on lui donne l'entrée [2,2,2,2,3], ce qui n'est pas correct car3/13 ~= 23.1%
Sophia Lechner

@SophiaLechner Laquelle des réponses fait cela correctement?
Titus

La plupart le font, en fait. Jusqu'à présent, les bonnes réponses semblent être construites autour de l'un des deux algorithmes; le premier arrondit les pourcentages des sommes cumulées et prend la différence; le second calcule les étages des pourcentages puis incrémente suffisamment de pourcentages distincts pour porter le total à 100.
Sophia Lechner

@SophiaLechner Je ne voulais pas dire que je ne m'y intéresserais pas; mais je ferai plus tard. Merci d'avoir remarqué.
Titus
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.