Двухцветные перекрывающиеся круги

22

Напишите программу или функцию, которая принимает следующие данные в приемлемом формате по вашему выбору:

  • Два натуральных числа W и H, которые определяют ширину и высоту изображения, которое вы будете генерировать.

  • Два цвета RGB C1 и C2, которые будут использоваться для окрашивания изображения.

  • Список из трех кортежей формы, (r, x, y)которые определяют круги с радиусом rи центром x, yв плоскости изображения. rявляется положительным целым числом и xи yявляются любыми целыми числами. Верхний левый пиксель изображения - это, 0, 0а ось x увеличивается вправо, а ось y увеличивается вниз.

Выведите изображение с размерами W по H, которое раскрашено C1 и C2 так , чтобы никакие две соседние области, определенные всеми перекрывающимися кругами, не были одного цвета.

Например: если ввод

W = 300
H = 200
C1 = (255, 200, 0)
C2 = (128, 0, 255)
Circles = (25, 50, 80), (40, 80, 120), (300, -100, 6), (17, 253, 162)

тогда границы круга выглядят так:

пример 1 границы круга

В изображении, созданном кругами, есть шесть отдельных смежных областей. Каждый регион должен быть окрашен в C1 (желтый) или C2 (фиолетовый) так, чтобы никакие два соседних региона не были одинакового цвета.

Есть два способа сделать это, их единственное отличие состоит в том, что цвета меняются местами:

пример 1 выход 1 пример 1 вывод 2

Таким образом, любое из этих двух изображений будет правильным выводом для примера ввода.

Что - то вроде этого будет недействительным выходом , так как два желтых областей граничат друг с другом.

Ваши выходные изображения должны следовать этим рекомендациям:

  • Помимо C1 и C2, третий, нейтральный цвет, такой как черный или белый, может использоваться для границ круга, если они имеют толщину не более 5 пикселей. (Черные границы толщиной в 1 пиксель присутствуют в приведенном выше примере.)

  • Однако границы кругов не обязательны. Регионы могут соседствовать друг с другом напрямую:

    пример 1 вывод 3 пример 1 вывод 4

    И то, и другое является еще одним допустимым выходом для примера выше.

  • Круги должны быть настолько точными, насколько это возможно, используя алгоритмы рисования кругов или все, что предоставляет ваша графическая библиотека.

  • В общем, пиксельное совершенство не требуется, но если входные параметры масштабируются одинаково все больше и больше, результирующее изображение должно становиться все более и более точным.

  • Сглаживание разрешено, но не обязательно.

  • Линии сетки или метки осей и т. Д. На заднем плане не допускаются.

Самый короткий код в байтах побеждает.

Больше примеров

Все используют эти входы с различными наборами кругов:

W = 100
H = 60
C1 = (255, 0, 0)
C2 = (0, 0, 255)

В любом примере цвета можно поменять местами и оставить их действительными.

Circles =
A. empty list
B. (13, 16, 20)
C. (30, 16, 20)
D. (200, 16, 20)
E. (42, 50, 20)
F. (42, 50, 20), (17, 40, 30)
G. (42, 50, 20), (17, 20, 30)
H. (42, 50, 20), (17, 10, 30), (10, 50, 30)
I. (42, 50, 20), (17, 10, 30), (35, 50, 20)
J. (18, 36, 40), (18, 63, 40), (18, 50, 20)
K. (100, -10, -20), (60, 50, -10)
L. (18, 36, 40), (18, 63, 40), (18, 50, 20), (14, 50, 20), (5, 50, 18), (20, 0, 0), (70, 22, 0), (10000, -9970, 0), (135, 100, -80) 

A. бывший B. бывший B C. бывший C D. бывший D
E. исполняемый файл F. бывший F G. бывший G H. бывший H
I. бывший я J. бывший J K. бывший К L. бывший L

Убедитесь, что ваш вывод ведет себя подобно всем этим примерам.

