14
\$\begingroup\$

The challenge is simple:

Create a pie-chart based on a number of input values.

The input will be a list of positive numbers, decimal or integers, and the output will be a pie-chart where each of the input values are represented by separate colors, and a percentage value outside each of the areas.

Rules:

  • The colors must be visually distinguishable (the exact colors are optional)
  • There will be at least two, and maximum 10 input values
  • The radius of the circle must be in the range [100 300] pixels
    • Vector graphics are OK as long as the default output gives a radius of [100, 300] pixels
  • The percentage values shall be integers
    • There is no strict rule saying where the percentage value shall be placed, but it must be easily seen which area it belongs to
    • The distance between the closest character and the outer edge of the circle must be in the range [5, 40] pixels
    • The font is optional
  • The plot may or may not have black lines separating each region
  • Functions made for creating pie charts, for instance, MATLAB: pie, Python: matplotlib.pyplot.pie and Mathematica: PieChart are not allowed
  • Normal rounding rules (up if it's (1.00, 0.5], down if it's (0.5, 0.00))
  • If the percentage value of a slice is smaller than 0.5%, output 0%. The slice must still be included in the plot.
  • Please provide plots for examination (or a link to an interpreter). It's enough to show only the plot with 10 input values (to avoid very long answers)

Examples

Please use the example values below. You can convert the lists to an appropriate format using a numeric list converter, for instance this 27 byte one by jimmy23013.

x = [0.3, 1.2] 

enter image description here

x = [3, 6, 2, 10]

enter image description here

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

enter image description here

\$\endgroup\$
4
  • \$\begingroup\$ "The radius of the circle must be in the range [100 300] pixels." Are vector graphics allowed too? \$\endgroup\$ Commented Apr 14, 2016 at 10:01
  • \$\begingroup\$ @MartinBüttner, yes. That's OK, as long as the output from the program looks like it's between [100, 300] by default. Is that a sufficient answer? \$\endgroup\$ Commented Apr 14, 2016 at 10:04
  • \$\begingroup\$ R rounds 0.5 to 0. Is that a problem? \$\endgroup\$
    – Masclins
    Commented Apr 14, 2016 at 12:35
  • \$\begingroup\$ It's ok to round 0.5 to zero if that's default. But 0.50001 must be rounded to 1. \$\endgroup\$ Commented Apr 14, 2016 at 12:39

3 Answers 3

12
\$\begingroup\$

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

Could be golfed further. Currently generates a Graphics object. Test cases:



\$\endgroup\$
7
\$\begingroup\$

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

Saved a byte with help from @Neil!

Explanation

Writes some SVG to the HTML of the current page. Builds the chart with centre point 135 x 150 of radius 100px and text at a radius of 135px from the centre.

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

\$\endgroup\$
5
  • \$\begingroup\$ I think you can save a few bytes using with(Math)c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150]. \$\endgroup\$
    – Neil
    Commented Apr 14, 2016 at 12:21
  • \$\begingroup\$ Hmm, you might have to write with(Math)var solution = a=> etc. \$\endgroup\$
    – Neil
    Commented Apr 14, 2016 at 12:26
  • \$\begingroup\$ Hmm, actually I can use with. I think I might have been in strict mode when I tried it last... \$\endgroup\$
    – user81655
    Commented Apr 14, 2016 at 12:26
  • \$\begingroup\$ @Neil Got it in there, thanks. I'm pretty sure there's a fair bit more golfing that can be done on this, since I was rushing a bit when I wrote it. \$\endgroup\$
    – user81655
    Commented Apr 14, 2016 at 12:30
  • \$\begingroup\$ Only saved 1 byte? I guess it's a start... \$\endgroup\$
    – Neil
    Commented Apr 14, 2016 at 12:34
6
\$\begingroup\$

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

enter image description here

Result for the largest example list :

enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ In Python 2, isn't eval(raw_input()) equivalent to Python 2's input()? \$\endgroup\$
    – cat
    Commented Apr 15, 2016 at 2:31
  • \$\begingroup\$ @cat yes it is ! \$\endgroup\$
    – dieter
    Commented Apr 15, 2016 at 7:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.