Создать круговую диаграмму


14

Задача проста:

Создайте круговую диаграмму на основе количества входных значений.

Входными данными будет список положительных чисел, десятичных или целых чисел, а выходными данными будет круговая диаграмма, где каждое из входных значений представлено отдельными цветами и процентным значением вне каждой из областей.

Правила:

  • Цвета должны быть визуально различимы (точные цвета необязательны)
  • Будет не менее двух и не более 10 входных значений.
  • Радиус круга должен быть в диапазоне [100 300]пикселей
    • С векторной графикой все в порядке, пока вывод по умолчанию дает радиус [100, 300]пикселей
  • Процентные значения должны быть целыми числами
    • Не существует строгого правила, согласно которому процентное значение должно быть размещено, но должно быть легко видно, к какой области оно относится
    • Расстояние между ближайшим символом и внешним краем круга должно быть в [5, 40]пикселях диапазона
    • Шрифт не является обязательным
  • График может иметь или не иметь черные линии, разделяющие каждый регион
  • Функции, созданные для создания круговых диаграмм, например, MATLAB:, piePython: matplotlib.pyplot.pieи Mathematica: PieChartне допускаются
  • Нормальные правила округления (если есть (1.00, 0.5], то вниз, если есть (0.5, 0.00))
  • Если процентное значение среза меньше чем 0.5%, выведите 0%. Срез все еще должен быть включен в сюжет.
  • Пожалуйста, предоставьте участки для экспертизы (или ссылку на переводчика). Достаточно показать только график с 10 входными значениями (чтобы избежать очень длинных ответов)

Примеры

Пожалуйста, используйте пример значений ниже. Вы можете преобразовать списки в соответствующий формат, используя числовой преобразователь списка , например, этот 27-байтовый по 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]

введите описание изображения здесь


«Радиус круга должен быть в диапазоне [100 300] пикселей». Разрешена ли векторная графика?
Мартин Эндер

@ MartinBüttner, да. Это нормально, пока вывод программы выглядит так, как будто он находится между [100, 300] по умолчанию. Это достаточный ответ?
Стьюи Гриффин

R округляет 0,5 до 0. Это проблема?
Masclins

Это нормально, чтобы округлить 0.5до нуля, если это по умолчанию. Но 0.50001должно быть округлено до 1.
Стьюи Гриффин

Ответы:


12

Mathematica, 186 183 164 байта

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

Может быть в гольфе дальше. В настоящее время генерирует Graphicsобъект. Тестовые случаи:




7

JavaScript (ES6), 311 310 302 298 байт

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

Сохранил байт с помощью @Neil!

объяснение

Записывает некоторые SVG в HTML текущей страницы. Строит диаграмму с центральной точкой 135 x 150радиуса 100pxи текстом в радиусе 135pxот центра.

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


Я думаю, что вы можете сэкономить несколько байтов, используя with(Math)c=r=>[sin(d=PI*2*(v+p))*r+135,cos(d)*r+150].
Нил

Хм, возможно, вам придется написать with(Math)var solution = a=>и т. Д.
Нейл

Хм, на самом деле я могу использовать with. Я думаю, что я мог быть в строгом режиме, когда я пытался это в последний раз ...
user81655

@ Нейл, спасибо. Я почти уверен, что на этом есть немало возможностей для игры в гольф, так как я немного торопился, когда писал это.
user81655

Сохранено только 1 байт? Я думаю, что это начало ...
Нил

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

введите описание изображения здесь

Результат для самого большого списка примеров:

введите описание изображения здесь


В Python 2 не eval(raw_input())эквивалентно Python 2 input()?
кот

@ Cat Да, это так!
Дитер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.