Círculos superpuestos de dos colores


22

Escriba un programa o función que tome la siguiente entrada en un formato razonable de su elección:

  • Dos enteros positivos W y H que definen el ancho y la altura de la imagen que generará.

  • Dos colores RGB C1 y C2 que se usarán para colorear la imagen.

  • Una lista de 3 tuplas de la forma (r, x, y)que definen círculos con radio ry centro x, yen el plano de la imagen. res un número entero positivo xy yes cualquier número entero . El píxel superior izquierdo de la imagen es 0, 0y el eje x aumenta a la derecha y el eje y aumenta hacia abajo.

Imprima una imagen con dimensiones W por H que esté coloreada con C1 y C2 de modo que no haya dos regiones vecinas definidas por todos los círculos superpuestos que sean del mismo color.

Por ejemplo: si la entrada es

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)

entonces los límites del círculo se ven así:

ejemplo 1 límites del círculo

Hay seis regiones distintas y contiguas en la imagen creada por los círculos. Cada región debe estar coloreada con C1 (amarillo) o C2 (púrpura) de modo que no haya dos regiones vecinas del mismo color.

Hay dos formas de hacer esto, la única diferencia es que los colores se intercambian:

ejemplo 1 salida 1 ejemplo 1 salida 2

Por lo tanto, cualquiera de estas dos imágenes sería una salida válida para la entrada de ejemplo.

Algo como esto sería una salida no válida ya que dos regiones amarillas se unen entre sí.

Sus imágenes de salida deben seguir estas pautas:

  • Además de C1 y C2, se puede usar un tercer color neutro, como el negro o el blanco, para los límites de los círculos, siempre que no tengan más de 5 píxeles de grosor. (Los límites negros de 1 píxel de grosor están presentes en el ejemplo anterior).

  • Sin embargo, no se requieren límites de círculos. Las regiones pueden ser vecinas entre sí directamente:

    ejemplo 1 salida 3 ejemplo 1 salida 4

    Ambos son otro resultado válido para el ejemplo anterior.

  • Los círculos deben ser tan precisos como sea razonablemente posible, utilizando algoritmos de dibujo de círculos o lo que proporcione su biblioteca de gráficos.

  • En general, no se requiere la perfección de píxeles, pero si los parámetros de entrada se escalan cada vez más, la imagen resultante debería ser más y más precisa.

  • El suavizado está permitido pero no es obligatorio.

  • Las cuadrículas o etiquetas de eje, etc. en el fondo no están permitidas.

El código más corto en bytes gana.

Más ejemplos

Todos usan estas entradas con diferentes conjuntos de círculos:

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

En cualquier ejemplo, los colores se pueden intercambiar y seguir siendo válidos.

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. ex A B. ex B C. Exc ª D. ex D
E. exe F. ex F G. ex G H. ex H
I. ex yo J. ex J K. ex K L. ex L

Asegúrese de que su salida se comporte de manera similar a todos estos ejemplos.


Se ve bien, ¿podemos generar en ascii, por ejemplo C1 es 1 y C2 es 0?
Matthew Roh

@MatthewRoh No. Sé que sería conveniente, pero se requieren imágenes.
Calvin's Hobbies

1
Ok, entonces creo que puedo contartikz
Wheat Wizard

1
@MatthewRoh, netpbm es un formato de imagen de uso común en este sitio.
Peter Taylor

2
@Luis Ok. Pequeñas variaciones de entrada como esa o hacer que el eje y suba están bien.
Calvin's Hobbies

Respuestas:


14

Mathematica, 165 bytes

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

Función pura que toma cuatro argumentos: el ancho, la altura (ambos enteros), un par ordenado de triples números entre 0 y 1 (que representan los dos colores RGB) y una lista de elementos de la forma {r, {x, y}}para registrar los radios y centros de los círculos Por ejemplo, el primer ejemplo en el OP se llamaría con los argumentos [300, 200, {{1, 0.784, 0}, {0.5, 0, 1}}, {{25, {50, 80}}, {40, {80, 120}}, {300, {-100, 6}}, {17, {253, 162}}}]. El eje y positivo apunta hacia arriba en Mathematica.

