Erstellen Sie ein Kreisdiagramm

14

Die Herausforderung ist einfach:

Erstellen Sie ein Kreisdiagramm basierend auf einer Reihe von Eingabewerten.

Die Eingabe ist eine Liste positiver Zahlen, Dezimalzahlen oder Ganzzahlen, und die Ausgabe ist ein Kreisdiagramm, in dem jeder der Eingabewerte durch separate Farben und einen Prozentwert außerhalb der einzelnen Bereiche dargestellt wird.

Regeln:

  • Die Farben müssen optisch unterscheidbar sein (die genauen Farben sind optional)
  • Es gibt mindestens zwei und maximal 10 Eingabewerte
  • Der Radius des Kreises muss im Bereich [100 300]Pixel liegen
    • Vektorgrafiken sind in Ordnung, solange die Standardausgabe einen Pixelradius [100, 300]angibt
  • Die Prozentwerte sind ganze Zahlen
    • Es gibt keine strenge Regel, die besagt, wo der Prozentwert platziert werden soll, aber es muss leicht ersichtlich sein, zu welchem ​​Bereich er gehört
    • Der Abstand zwischen dem nächstgelegenen Zeichen und dem äußeren Rand des Kreises muss im Bereich von [5, 40]Pixeln liegen
    • Die Schriftart ist optional
  • Der Plot kann schwarze Linien aufweisen, die jeden Bereich trennen oder nicht
  • Funktionen zum Erstellen von Kreisdiagrammen, z. B. MATLAB:, piePython: matplotlib.pyplot.pieund Mathematica:, PieChartsind nicht zulässig
  • Normale Rundungsregeln (nach oben (1.00, 0.5], nach unten (0.5, 0.00))
  • Wenn der Prozentwert eines Slice kleiner als ist 0.5%, wird ausgegeben 0%. Das Stück muss noch in der Zeichnung enthalten sein.
  • Bitte geben Sie die zu prüfenden Parzellen an (oder einen Link zu einem Dolmetscher). Es reicht aus, nur den Plot mit 10 Eingabewerten anzuzeigen (um sehr lange Antworten zu vermeiden)

Beispiele

Bitte verwenden Sie die folgenden Beispielwerte. Sie können die Listen mit einem numerischen Listenkonverter in ein geeignetes Format konvertieren , beispielsweise dieses 27-Byte- Format von jimmy23013 .

x = [0.3, 1.2] 

Bildbeschreibung hier eingeben

x = [3, 6, 2, 10]

Bildbeschreibung hier eingeben

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

Bildbeschreibung hier eingeben

Stewie Griffin
quelle
"Der Radius des Kreises muss im Bereich [100 300] Pixel liegen." Sind auch Vektorgrafiken erlaubt?
Martin Ender
@ MartinBüttner, ja. Das ist in Ordnung, solange die Ausgabe des Programms standardmäßig zwischen [100, 300] liegt. Ist das eine ausreichende Antwort?
Stewie Griffin
R rundet 0,5 bis 0. Ist das ein Problem?
Masclins
Es ist in Ordnung, 0.5auf Null zu runden , wenn dies die Standardeinstellung ist. Aber 0.50001muss auf 1 gerundet werden
Stewie Griffin

Antworten:

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

Könnte weiter golfen werden. Erzeugt derzeit ein GraphicsObjekt. Testfälle:



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

Mit Hilfe von @Neil ein Byte gespeichert!

Erläuterung

Schreibt eine SVG-Datei in den HTML-Code der aktuellen Seite. Erstellt das Diagramm mit 135 x 150Radiusmittelpunkt 100pxund Text in einem Radius von 135pxvon der Mitte.

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
quelle
Ich denke, Sie können mit ein paar Bytes sparen with(Math)c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150].
Neil
Hmm, müssen Sie vielleicht schreiben with(Math)var solution = a=>usw.
Neil
Hmm, kann ich eigentlich gebrauchen with. Ich glaube, ich war vielleicht im strengen Modus, als ich es zuletzt ausprobiert habe ...
user81655
@ Neil Habe es drin, danke. Ich bin mir ziemlich sicher, dass man ein bisschen mehr Golf spielen kann, da ich mich beim Schreiben ein bisschen beeilt habe.
user81655
Nur 1 Byte gespeichert? Ich denke, es ist ein Anfang ...
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()

Bildbeschreibung hier eingeben

Ergebnis für die größte Beispielliste:

Bildbeschreibung hier eingeben

Dieter
quelle
eval(raw_input())Entspricht Python 2 nicht Python 2 input()?
Katze
@cat ja das ist es!
Dieter