Círculos sobrepostos de duas cores

22

Escreva um programa ou função que receba as seguintes entradas em um formato razoável de sua escolha:

  • Dois números inteiros positivos W e H que definem a largura e a altura da imagem que você irá gerar.

  • Duas cores RGB C1 e C2 que serão usadas para colorir a imagem.

  • Uma lista de três tuplas do formulário (r, x, y)que definem círculos com raio re centro x, yno plano da imagem. rÉ um número inteiro positivo e xe ysão quaisquer inteiros. O pixel superior esquerdo da imagem é 0, 0e o eixo x aumenta para a direita e o eixo y aumenta para baixo.

Envie uma imagem com as dimensões W por H coloridas com C1 e C2, de modo que não haja duas regiões vizinhas definidas por todos os círculos sobrepostos da mesma cor.

Por exemplo: Se a entrada for

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)

então os limites do círculo ficam assim:

exemplo 1 limites do círculo

Existem seis regiões distintas e contíguas na imagem criada pelos círculos. Cada região deve ser colorida com C1 (amarelo) ou C2 (roxo), de modo que não haja duas regiões vizinhas da mesma cor.

Há duas maneiras de fazer isso, sua única diferença é que as cores são trocadas:

exemplo 1 saída 1 exemplo 1 saída 2

Assim, qualquer uma dessas duas imagens seria saída válida para a entrada de exemplo.

Algo parecido com isso seria saída inválida, pois duas regiões amarelas são vizinhas.

Suas imagens de saída devem seguir estas diretrizes:

  • Além de C1 e C2, uma terceira cor neutra, como preto ou branco, pode ser usada para os limites do círculo, desde que não tenham mais que 5 pixels de espessura. (Os limites pretos de 1 pixel de espessura estão presentes no exemplo acima.)

  • Os limites dos círculos não são necessários, no entanto. As regiões podem se vizinhos diretamente:

    exemplo 1 saída 3 exemplo 1 saída 4

    Ambos são outra saída válida para o exemplo acima.

  • Os círculos devem ser o mais precisos possível, usando algoritmos de desenho de círculo ou o que sua biblioteca de gráficos fornecer.

  • Em geral, a perfeição de pixels não é necessária, mas se os parâmetros de entrada forem redimensionados igualmente cada vez maiores, a imagem resultante deverá se tornar cada vez mais precisa.

  • Anti-aliasing é permitido, mas não obrigatório.

  • Linhas de grade ou rótulos de eixos etc. em segundo plano não são permitidos.

O código mais curto em bytes vence.

Mais exemplos

Todos usando essas entradas com diferentes conjuntos de círculos:

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

Em qualquer exemplo, as cores podem ser trocadas e permanecem válidas.

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. ex C D. ex D
E. Exe F. ex F G. ex G H. ex H
I. ex eu J. ex J K. ex K L. ex L

Verifique se sua saída se comporta de maneira semelhante a todos esses exemplos.

Passatempos de Calvin
fonte
Parece bom, podemos produzir em ASCII, por exemplo, C1 é 1 e C2 é 0?
Matthew Roh
@MatthewRoh Não. Eu sei que seria conveniente, mas são necessárias imagens.
Hobbies de Calvin
1
Ok, então eu acho que posso contartikz
Wheat Wizard
1
@MatthewRoh, netpbm é um formato de imagem comumente usado neste site.
Peter Taylor
2
@Luis Ok. Pequenas variações de entrada como essa ou a elevação do eixo y estão boas.
Hobbies de Calvin

Respostas:

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

Função pura usando quatro argumentos: a largura, a altura (ambos os números inteiros), um par ordenado de triplos de números entre 0 e 1 (representando as duas cores RGB) e uma lista de itens do formulário {r, {x, y}}para registrar os raios e centros de os círculos. Por exemplo, o primeiro exemplo no OP seria chamado com os argumentos [300, 200, {{1, 0.784, 0}, {0.5, 0, 1}}, {{25, {50, 80}}, {40, {80, 120}}, {300, {-100, 6}}, {17, {253, 162}}}]. O eixo y positivo aponta para cima no Mathematica.

