Числа как круговая графика

36

Сначала изучите эту головоломку, чтобы почувствовать, что вы будете производить.

Ваша задача - написать программу или функцию, которая будет выводить круглую графику, подобную изображенной в головоломке, с числом (основание 10) от 1 до 100 (включительно). Это похоже на этот вызов , за исключением того, что вы будете создавать графические, а не римские цифры. Следующие кружки представляют цифры 1-10 слева направо:

круг картины

Поскольку ответ на загадку гласит, ваша графика должна читаться как римская цифра изнутри, где толщина линии представляет символы римской цифры, а весь рисунок представляет число. Для справки, вот толщина линий, которые вам понадобятся. Каждая строка должна иметь отступ в 3 пикселя между ней и следующей.

Number  Roman Numeral   Line Width
1       I               1px
5       V               3px
10      X               5px
50      L               7px
100     C               9px

Пожалуйста, опубликуйте образец или два ваших вывода. Предположим, что ввод правильный, стандартные лазейки и т. Д. И т. Д. Это кодовый гольф, поэтому выигрывает меньшее количество байтов. В случае ничьей побеждает большинство голосов. Удачи!

Рип Лееб
источник
3
Нужен ли правильный абсолютный размер изображения или достаточно правильных относительных размеров?
Дэвид Чжан
@DavidZhang Да, пожалуйста, придерживайтесь размеров линии и отступов, которые я перечислил, ради справедливости.
Рип Либ

Ответы:

15

Mathematica - 166 181 байт

Немного более лаконично, чем другой ответ Mathematica, отчасти благодаря стилю без очков.

