# Create a pie chart

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]


x = [3, 6, 2, 10]


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


• "The radius of the circle must be in the range [100 300] pixels." Are vector graphics allowed too? Apr 14 '16 at 10:01
• @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? Apr 14 '16 at 10:04
• R rounds 0.5 to 0. Is that a problem? Apr 14 '16 at 12:35
• It's ok to round 0.5 to zero if that's default. But 0.50001 must be rounded to 1. Apr 14 '16 at 12:39

# Mathematica, 186183 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:

# JavaScript (ES6), 311310302 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));

• 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].
– Neil
Apr 14 '16 at 12:21
• Hmm, you might have to write with(Math)var solution = a=> etc.
– Neil
Apr 14 '16 at 12:26
• Hmm, actually I can use with. I think I might have been in strict mode when I tried it last... Apr 14 '16 at 12:26
• @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. Apr 14 '16 at 12:30
• Only saved 1 byte? I guess it's a start...
– Neil
Apr 14 '16 at 12:34

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


Result for the largest example list :

• In Python 2, isn't eval(raw_input()) equivalent to Python 2's input()?
– cat
Apr 15 '16 at 2:31
• @cat yes it is ! Apr 15 '16 at 7:46