Créer un graphique à secteurs

14

Le défi est simple:

Créez un graphique à secteurs basé sur un certain nombre de valeurs d'entrée.

L'entrée sera une liste de nombres positifs, décimaux ou entiers, et la sortie sera un diagramme circulaire où chacune des valeurs d'entrée est représentée par des couleurs distinctes, et un pourcentage en dehors de chacune des zones.

Règles:

  • Les couleurs doivent être visuellement reconnaissables (les couleurs exactes sont facultatives)
  • Il y aura au moins deux et maximum 10 valeurs d'entrée
  • Le rayon du cercle doit être compris dans la plage [100 300]pixels
    • Les graphiques vectoriels sont OK tant que la sortie par défaut donne un rayon de [100, 300]pixels
  • Les pourcentages doivent être des entiers
    • Il n'y a pas de règle stricte indiquant où la valeur en pourcentage doit être placée, mais il doit être facile de voir à quelle zone elle appartient
    • La distance entre le caractère le plus proche et le bord extérieur du cercle doit être comprise dans la plage [5, 40]pixels
    • La police est facultative
  • Le tracé peut ou non avoir des lignes noires séparant chaque région
  • Les fonctions faites pour créer des graphiques circulaires, par exemple, MATLAB:, piePython: matplotlib.pyplot.pieet Mathematica: PieChartne sont pas autorisées
  • Règles d'arrondi normales (vers le haut si c'est (1.00, 0.5], vers le bas si c'est (0.5, 0.00))
  • Si la valeur en pourcentage d'une tranche est inférieure à 0.5%, affichez 0%. La tranche doit toujours être incluse dans le tracé.
  • Veuillez fournir des graphiques pour examen (ou un lien vers un interprète). Il suffit de n'afficher que l'intrigue avec 10 valeurs d'entrée (pour éviter les réponses très longues)

Exemples

Veuillez utiliser les exemples de valeurs ci-dessous. Vous pouvez convertir les listes dans un format approprié à l'aide d'un convertisseur de liste numérique , par exemple celui de 27 octets par jimmy23013 .

x = [0.3, 1.2] 

entrez la description de l'image ici

x = [3, 6, 2, 10]

entrez la description de l'image ici

x = [0.4387, 0.3816, 0.7655, 0.7952, 0.1869, 0.4898, 0.4456, 0.6463, 0.7094, 0.7547]

entrez la description de l'image ici

Stewie Griffin
la source
"Le rayon du cercle doit être compris entre [100 300] pixels." Les graphiques vectoriels sont-ils également autorisés?
Martin Ender
@ MartinBüttner, oui. C'est OK, tant que la sortie du programme semble être entre [100, 300] par défaut. Est-ce une réponse suffisante?
Stewie Griffin
R arrondit 0,5 à 0. Est-ce un problème?
Masclins
Il est possible d'arrondir 0.5à zéro si c'est le cas par défaut. Mais 0.50001doit être arrondi à 1.
Stewie Griffin

Réponses:

12

Mathematica, 186 183 164 octets

Graphics[{Hue@#,Disk[{0,0},{1,1},a=2Pi{##}],Black,Text[ToString@Round[100(#2-#)]<>"%",5Through@{Cos,Sin}@Mean@a/4]}&@@@Partition[Accumulate[#/Tr@#]~Prepend~0,2,1]]&

Pourrait être joué au golf plus loin. Génère actuellement un Graphicsobjet. Cas de test:



LegionMammal978
la source
7

JavaScript (ES6), 311 310 302 298 octets

a=>{with(Math)document.write(`<svg height=300>`+a.map(n=>`<path fill=#${(p*4e3|0).toString(16)} d=M135,150L${c(o=100,v=0)}A${[o,o,0,(v=n/=s)+.5|0,0,c(o)]}Z /><text x=${(z=c(135,v/=2))[0]} y=${z[p+=n,1]}>${n*o+.5|0}%</text>`,c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150],p=s=0,a.map(n=>s+=n)).join``)}

Un octet enregistré avec l'aide de @Neil!

Explication

Écrit du SVG dans le code HTML de la page actuelle. Construit le graphique avec le point central 135 x 150du rayon 100pxet le texte à un rayon du 135pxcentre.

var solution =

a=>{
  with(Math)
  document.write(       // write to HTML body
    `<svg height=300>`+ // create 300px x 300px SVG canvas (width defaults to 300px)
    a.map(n=>           // for each number
      
      // Get the hex colour by multiplying the current position by (roughly) 0xfff
      `<path fill=#${(p*4e3|0).toString(16)
      
      // Calculate the path of the pie slice
      } d=M135,150L${c(o=100,v=0)}A${[o,o,0,(v=n/=s)+.5|0,0,c(o)]
      
      // Text
      }Z /><text x=${(z=c(135,v/=2))[0]} y=${z[p+=n,1]}>${n*o+.5|0}%</text>`,
      
      // Returns [ x, y ] for a certain radius at position v around the pie
      c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150],
      p=s=0,             // p = current position around pie (0 - 1)
      a.map(n=>s+=n)     // s = sum of all numbers
    ).join``
    
    +`</svg>` // <- this is just here for the test, so multiple charts can be displayed
  )
}

// Test
;[
  [0.3, 1.2],
  [3, 6, 2, 10],
  [0.4387, 0.3816, 0.7655, 0.7952, 0.1869, 0.4898, 0.4456, 0.6463, 0.7094, 0.7547]
].map(c=>solution(c));

user81655
la source
Je pense que vous pouvez économiser quelques octets en utilisant with(Math)c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150].
Neil
Hmm, tu devrais peut-être écrire with(Math)var solution = a=>etc.
Neil
Hmm, en fait je peux utiliser with. Je pense que j'aurais pu être en mode strict lors de mon dernier
essai
@Neil J'ai compris, merci. Je suis à peu près sûr qu'il y a un peu plus de golf qui peut être fait à ce sujet, car je me précipitais un peu quand je l'ai écrit.
user81655
Un seul octet enregistré? Je suppose que c'est un début ...
Neil
6

Python + PIL, 365 355

from math import*;from random import*
from PIL import Image,ImageDraw
L,a,r=256,0,0.8;l,p,c=L/2,L/6,(L,L,L);I=Image.new('RGB',(L,L),c);D=ImageDraw.Draw(I)
x=input()
for i in x:b=a+ceil(360.0*i/sum(x));D.pieslice((p,p,L-p,L-p),int(a),int(b),tuple(map(randrange,c)));t=(a+b)*0.00872;D.text((l+cos(t)*l*r,l+sin(t)*l*r),str(int((b-a)/3.6))+'%',0);a=b
I.show()

entrez la description de l'image ici

Résultat pour la plus grande liste d'exemples:

entrez la description de l'image ici

diète
la source
En Python 2, n'est-ce pas eval(raw_input())équivalent à Python 2 input()?
chat
@cat oui c'est ça!
Dieter