c = Characters; r = Riffle;
Graphics[r[{0, 0}~Disk~# & /@ Reverse@Accumulate[
    l = {3} ~Join~ r[2 Position[c@"IVXLC", #][[1, 1]] - 1 & /@ 
        c@IntegerString[#, "Roman"], 3]], {White, Black}],
    ImageSize -> 2 Total@l] &

Все пробелы только для ясности. Это определяет анонимную функцию, которая возвращает желаемую графику.

Анимация

Анимированные круги

Создание анимированного GIF из числовых кругов тривиально в Mathematica, которая имеет встроенные функции для анимации и экспорта последовательностей произвольных объектов. Предполагая, что приведенный выше код был только что выполнен,

Table[Show[%@n, PlotRange -> {{-100, 100}, {-100, 100}}, 
    ImageSize -> 200], {n, 1, 399, 1}];
Export["animcircles.gif", %]

Пример вывода

Пример вывода

Дэвид Чжан
источник
Пожалуйста, опубликуйте несколько результатов. Извините, что не спрашиваю, это первое место. Я также изменил вопрос, чтобы принять функции.
Рип Либ
Спасибо за предложения @ MartinBüttner. Исправлен код для вывода изображений правильного размера, и добавлен пример вывода.
Дэвид Чжан
3
Твоя анимация покачивается. Не то чтобы я мог сделать лучше.
CorsiKa
Хм, ты прав. Я действительно не уверен, почему это происходит, учитывая, что я определил диапазон сюжета для Mathematica явно.
Дэвид Чжан
Может быть связано с вилянием: mathematica.stackexchange.com/q/134272
coredump
15

Обыкновенный Лисп - 376 331 304 байта

(use-package(car(ql:quickload'vecto)))(lambda(n o &aux(r 3)l p)(map()(lambda(c)(setf l(position c" I V X L C D M")p(append`((set-line-width,l)(centered-circle-path 0 0,(+(/ l 2)r))(stroke))p)r(+ r l 3)))(format()"~@R"n))(with-canvas(:width(* 2 r):height(* 2 r))(translate r r)(map()'eval p)(save-png o)))

Примеры

enter image description here(1) enter image description here(24)

enter image description here(104) enter image description here(1903) enter image description here(3999)

Анимация

Для номеров от 1 до 400:

New

NB: для записи, эта анимация выполняется следующим образом:

У меня есть измененная версия кода с именем rings которая возвращает ширину полученного изображения. Следовательно, результатом следующего цикла является максимальный размер, здесь 182 :

 (loop for x from 1 to 400
       maximize (rings x (format nil "/tmp/rings/ring~3,'0d.png" x)))

Весь цикл занимает 9,573 секунды. Это дает примерно 24 мс для каждого целого числа. Затем в оболочке:

 convert -delay 5 -loop 0 -gravity center -extent 182x182 ring*png anim.gif

Ungolfed

(ql:quickload :vecto)
(use-package :vecto)

(lambda (n o)
  (loop with r = 3
        for c across (format nil "~@R" n)
        for l = (1+ (* 2(position c"IVXLCDM")))
        for h = (/ l 2)
        collect `(,(incf r h),l) into p
        do (incf r (+ h 3))
        finally (with-canvas(:width (* 2 r) :height (* 2 r))
                  (loop for (x y) in p
                        do (set-line-width y)
                           (centered-circle-path r r x)
                           (stroke))
                  (save-png o))))

Пояснения

  • Функция принимает целое число N от 1 до 3999 и имя файла

  • Я использую, (format nil "~@R" N)чтобы преобразовать из десятичной в римскую. Например:

     (format nil "~@R" 34) => "XXXIV"
    

    ~@R Строка управления форматом задается для работы для целых чисел от 1 до 3999, поэтому существует ограничение на диапазон допустимых входных сигналов.

  • Я перебираю полученную строку, чтобы построить список, Pсодержащий(radius width) пары, для каждой цифры C.

    • Ширина - это простое линейное отображение: я использую постоянную строку «IVXLCDM», чтобы вычислить позицию C в ней. Умножая на два и добавляя один, мы получаем желаемое значение:

             (1+ (* 2 (position c "IVXLCDM")))
      

      Это, однако, сделано немного по-другому в версии для гольфа:

             (position c " I V X L C D M")
      
    • Вычисление каждого радиуса учитывает ширину каждого кольца, а также пустые пространства между кольцами. Без какой-либо оптимизации скорости вычисления остаются точными, потому что они основаны не на числах с плавающей запятой, а на рациональных числах.

      Изменить : я изменил параметры, чтобы соответствовать правилам заполнения.

  • Как только это будет сделано, я знаю требуемый размер результирующего холста (в два раза больше последнего вычисленного радиуса).

  • Наконец, я рисую круг для каждого элемента Pи сохраняю холст.
CoreDump
источник
1
Msgstr "Этот код поддерживает все римские цифры (IVXLCDM)". Означает ли это, что ваша программа использует римские цифры в качестве входных данных? Это не то, что я хотел, но довольно круто. Реквизит для анимации тоже.
Рип Либ
1
Нет, нет, извините, если это неясно: оно работает для любого целого числа от 1 до 3999. В вашем вопросе вам потребовались только входные данные от 1 до 100, и ваша таблица не содержит D или M ... Я отредактирую это часть.
coredump
8

HTML + JQuery, 288

HTML

<canvas>

JS

    r=3;w=9;c=$('canvas').get(0).getContext('2d')
    for(i=prompt(),e=100;e-.1;e/=10){
    if((x=Math.floor(i/e)%10)==4)d(w)+d(w+2)
    else if(x==9)d(w)+d(w+4)
    else{if(x>4)d(w+2)
    for(j=x%5;j;j--)d(w)}
    w-=4}
    function d(R){c.lineWidth=R
    c.beginPath()
    c.arc(150,75,r+=R/2,0,7)
    c.stroke()
    r+=R/2+3}

скрипка

TwiNight
источник
Нет фрагмента стека?
Оптимизатор
@Optimizer Полностью забыл, что у нас есть это сейчас
TwiNight
5

Ява, 565

import java.awt.*;class Z{public static void main(String[]s){int i=new Byte(s[0]),j=i/10,k=i%10;String t="",u;if(j>8)t="59";if(j>9)t="9";if(j==4)t="57";else if(j<9){t=j>4?"7":"";j-=j>4?5:0;if(j>0)t+="5";if(j>1)t+="5";if(j>2)t+="5";}if(k>8)t+="15";if(k==4)t+="13";else if(k<9){t+=k>4?"3":"";k-=k>4?5:0;if(k>0)t+="1";if(k>1)t+="1";if(k>2)t+="1";}u=t;Frame f=new Frame(){public void paint(Graphics g){g.setColor(Color.BLACK);int x=0;for(char c:u.toCharArray()){int z=c-48,q=x;for(;x<q+z;)g.drawOval(99-x,99-x,x*2,x++*2);x+=3;}}};f.setSize(200,200);f.setVisible(1>0);}}

Примеры

15

15

84

84

93

93

Отформатировано красиво:

import java.awt.*;    
class Z {    
    public static void main(String[] s) {
        int i = new Byte(s[0]), j = i / 10, k = i % 10;
        String t = "", u;
        if (j > 8)
            t = "59";
        if (j > 9)
            t = "9";
        if (j == 4) {
            t = "57";
        } else if (j < 9) {
            t = j > 4 ? "7" : "";
            j -= j > 4 ? 5 : 0;
            if (j > 0)
                t += "5";
            if (j > 1)
                t += "5";
            if (j > 2)
                t += "5";
        }
        if (k > 8)
            t += "15";
        if (k == 4) {
            t += "13";
        } else if (k < 9) {
            t += k > 4 ? "3" : "";
            k -= k > 4 ? 5 : 0;
            if (k > 0)
                t += "1";
            if (k > 1)
                t += "1";
            if (k > 2)
                t += "1";
        }
        u = t;
        Frame f = new Frame() {
            public void paint(Graphics g) {
                g.setColor(Color.BLACK);
                int x = 0;
                for (char c : u.toCharArray()) {
                    int z = c - 48, q = x;
                    for (; x < q + z;) {
                        g.drawOval(99 - x, 99 - x, x * 2, x++ * 2);
                    }
                    x += 3;
                }
            }
        };
        f.setSize(200, 200);
        f.setVisible(1 > 0);
    }
}
Ypnypn
источник
Пожалуйста, опубликуйте несколько результатов. Извините, что не спрашиваю, это первое место.
Рип Либ
3

Mathematica 9 - 301 249 байт

: D Это обманывает, используя встроенное преобразование в римские цифры, но эй.

l=Length;k=Characters;r@n_:=(w=Flatten[Position[k@"IVXLC",#]*2-1&/@k@IntegerString[n,"Roman"]];Show[Table[Graphics@{AbsoluteThickness@w[[i]],Circle[{0,0},(Join[{0},Accumulate[3+w]]+3)[[i]]+w[[i]]/2]},{i,Range@l@w}],ImageSize->{(Total@w+(l@w)*3)*2}])

(Когда я делал это прошлой ночью, у меня не было много времени, но я понял, что его можно играть в гольф намного больше. И я также взял некоторые подсказки от Дэвида Чжана ...: D Спасибо!)

Немного более четко:

l=Length;
k=Characters;
r@n_:=
    (
    w=Flatten[Position[k@"IVXLC",#]*2-1&/@k@IntegerString[n,"Roman"]];
    Show[Table[Graphics@{AbsoluteThickness@w[[i]],Circle[{0,0},(Join[{0},Accumulate[3+w]]+3)[[i]]+w[[i]]/2]},{i,Range@l@w}],ImageSize->{(Total@w+(l@w)*3)*2}]
    )

Это функция, которую вы можете вызвать так:

r[144]

enter image description here

Или вы можете показать результаты значений от a до b с помощью:Table[r[i],{i,a,b}]

Примечание : это работает только для значений до 399.

kukac67
источник
1

Python 2, 322 296

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

.. Я использую «красный» вместо «черный», потому что это экономит 2 символа :)

Here are some samples : for 23 : http://jsfiddle.net/39xmpq49/ for 42 : http://jsfiddle.net/7Ls24q9e/1/

i=input();r=9
def R(n,p):
 global r,i;i-=n;print '<circle r="{0}" stroke-width="{1}"/>'.format(r,p);r+=p+3
print '<svg viewBox="-50 -50 99 99" fill="none" stroke="red">',[[R(n,int(p)) for p in s*int(i/n)] for n,s in zip([100,90,50,40,10,9,5,4,1],'9/59/7/57/5/15/3/13/1'.split('/'))]and'','</svg>'
dieter
источник
1

JavaScript 342 334 308

function R(n){var v=document,o=[],x=1,c=v.body.appendChild(v.createElement('canvas')).getContext('2d')
while(n)v=n%10,y=x+2,o=[[],[x],[x,x],[x,x,x],[x,y],[y],[y,x],[y,x,x],[y,x,x,x],[x,x+=4]][v].concat(o),n=(n-v)/10
v=3
while(x=o.shift())c.lineWidth=x,c.beginPath(),c.arc(150,75,v+x/2,0,7),c.stroke(),v+=x+3}

for (var i = 1; i <= 100; i++) {
  R(i);
}

wolfhammer
источник