Utwórz wykres kołowy

14

Wyzwanie jest proste:

Utwórz wykres kołowy na podstawie szeregu wartości wejściowych.

Dane wejściowe będą listą liczb dodatnich, dziesiętnych lub liczb całkowitych, a dane wyjściowe będą wykresem kołowym, na którym każda z wartości wejściowych jest reprezentowana przez osobne kolory, a wartość procentowa poza każdym obszarem.

Zasady:

  • Kolory muszą być widoczne wizualnie (dokładne kolory są opcjonalne)
  • Będą co najmniej dwie, a maksymalnie 10 wartości wejściowych
  • Promień okręgu musi być w zakresie [100 300]pikseli
    • Grafika wektorowa jest OK, o ile domyślne wyjście daje promień [100, 300]pikseli
  • Wartości procentowe są liczbami całkowitymi
    • Nie ma ścisłej zasady określającej, gdzie ma zostać umieszczona wartość procentowa, ale należy łatwo zobaczyć, do którego obszaru należy
    • Odległość między najbliższym znakiem a zewnętrzną krawędzią koła musi się mieścić w zakresie [5, 40] pikseli
    • Czcionka jest opcjonalna
  • Na wykresie mogą znajdować się czarne linie oddzielające każdy region
  • Funkcje stworzone do tworzenia wykresów kołowych, na przykład MATLAB:, piePython: matplotlib.pyplot.piei Mathematica: PieChartsą niedozwolone
  • Normalne zasady zaokrąglania (w górę, jeśli jest (1.00, 0.5], w dół, jeśli jest (0.5, 0.00))
  • Jeśli wartość procentowa plasterka jest mniejsza niż 0.5%, wynik 0%. Plasterek musi być nadal włączony do wykresu.
  • Podaj działki do zbadania (lub link do tłumacza). Wystarczy wyświetlić tylko wykres z 10 wartościami wejściowymi (aby uniknąć bardzo długich odpowiedzi)

Przykłady

Użyj poniższych wartości przykładowych. Możesz przekonwertować listy do odpowiedniego formatu za pomocą konwertera liczb , na przykład ten 27-bajtowy przez jimmy23013 .

x = [0.3, 1.2] 

wprowadź opis zdjęcia tutaj

x = [3, 6, 2, 10]

wprowadź opis zdjęcia tutaj

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

wprowadź opis zdjęcia tutaj

Stewie Griffin
źródło
„Promień koła musi mieścić się w zakresie [100 300] pikseli.” Czy grafika wektorowa jest dozwolona?
Martin Ender
@ MartinBüttner, tak. Zgadza się, pod warunkiem, że wyjście programu domyślnie wygląda tak, jakby zawierało się w przedziale [100, 300]. Czy to wystarczająca odpowiedź?
Stewie Griffin
R zaokrągla od 0,5 do 0. Czy to problem?
Masclins
Można zaokrąglić 0.5do zera, jeśli jest to ustawienie domyślne. Ale 0.50001należy zaokrąglić do 1.
Stewie Griffin

Odpowiedzi:

12

Mathematica, 186 183 164 bajtów

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

Można dalej grać w golfa. Obecnie generuje Graphicsobiekt. Przypadki testowe:



LegionMammal978
źródło
7

JavaScript (ES6), 311 310 302 298 bajtów

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

Zapisano bajt z pomocą @Neil!

Wyjaśnienie

Zapisuje niektóre pliki SVG w kodzie HTML bieżącej strony. Tworzy wykres z punktem środkowym 135 x 150promienia 100pxi tekstem w promieniu 135pxod środka.

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

użytkownik 81655
źródło
Myślę, że możesz zaoszczędzić kilka bajtów with(Math)c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150].
Neil
Hmm, być może będziesz musiał napisać with(Math)var solution = a=>itp.
Neil
Hmm, właściwie mogę użyć with. Myślę, że mogłem być w trybie ścisłym, kiedy próbowałem go ostatnio ...
user81655 14.04.16
@Neil Mam go tam, dzięki. Jestem prawie pewien, że można na tym grać w golfa o wiele więcej, ponieważ trochę się spieszyłem, kiedy to napisałem.
user81655 14.04.2016
Zapisano tylko 1 bajt? Myślę, że to początek ...
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()

wprowadź opis zdjęcia tutaj

Wynik dla największej przykładowej listy:

wprowadź opis zdjęcia tutaj

dieter
źródło
W Pythonie 2 nie jest eval(raw_input())odpowiednikiem Pythona 2 input()?
kot
@ kot tak to jest!
dieter