Norm[{x,y}-#2]<#detecta se um ponto está dentro de um determinado círculo; Boole[...]Piconverte isso Trueou Falsepara πou 0. Após calcular esses πs / 0s em todos os círculos de entrada, Trsome-os e Cosconverta múltiplos pares de π em 1, múltiplos ímpares de π em –1. ContourPlot[...,Contours->{0}]em seguida, pinte a região apropriada do plano em duas cores, dependendo se o valor for maior ou menor que 0. AspectRatio->Automaticfaz círculos parecerem círculos; PlotPoints->5!fornece uma precisão decente (aumente-a 9!se você realmente quiser uma imagem incrível, no futuro!); Frame->Falsese livra dos eixos; e ContourShading->RGBColor@@@#3usa as cores de entrada para os contornos.

Exemplo de saída, com o primeiro par de cores (uma vez que são legais), mas o último conjunto de círculos:

saída de amostra

Greg Martin
fonte
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>`));

Neil
fonte
10

BBC Basic, 120 117 bytes

Faça o download do intérprete em 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

O BBC Basic possui uma variedade de modos de cores, permitindo plotar gráficos de varredura de acordo com operações lógicas básicas: OR, AND, XOR etc.

Ele também suporta reprogramação de paleta, o que significa que, por exemplo, aqui uma imagem de duas cores pode ter suas cores reprogramadas para qualquer uma das 4096 cores. A implementação usada aqui tem algumas diferenças (não documentadas) em relação à implementação original da BBC, na qual os operadores de EOR não seriam necessários.

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

Tela de saída típica

Imagem de exemplo ampliada por um fator de 10 em unidades / fator de 5 em pixels (a BBC basic usa 1 pixel = 2 unidades).

insira a descrição da imagem aqui

Level River St
fonte
10

MATL , 30 29 25 bytes

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

Formato de entrada:

  • Mapa de cores como uma matriz de valores entre 0 e 255, em que cada linha define uma cor
  • W
  • H
  • Vetor de coluna de coordenadas centrais com base em 1 como valores complexos ( x é a parte real, y é a parte imaginária)
  • Vetor de coluna de raios.

Experimente o MATL Online! Ou verifique o último caso de teste . (O intérprete ainda é experimental. Pode ser necessário atualizar a página e tentar novamente se não funcionar).

Explicação

O código usa números complexos para definir a grade de pontos e calcular distâncias e faz uso pesado de operações de matriz com transmissão .

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
Luis Mendo
fonte
2
Eu digo Salvar esses bytes! : D
Greg Martin
1
@GregMartin Você está certo. Quem se importa com a elegância quando 4 bytes podem ser salvos! :-) Concluído
Luis Mendo
1
@LuisMendo Quanto menor, melhor com o codegolf, por mais feio que seja. ;)
Kevin Cruijssen 13/03/19
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')

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

Obrigado ao xnor por salvar 2 bytes.

Alex Hall
fonte
Bem-vindo ao código de golfe! Para verificar se um ponto está em um círculo, um truque é usar norma complexa: abs(x-X+1j*(y-Y))<r.
xnor
3

Matemática (não competitiva)

(idk como fazer LaTeX em PPCG, então eu usei uma ferramenta LaTeX para png)

Explicação

O produto de múltiplas equações circulares ( (x-a)^2+(y-b)^2-r^2)> = 0 fará um gráfico necessário para esta pergunta. Na equação, né o tamanho da matriz e (x, y or r)_ké o elemento kth (x, y, or r).

Exemplo

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

(Obrigado WolframAlpha)

(Gráfico de desigualdade de WolframAlpha)

Obter / Executar equação para WolframAlpha

Obtendo o script: Completo

Script em execução: ainda não concluído

Agora faça funcionar com o Mathematica ...

Matthew Roh
fonte
Gostaria de saber se isso é válido?
Matthew Roh
Você precisaria listar um intérprete preexistente específico que plotaria a saída no formato que você queria, com base nessa entrada. Isso tornaria possível contar os bytes nele. No momento, o problema é que, como não está vinculado a um intérprete, não está vinculado a um formato específico para representar a equação e, portanto, a notação é informal e impossível de contar objetivamente. Existem muitos programas para plotar gráficos de equações, portanto vale a pena tentar encontrar um com um formato de entrada conciso.
@ ais523 Ohh. Vou tentar fazê-lo funcionar com o WolframAlpha.
Matthew Roh 23/03
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)]))

A função gera um arquivo PPM na saída padrão.

exemplo:

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)

exemplo

dieter
fonte
1

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

Este é um dos códigos mais amplos que já escrevi no CL, e se não estivesse fazendo um código de golfe, teria reestruturado isso para facilitar a leitura ...

Prelúdio (20 caracteres)

(ql:quickload 'zpng)

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

Ungolfed:

(Utiliza defun para permitir testes e nomes de variáveis ​​mais longos para facilitar a leitura)

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

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

Explicação

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

Retorna true se o ponto (i, j) se encaixar dentro do circulo dado. A distância euclidiana é calculada tomando o valor absoluto do número complexo que representa o vetor de (i, j) até o centro do circ.

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

Mapeie essa função na lista de círculos e verifique se o ponto especificado (i, j) se enquadra em um número par de círculos.

(if ____
     color1 color2)

Selecione a cor com base nesse teste.

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

Colete uma lista simples de todos os bytes rgb fazendo um loop sobre cada (i, j) na imagem e anexando as listas resultantes.

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

Converta essa lista de bytes em uma matriz adequada de bytes, para que o zpng possa ingeri-la corretamente.

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

Crie o objeto png.

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

Crie a função para obter a largura, altura, duas cores e lista de círculos e retornar o objeto png criado.

djeis
fonte
0

JavaScript (ES6), 224 bytes

Eu vi a solução JS + SVG, mas eu apenas tive que criar uma solução baseada em tela ;-) Esta é uma função que retorna um elemento de tela. Se um elemento de tela existente puder ser fornecido, remova 40 bytes.

Ligue 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>

Exemplo de saída:

círculos bicolores

ETHproductions
fonte
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")
ATaco
fonte