Кальвин Хобби
источник
Это выглядит хорошо, мы можем вывести в ascii, например, C1 равен 1, а C2 равен 0?
Мэтью Ро
@ MatthewRoh Нет. Я знаю, что это было бы удобно, но изображения требуются.
Увлечения Кэлвина
1
Хорошо, тогда, я думаю, я могу рассчитыватьtikz
Wheat Wizard
1
@MatthewRoh, netpbm - это широко используемый формат изображений на этом сайте.
Питер Тейлор
2
@ Луис Ок. Небольшие входные изменения, такие как это, или увеличение оси y, в порядке.
Увлечения Кэлвина

Ответы:

14

Mathematica, 165 байт

ContourPlot[Cos@Tr[Boole[Norm[{x,y}-#2]<#]Pi&@@@#4],{x,0,#},{y,0,#2},PlotPoints->5!,AspectRatio->Automatic,Frame->False,ContourShading->RGBColor@@@#3,Contours->{0}]&

Чистая функция, принимающая четыре аргумента: ширина, высота (оба целых числа), упорядоченная пара троек чисел от 0 до 1 (представляющих два цвета RGB) и список элементов в форме {r, {x, y}} для записи радиусов и центров круги. Например, первый пример в OP будет вызван с аргументами [300, 200, {{1, 0.784, 0}, {0.5, 0, 1}}, {{25, {50, 80}}, {40, {80, 120}}, {300, {-100, 6}}, {17, {253, 162}}}]. Положительная ось Y указывает вверх в Mathematica.

Norm[{x,y}-#2]<#определяет, находится ли точка внутри данного круга; Boole[...]Piпреобразует это Trueили Falseв πили 0. После вычисления этих πs / 0s по всем входным кружкам Trскладывает их и Cosпреобразует четные кратные от π до 1, нечетные кратные от π до –1. ContourPlot[...,Contours->{0}]затем окрашивает соответствующую область плоскости в два цвета в зависимости от того, больше или меньше значение 0. AspectRatio->Automaticделает круги похожими на круги; PlotPoints->5!дает приличную точность (повысите ее, 9!если вы действительно хотите удивительную картинку, далеко в будущем!); Frame->Falseизбавляется от осей; и ContourShading->RGBColor@@@#3использует входные цвета для контуров.

Пример вывода с первой парой цветов (поскольку они хороши), но с последним набором кругов:

образец вывода

Грег Мартин
источник
11

JavaScript / SVG / HTML5, 219 байт

f=// for demo
(w,h,b,f,a)=>`<svg width=${w} height=${h}><rect width=${w} height=${h} fill=rgb(${b}) /><path fill=rgb(${f}) fill-rule=evenodd d=${a.map(([r,x,y])=>[`M`+x,y-r+`a`+r,r,0,0,0,0,r+r+`a`+r,r,0,0,0,0,-r-r]).join``} /></svg>`
;//demo
[[`A`, []],
 [`B`, [[13, 16, 20]]],
 [`C`, [[30, 16, 20]]],
 [`D`, [[200, 16, 20]]],
 [`E`, [[42, 50, 20]]],
 [`F`, [[42, 50, 20], [17, 40, 30]]],
 [`G`, [[42, 50, 20], [17, 20, 30]]],
 [`H`, [[42, 50, 20], [17, 10, 30], [10, 50, 30]]],
 [`I`, [[42, 50, 20], [17, 10, 30], [35, 50, 20]]],
 [`J`, [[18, 36, 40], [18, 63, 40], [18, 50, 20]]],
 [`K`, [[100, -10, -20], [60, 50, -10]]],
 [`L`, [[18, 36, 40], [18, 63, 40], [18, 50, 20], [14, 50, 20], [5, 50, 18], [20, 0, 0], [70, 22, 0], [10000, -9970, 0], [135, 100, -80]]]
 ].forEach(([c, a])=>document.write(`<nobr><tt>&nbsp;${c}.&nbsp;</tt>${f(100, 60, [255, 0, 0], [0, 0, 255], a)}</nobr><wbr>`));

Нил
источник
10

BBC Basic, 120 117 байт

Скачать переводчик можно по адресу http://www.bbcbasic.co.uk/bbcwin/bbcwin.html.

I.w,h,R,G,B,r,g,b:V.22,4,19;16,r,g,b,275;16,R EORr,G EORg,B EORb,24,0;0;w;h;16
5I.r,x,y:V.25,4,x;h-y;25,154,r;0;:G.5

BBC Basic имеет ряд цветовых режимов, позволяющих строить растровую графику в соответствии с базовыми логическими операциями: OR, AND, XOR и т. Д.

Он также поддерживает перепрограммирование паллет, что означает, что, например, здесь двухцветное изображение может быть перепрограммировано в любой из 4096 цветов. Используемая здесь реализация имеет некоторые (недокументированные) отличия от исходной реализации BBC, в которых операторы EOR не потребуются.

Ungolfed

  INPUTw,h,R,G,B,r,g,b:                           :REM Input size and colours
  VDU22,4                                         :REM Change to MODE 4 (2 colours) as the default mode gives odd behaviour
  VDU19,0,16,r,g,b,19,1,16,R EORr,G EORg,B EORb   :REM Reprogram the colours to R,G,B and R^r,G^g,B^b
  VDU24,0;0;w;h;16                                :REM Setup a graphics viewport of the right size, and "clear" it to change background colour
5 INPUTr,x,y                                      :REM take input coordinates
  VDU25,4,x;h-y;                                  :REM move to x,y (h-y required as BBC BASIC y axis increases upward, reverse of spec)
  VDU25,154,r;0;                                  :REM draw circle in "logical inverse colour" of existing pixels (this implementation seems however to XOR with colour 1 instead)
  GOTO5                                           :REM repeat infinitely until user presses escape

Типичный выходной экран

Пример изображения, увеличенного в 10 раз в единицах / в 5 раз в пикселях (BBC basic использует 1 пиксель = 2 единицы).

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

Уровень реки St
источник
10

MATL , 30 29 25 байт

2ZG:i:!J*+2&!-|i<so2&!1YG

Формат ввода:

  • Цветовая карта как матрица значений от 0 до 255, где каждая строка определяет цвет
  • W
  • ЧАС
  • Вектор столбца координат центра на основе 1 в виде комплексных значений ( x - действительная часть, y - мнимая часть)
  • Столбец вектор радиусов.

Попробуйте в MATL Online! Или проверьте последний контрольный пример . (Интерпретатор все еще экспериментальный. Возможно, вам придется обновить страницу и повторить попытку, если она не работает).

объяснение

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

2ZG    % Implicitly input matrix of colors. Set as colormap
:      % Implicitly input W. Push [1 2 ... W]
i:     % Input H. Push [1 2 ... H]
!J*    % Transpose, multiply by 1i
+      % Add element-wise with broadcast. Gives H×W grid of points as
       % complex numbers, 1-based 
2&!    % Permute first dimension with the third. Gives a 1×W×H array
-|     % Implicitly input center coordinates. Subtract grid from them,
       % element-wise with broadcast. Gives a C×H×W array, where C is the
       % number of circles
i      % Input column vector of circle radii
<      % Less than, element-wise with broadcast
so     % Sum along first dimension, modulo 2. Gives a 1×W×H array
2&!    % Permute first dimension with the third. Gives a a H×W array
1YG    % Display as scaled image
Луис Мендо
источник
2
Я говорю, сохранить эти байты! : D
Грег Мартин
1
@GregMartin Вы правы. Кого волнует элегантность, когда можно сохранить 4 байта! :-) Готово
Луис Мендо
1
@LuisMendo Чем короче, тем лучше с Codegolf, независимо от того, насколько уродливым это становится. ;)
Кевин Круйссен
6

Python с использованием pypng , 140 138 байт

import png
f=lambda W,H,c,d,C:png.from_array([[[c,d][sum(abs(x-X+1j*(y-Y))<r for r,x,y in C)%2]for X in range(W)]for Y in range(H)],'RGB')

Пример использования:

W = 100
H = 60
C1 = (255, 0, 0)
C2 = (0, 0, 255)
Circles = (18, 36, 40), (18, 63, 40), (18, 50, 20), (14, 50, 20), (5, 50, 18), (20, 0, 0), (70, 22, 0), (10000, -9970, 0), (135, 100, -80)
f(W, H, C1, C2, Circles).save('test.png')

Спасибо xnor за сохранение 2 байта.

Алекс Холл
источник
Добро пожаловать в код гольф! Для проверки , если точка лежит в круге, одна хитрость заключается в использовании сложной нормы: abs(x-X+1j*(y-Y))<r.
xnor
3

Математика (неконкурентная)

(не знаю, как сделать LaTeX в PPCG, поэтому я использовал инструмент LaTeX для png)

объяснение

Произведение уравнений многократного круга ( (x-a)^2+(y-b)^2-r^2)> = 0 создаст график, в котором нуждается этот вопрос. В уравнении, nявляется размер массива, а (x, y or r)_kэто kй (x, y, or r)элемент.

пример

(0,0,2),(2,2,2)

(Спасибо, Вольфрам, Альфа)

(Неравенство сюжета от WolframAlpha)

Уравнение Get / Run для WolframAlpha

Получение сценария: завершено

Выполнение сценария: еще не выполнено

Теперь заставьте это работать с Mathematica ...

Мэтью Ро
источник
Интересно, действительно ли это?
Мэтью Ро
Вам нужно будет перечислить определенный ранее существующий интерпретатор, который отобразит выходные данные в той форме, которую вы хотели получить с учетом этого ввода. Это позволило бы посчитать байты в нем. В настоящее время проблема заключается в том, что поскольку он не привязан к интерпретатору, он не привязан к конкретному формату для представления уравнения, и, следовательно, нотация неформальна и ее невозможно сосчитать объективно. Существует множество программ для построения графиков уравнений вокруг, поэтому, возможно, стоит попытаться найти программу с кратким входным форматом.
@ ais523 Ооо. Я попытаюсь заставить это работать с WolframAlpha.
Мэтью Ро
1

Python 2.x, 166 158

import re;def f(W,H,c,d,C):print'P3',W,H,255,re.sub('[^0-9]',' ',repr([[d,c][sum([abs(x-X+1j*(y-Y))<r for r,x,y in C])%2]for Y in range(H)for X in range(W)]))

Функция генерирует файл PPM на стандартном выходе.

пример:

W = 300
H = 200
C1 = (255, 200, 0)
C2 = (128, 0, 255)
Circles = [(25, 50, 80), (40, 80, 120), (300, -100, 6), (17, 253, 162)]

f(W, H, C1, C2, Circles)

пример

Dieter
источник
1

Common Lisp + Quicklisp + ZPNG 260 + 20 = 280 символов

Это один из самых широких кодов, которые я когда-либо писал на CL, и если бы я не занимался гольфом кода, я бы реструктурировал его, чтобы его было легче читать ...

Прелюдия (20 символов)

(ql:quickload 'zpng)

Гольф (260 символов)

(lambda(w h g b c)(make-instance'zpng:png :image-data(coerce(loop :for j :below h :nconc(loop :for i :below w :append(if(evenp(count t(mapcar(lambda(c)(<(abs(complex(-(cadr c)i)(-(caddr c)j)))(car c)))c)))g b)))'(array(unsigned-byte 8)(*))):width w :height h))

Ungolfed:

(Использует defun для проверки и более длинные имена переменных для удобства чтения)

(defun mk-png (width height color1 color2 circles)
  (make-instance 'zpng:png
                 :image-data (coerce (loop :for j :below height
                                           :nconc (loop :for i :below width
                                                        :append (if (evenp (count t (mapcar (lambda (circ)
                                                                                              (< (abs (complex (- (cadr circ) i) (- (caddr circ) j)))
                                                                                                 (car circ)))
                                                                                            circles)))
                                                                    color1 color2)))
                                     '(array (unsigned-byte 8) (*)))
                 :width width
                 :height height))

Пример использования:

(let ((png (mk-png 300 200 '(255 200 0) '(128 0 255) '((25 50 80) (40 80 120) (300 -100 6) (17 253 162)))))
  (zpng:write-png png #p"path/to/file.png"))

Explaination

(lambda (circ)
   (< (abs (complex (- (cadr circ) i) (- (caddr circ) j)))
      (car circ)))

Возвращает true, если точка (i, j) попадает в данную окружность круга. Евклидово расстояние вычисляется путем взятия абсолютного значения комплексного числа, которое представляет вектор от (i, j) до центра окружности.

(evenp (count t (mapcar ___
                         circles)))

Отобразите эту функцию по списку окружностей и проверьте, попадает ли заданная точка (i, j) в четное число окружностей.

(if ____
     color1 color2)

Выберите цвет на основе этого теста.

(loop :for j :below height
       :nconc (loop :for i :below width
                    :append ____))

Соберите воедино плоский список всех байтов rgb, зацикливая каждый (i, j) на изображении и добавляя полученные списки вместе.

(coerce ____
         '(array (unsigned-byte 8) (*)))

Преобразуйте этот список байтов в правильный массив байтов, чтобы zpng мог его правильно принять.

(make-instance 'zpng:png
                :image-data ____
                :width width
                :height height)

Создайте объект png.

(defun mk-png (width height color1 color2 circles)
   ___)

Создайте функцию, которая будет принимать ширину, высоту, два цвета и список окружностей и возвращать созданный объект png.

djeis
источник
0

JavaScript (ES6), 224 байта

Я видел решение JS + SVG, но мне просто нужно было создать решение на основе холста ;-) Это функция, которая возвращает элемент холста. Если можно предоставить существующий элемент canvas, удалите 40 байт.

Звоните как f(width, height, [[r1, g1, b1], [r2, g2, b2]], [[r1, x1, y1], [r2, x2, y2], ...])

let f =
(w,h,a,c,O=document.createElement`canvas`)=>{O.width=w;O.height=h;C=O.getContext`2d`;for(y=0;y<h;y++)for(x=0;x<w;x++)C.fillStyle=`rgb(${a[c.filter(([R,X,Y])=>(X-x)**2+(Y-y)**2<R**2).length%2]})`,C.fillRect(x,y,1,1);return O}

let tests = A.innerHTML.match(/.+/g);
A.innerHTML = "";
for (let i of tests) {
  let p = document.createElement("span");
  p.innerHTML = "<br>" + i.slice(0, 3);
  p.style["font-family"] = "monospace";
  A.append(p);
  A.append(f(100, 60, [[255,0,0], [0,0,255]],
    eval(`[${ i.slice(3).replace(/\(/g, "[").replace(/\)/g, "]") }]`)
  ));
}
<div id=A>
A. 
B. (13, 16, 20)
C. (30, 16, 20)
D. (200, 16, 20)
E. (42, 50, 20)
F. (42, 50, 20), (17, 40, 30)
G. (42, 50, 20), (17, 20, 30)
H. (42, 50, 20), (17, 10, 30), (10, 50, 30)
I. (42, 50, 20), (17, 10, 30), (35, 50, 20)
J. (18, 36, 40), (18, 63, 40), (18, 50, 20)
K. (100, -10, -20), (60, 50, -10)
L. (18, 36, 40), (18, 63, 40), (18, 50, 20), (14, 50, 20), (5, 50, 18), (20, 0, 0), (70, 22, 0), (10000, -9970, 0), (135, 100, -80)
</div>

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

двухцветные круги

ETHproductions
источник
0

Löve2D , 353 байта.

o=love.graphics
a=arg
w,h,r,g,b,R,G,B=...c={}for i=9,#a,3 do
c[#c+1]={a[i],a[i+1],a[i+2]}end
C=o.newCanvas(w,h)o.setCanvas(C)o.clear(R,G,B)for k,v in pairs(c)do
o.stencil(function()o.circle("fill",v[2],v[3],v[1],9^3)end,"invert",1,true)end
o.setStencilTest("greater",0)o.setColor(r,g,b)o.rectangle("fill",0,0,w,h)local
C:newImageData():encode("png","c")
Ataco
источник