Norm[{x,y}-#2]<#detecta si un punto está dentro de un círculo dado; Boole[...]Piconvierte eso Trueo Falseto πor 0. Después de calcular esos πs / 0s en todos los círculos de entrada, los Trsuma y Cosconvierte los múltiplos pares de π a 1, los múltiplos impares de π a –1. ContourPlot[...,Contours->{0}]luego colorea la región apropiada del plano en dos colores dependiendo de si el valor es mayor o menor que 0. AspectRatio->Automatichace que los círculos parezcan círculos; PlotPoints->5!le da una precisión decente (¡aumente 9!si realmente desea una imagen increíble, lejos en el futuro!); Frame->Falsese deshace de los ejes; y ContourShading->RGBColor@@@#3usa los colores de entrada para los contornos.

Salida de muestra, con el primer par de colores (ya que son agradables) pero el último conjunto de círculos:

salida de muestra


11

JavaScript / SVG / HTML5, 219 bytes

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 básicos, 120 117 bytes

Descargue el intérprete en 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 tiene una gama de modos de color que le permite trazar gráficos ráster de acuerdo con operaciones lógicas básicas: OR, AND, XOR, etc.

También admite la reprogramación de paletas, lo que significa que, por ejemplo, aquí una imagen de 2 colores puede reprogramar sus colores a cualquiera de los 4096 colores. La implementación utilizada aquí tiene algunas diferencias (no documentadas) de la implementación original de la BBC, en la cual los operadores EOR no serían necesarios.

Sin golf

  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

Pantalla de salida típica

Imagen de ejemplo ampliada por un factor de 10 en unidades / factor de 5 en píxeles (BBC basic utiliza 1 píxel = 2 unidades).

ingrese la descripción de la imagen aquí


10

MATL , 30 29 25 bytes

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

Formato de entrada:

  • Mapa de colores como una matriz de valores entre 0 y 255, donde cada fila define un color
  • W
  • H
  • Vector de columna de coordenadas centrales basadas en 1 como valores complejos ( x es la parte real, y es la parte imaginaria)
  • Vector de columna de radios.

¡Pruébelo en MATL Online! O verificar el último caso de prueba . (El intérprete aún es experimental. Es posible que deba actualizar la página e intentar nuevamente si no funciona).

Explicación

El código usa números complejos para definir la cuadrícula de puntos y calcular distancias, y hace un uso intensivo de las operaciones de matriz con la transmisión .

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
¡Digo Guardar esos bytes! : D
Greg Martin

1
@ GregMartin Tienes razón. ¡A quién le importa la elegancia cuando se pueden guardar 4 bytes! :-) Hecho
Luis Mendo

1
@LuisMendo Cuanto más corto, mejor con codegolf, no importa cuán feo se vuelva. ;)
Kevin Cruijssen

6

Python usando pypng , 140 138 bytes

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

Ejemplo de uso:

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

Gracias a xnor por guardar 2 bytes.


Bienvenido a code golf! Para comprobar si un punto se encuentra en un círculo, un truco es utilizar norma compleja: abs(x-X+1j*(y-Y))<r.
xnor

3

Matemáticas (no competidoras)

(No sé cómo hacer LaTeX en PPCG, así que utilicé una herramienta LaTeX to png)

Explicación

El producto de ecuaciones de círculo múltiple ( (x-a)^2+(y-b)^2-r^2)> = 0 hará un gráfico que esta pregunta necesita. En la ecuación, nes el tamaño de la matriz y (x, y or r)_kes el elemento kth (x, y, or r).

Ejemplo

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

(Gracias WolframAlpha)

(Gráfico de desigualdad de WolframAlpha)

Obtener / Ejecutar ecuación para WolframAlpha

Obteniendo guión: Completo

Ejecución de script: aún no ha terminado

Ahora haz que funcione con Mathematica ...


Me pregunto si esto es válido?
Matthew Roh

Tendría que enumerar un intérprete preexistente específico que trazaría la salida en la forma que deseaba dada esa entrada. Eso permitiría contar los bytes que contiene. En la actualidad, el problema es que debido a que no está vinculado a un intérprete, no está vinculado a un formato específico para representar la ecuación y, por lo tanto, la notación es informal e imposible de contar objetivamente. Hay muchos programas para trazar gráficos de ecuaciones, por lo que puede valer la pena intentar encontrar uno con un formato de entrada conciso.

@ ais523 Ohh. Intentaré que funcione con WolframAlpha.
Matthew Roh

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

La función genera un archivo PPM en la salida estándar.

ejemplo:

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)

ejemplo


1

Common Lisp + Quicklisp + ZPNG 260 + 20 = 280 caracteres

Este es uno de los códigos más amplios que he escrito en CL, y si no estuviera haciendo un código de golf, lo habría reestructurado para que sea mucho más fácil de leer ...

Preludio (20 caracteres)

(ql:quickload 'zpng)

Golfizado (260 caracteres)

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

Sin golf:

(Utiliza defun para permitir pruebas y nombres de variables más largos para facilitar la lectura)

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

Ejemplo de uso:

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

Explicación

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

Devuelve verdadero si el punto (i, j) cae dentro del círculo del círculo dado. La distancia euclidiana se calcula tomando el valor absoluto del número complejo que representa el vector desde (i, j) hasta el centro del círculo.

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

Asigne esa función en la lista de círculos y verifique si el punto dado (i, j) se encuentra dentro de un número par de círculos.

(if ____
     color1 color2)

Seleccione el color basado en esa prueba.

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

Reúna una lista plana de todos los bytes rgb haciendo un bucle sobre cada (i, j) en la imagen y agregando las listas resultantes.

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

Convierta esa lista de bytes en una matriz adecuada de bytes, para que zpng pueda ingerirla correctamente.

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

Crea el objeto png.

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

Cree la función para tomar el ancho, la altura, dos colores y la lista de círculos y devolver el objeto png creado.


0

JavaScript (ES6), 224 bytes

Vi la solución JS + SVG, pero solo tuve que crear una solución basada en lienzo ;-) Esta es una función que devuelve un elemento de lienzo. Si se puede proporcionar un elemento de lienzo existente, elimine 40 bytes.

Llamar como 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>

Salida de ejemplo:

círculos de dos colores


0

Löve2D , 353 Bytes.

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")
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.