Buat diagram lingkaran

14

Tantangannya sederhana:

Buat diagram lingkaran berdasarkan sejumlah nilai input.

Input akan berupa daftar angka positif, desimal atau bilangan bulat, dan output akan menjadi diagram lingkaran di mana masing-masing nilai input diwakili oleh warna yang terpisah, dan nilai persentase di luar masing-masing area.

Aturan:

  • Warna harus dapat dibedakan secara visual (warna yang tepat adalah opsional)
  • Setidaknya akan ada dua, dan maksimum 10 nilai input
  • Jari-jari lingkaran harus dalam rentang [100 300]piksel
    • Vektor grafis yang OK asalkan output default memberikan radius [100, 300]piksel
  • Nilai persentase harus bilangan bulat
    • Tidak ada aturan ketat yang mengatakan di mana nilai persentase akan ditempatkan, tetapi harus mudah dilihat di daerah mana ia berada
    • Jarak antara karakter terdekat dan tepi luar lingkaran harus dalam [5, 40]piksel rentang
    • Fon bersifat opsional
  • Plot mungkin memiliki garis hitam yang memisahkan masing-masing daerah
  • Fungsi yang dibuat untuk membuat diagram lingkaran, misalnya, MATLAB:, piePython: matplotlib.pyplot.piedan Mathematica: PieCharttidak diizinkan
  • Aturan pembulatan normal (naik jika itu (1.00, 0.5], turun jika itu(0.5, 0.00) )
  • Jika nilai persentase slice lebih kecil dari 0.5%, output 0%. Irisan masih harus dimasukkan dalam plot.
  • Harap berikan plot untuk pemeriksaan (atau tautan ke juru bahasa). Cukup dengan hanya menampilkan plot dengan 10 nilai input (untuk menghindari jawaban yang sangat panjang)

Contohnya

Silakan gunakan nilai contoh di bawah ini. Anda dapat mengonversi daftar ke format yang sesuai menggunakan pengonversi daftar angka , misalnya yang 27 byte ini oleh jimmy23013 .

x = [0.3, 1.2] 

masukkan deskripsi gambar di sini

x = [3, 6, 2, 10]

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

Stewie Griffin
sumber
"Jari-jari lingkaran harus dalam kisaran [100 300] piksel." Apakah grafik vektor juga diperbolehkan?
Martin Ender
@ MartinBüttner, ya. Tidak apa-apa, asalkan output dari program terlihat antara [100, 300] secara default. Apakah itu jawaban yang cukup?
Stewie Griffin
R rounds 0.5 to 0. Apakah itu masalah?
Masclins
Tidak apa-apa untuk membulatkan 0.5ke nol jika itu default. Tetapi 0.50001harus dibulatkan ke 1.
Stewie Griffin

Jawaban:

12

Mathematica, 186 183 164 byte

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

Bisa bermain golf lebih lanjut. Saat ini menghasilkan Graphicsobjek. Kasus uji:



LegionMammal978
sumber
7

JavaScript (ES6), 311 310 302 298 byte

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

Menyimpan byte dengan bantuan dari @Neil!

Penjelasan

Menulis beberapa SVG ke HTML halaman saat ini. Buat bagan dengan titik tengah 135 x 150radius 100pxdan teks pada radius dari 135pxtengah.

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

pengguna81655
sumber
Saya pikir Anda dapat menyimpan beberapa byte menggunakan with(Math)c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150].
Neil
Hmm, Anda mungkin harus menulis with(Math)var solution = a=>dll.
Neil
Hmm, sebenarnya saya bisa pakai with. Saya pikir saya mungkin berada dalam mode ketat ketika saya mencobanya terakhir ...
user81655
@Neil mendapatkannya di sana, terima kasih. Saya cukup yakin ada sedikit lebih banyak golf yang bisa dilakukan dalam hal ini, karena saya agak terburu-buru ketika saya menulisnya.
user81655
Hanya disimpan 1 byte? Saya kira ini awal ...
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()

masukkan deskripsi gambar di sini

Hasil untuk daftar contoh terbesar:

masukkan deskripsi gambar di sini

pelaku diet
sumber
Dalam Python 2, bukankah ini eval(raw_input())setara dengan Python 2 input()?
kucing
@cat ya itu!
diet