Crea un gráfico circular

14

El desafío es simple:

Cree un gráfico circular basado en una serie de valores de entrada.

La entrada será una lista de números positivos, decimales o enteros, y la salida será un gráfico circular donde cada uno de los valores de entrada están representados por colores separados y un valor porcentual fuera de cada una de las áreas.

Reglas:

  • Los colores deben ser visualmente distinguibles (los colores exactos son opcionales)
  • Habrá al menos dos y un máximo de 10 valores de entrada
  • El radio del círculo debe estar en el rango de [100 300]píxeles
    • Los gráficos vectoriales están bien siempre que la salida predeterminada proporcione un radio de [100, 300]píxeles
  • Los valores porcentuales serán enteros
    • No hay una regla estricta que diga dónde se colocará el valor porcentual, pero debe verse fácilmente a qué área pertenece
    • La distancia entre el personaje más cercano y el borde exterior del círculo debe estar en el rango [5, 40] píxeles
    • La fuente es opcional
  • La trama puede o no tener líneas negras que separan cada región
  • Funciones realizadas para crear gráficos circulares, por ejemplo, MATLAB:, piePython: matplotlib.pyplot.piey Mathematica:PieChart no están permitidas
  • Reglas de redondeo normales (arriba si es (1.00, 0.5], abajo si es(0.5, 0.00) )
  • Si el valor porcentual de un segmento es menor que 0.5%, salida0% . El corte aún debe incluirse en la trama.
  • Proporcione parcelas para su examen (o un enlace a un intérprete). Es suficiente mostrar solo el gráfico con 10 valores de entrada (para evitar respuestas muy largas)

Ejemplos

Utilice los valores de ejemplo a continuación. Puede convertir las listas a un formato apropiado utilizando un convertidor de lista numérica , por ejemplo, este de 27 bytes por jimmy23013 .

x = [0.3, 1.2] 

ingrese la descripción de la imagen aquí

x = [3, 6, 2, 10]

ingrese la descripción de la imagen aquí

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

ingrese la descripción de la imagen aquí

Stewie Griffin
fuente
"El radio del círculo debe estar en el rango [100 300] píxeles". ¿También se permiten los gráficos vectoriales?
Martin Ender
@ MartinBüttner, sí. Eso está bien, siempre que la salida del programa parezca estar entre [100, 300] por defecto. ¿Es esa una respuesta suficiente?
Stewie Griffin
R redondea 0.5 a 0. ¿Es eso un problema?
Masclins
Está bien redondear 0.5a cero si eso es predeterminado. Pero 0.50001debe redondearse a 1.
Stewie Griffin

Respuestas:

12

Mathematica, 186 183 164 bytes

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]]&

Se podría jugar más al golf. Actualmente genera un Graphicsobjeto. Casos de prueba:



LegionMammal978
fuente
7

JavaScript (ES6), 311 310 302 298 bytes

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``)}

¡Salvé un byte con la ayuda de @Neil!

Explicación

Escribe algo de SVG en el HTML de la página actual. Construye el gráfico con el punto central 135 x 150del radio 100pxy el texto en un radio 135pxdesde el centro.

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));

usuario81655
fuente
Creo que puedes guardar algunos bytes usando with(Math)c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150].
Neil
Puede que tenga que escribir, with(Math)var solution = a=>etc.
Neil
Hmm, en realidad puedo usar with. Creo que podría haber estado en modo estricto la última vez que lo intenté ...
user81655
@Neil Lo tengo allí, gracias. Estoy bastante seguro de que hay un poco más de golf que se puede hacer con esto, ya que me apresuré un poco cuando lo escribí.
user81655
¿Solo guardado 1 byte? Supongo que es un comienzo ...
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()

ingrese la descripción de la imagen aquí

Resultado para la lista de ejemplo más grande:

ingrese la descripción de la imagen aquí

dieter
fuente
En Python 2, ¿no es eval(raw_input())equivalente a Python 2 input()?
gato
@cat sí lo es!
dieter