Dwukolorowe nakładające się koła

22

Napisz program lub funkcję, która przyjmuje następujące dane wejściowe w rozsądnym wybranym formacie:

  • Dwie dodatnie liczby całkowite W i H, które określają szerokość i wysokość generowanego obrazu.

  • Dwa kolory RGB C1 i C2, które zostaną użyte do pokolorowania obrazu.

  • Lista 3-krotek formularza, (r, x, y)które definiują koła o promieniu ri środku x, yw płaszczyźnie obrazu. rjest dodatnią liczbą całkowitą xi ysą dowolnymi liczbami całkowitymi. Lewy górny piksel obrazu jest, 0, 0a oś x zwiększa się w prawo, a oś y zwiększa się w dół.

Wyjście obrazu o wymiarach W przez H, który jest zabarwiony za pomocą C1 i C2 w taki sposób, że żadne dwa sąsiednie regiony zdefiniowane przez wszystkie nakładające się koła nie są tego samego koloru.

Na przykład: Jeśli dane wejściowe to

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)

wtedy granice okręgu wyglądają tak:

przykład 1 granice okręgu

Na obrazie utworzonym przez kręgi znajduje się sześć odrębnych, ciągłych regionów. Każdy region musi być zabarwiony za pomocą C1 (żółty) lub C2 (fioletowy), aby żadne dwa sąsiednie regiony nie były tego samego koloru.

Można to zrobić na dwa sposoby, a jedyną różnicą jest zamiana kolorów:

przykład 1 wyjście 1 przykład 1 wyjście 2

Zatem każdy z tych dwóch obrazów byłby prawidłowym wyjściem dla przykładowego wejścia.

Coś jak to byłoby nieważne wyjście ponieważ dwie żółte regionów sąsiada siebie.

Obrazy wyjściowe powinny być zgodne z następującymi wskazówkami:

  • Oprócz C1 i C2 można zastosować trzeci, neutralny kolor, taki jak czarny lub biały, do granic okręgu, o ile nie mają one więcej niż 5 pikseli grubości. (Czarne granice o grubości 1 piksela są obecne w powyższym przykładzie).

  • Granice kręgów nie są jednak wymagane. Regiony mogą sąsiadować bezpośrednio:

    przykład 1 wyjście 3 przykład 1 wyjście 4

    Oba są kolejnymi prawidłowymi danymi wyjściowymi do powyższego przykładu.

  • Koła powinny być tak dokładne, jak to możliwe, przy użyciu algorytmów rysowania okręgów lub czegokolwiek, co zapewnia biblioteka graficzna.

  • Zasadniczo perfekcja pikseli nie jest wymagana, ale jeśli parametry wejściowe są skalowane jednakowo coraz bardziej, otrzymany obraz powinien być coraz bardziej dokładny.

  • Wygładzanie jest dozwolone, ale nie wymagane.

  • Linie siatki lub etykiety osi itp. W tle są niedozwolone.

Najkrótszy kod w bajtach wygrywa.

Więcej przykładów

Wszystkie używają tych danych wejściowych z różnymi zestawami kół:

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

W każdym przykładzie kolory mogą być zamieniane i pozostają ważne.

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

Upewnij się, że dane wyjściowe zachowują się podobnie do wszystkich tych przykładów.

Hobby Calvina
źródło
Wygląda ładnie, czy możemy wyprowadzać w ascii, na przykład C1 to 1, a C2 to 0?
Matthew Roh
@MatthewRoh Nie. Wiem, że byłoby to wygodne, ale wymagane są zdjęcia.
Calvin's Hobbies
1
Ok, więc chyba mogę liczyć tikz
Wheat Wizard
1
@MatthewRoh, netpbm jest powszechnie używanym formatem obrazu na tej stronie.
Peter Taylor,
2
@Luis Ok. Małe odmiany wejściowe lub takie, w których oś Y idzie w górę, są w porządku.
Hobby Calvina

Odpowiedzi:

14

Mathematica, 165 bajtów

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

Czysta funkcja pobierająca cztery argumenty: szerokość, wysokość (obie liczby całkowite), uporządkowaną parę trójek liczb od 0 do 1 (reprezentujących dwa kolory RGB) oraz listę elementów formularza {r, {x, y}}do rejestrowania promieni i środków koła Na przykład pierwszy przykład w PO zostałby wywołany z argumentami [300, 200, {{1, 0.784, 0}, {0.5, 0, 1}}, {{25, {50, 80}}, {40, {80, 120}}, {300, {-100, 6}}, {17, {253, 162}}}]. Dodatnia oś Y wskazuje w górę w Mathematica.

Norm[{x,y}-#2]<#wykrywa, czy punkt znajduje się w danym okręgu; Boole[...]Pikonwertuje to Truelub Falsenaπ lub 0. Po obliczeniu πs / 0s we wszystkich okręgach wejściowych, Trdodaje je i Coskonwertuje parzyste wielokrotności π na 1, nieparzyste wielokrotności π na –1. ContourPlot[...,Contours->{0}]następnie koloruje odpowiedni obszar płaszczyzny w dwóch kolorach w zależności od tego, czy wartość jest większa czy mniejsza niż0 . AspectRatio->Automaticsprawia, że ​​koła wyglądają jak koła; PlotPoints->5!daje przyzwoitą dokładność (zwiększ ją, 9!jeśli naprawdę chcesz niesamowitego obrazu w dalekiej przyszłości!); Frame->Falsepozbywa się osi; i ContourShading->RGBColor@@@#3używa kolorów wejściowych dla konturów.

Przykładowe dane wyjściowe z pierwszą parą kolorów (ponieważ są ładne), ale ostatnim zestawem kół:

sample output

Greg Martin
źródło
11

JavaScript / SVG / HTML5, 219 bajtów

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
źródło
10

BBC Basic, 120 117 bajtów

Pobierz tłumacza na 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 ma szereg trybów kolorów, umożliwiających kreślenie grafiki rastrowej zgodnie z podstawowymi operacjami logicznymi: OR, AND, XOR itp.

Obsługuje również przeprogramowanie palet, co oznacza, że ​​na przykład tutaj obraz dwukolorowy może zostać przeprogramowany na dowolny z 4096 kolorów. Zastosowana tutaj implementacja ma pewne (nieudokumentowane) różnice w stosunku do oryginalnej implementacji BBC, w których operatorzy EOR nie byliby potrzebni.

Nie golfił

  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

Typowy ekran wyjściowy

Przykładowy obraz powiększony o współczynnik 10 w jednostkach / współczynnik 5 w pikselach (BBC basic używa 1 piksela = 2 jednostki).

wprowadź opis zdjęcia tutaj

Level River St
źródło
10

MATL , 30 29 25 bajtów

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

Format wejściowy:

  • Colormap jako macierz wartości od 0 do 255, gdzie każdy wiersz określa kolor
  • W.
  • H.
  • Wektor kolumny współrzędnych centralnych opartych na 1 jako wartości zespolone ( x jest częścią rzeczywistą, y jest częścią urojoną)
  • Wektor kolumny promieni.

Wypróbuj w MATL Online! Lub sprawdź ostatni przypadek testowy . (Tłumacz jest nadal w fazie eksperymentalnej. Może być konieczne odświeżenie strony i spróbuj ponownie, jeśli nie działa).

Wyjaśnienie

Kod używa liczb zespolonych do definiowania siatki punktów i obliczania odległości oraz intensywnie wykorzystuje operacje tablicowe z rozgłaszaniem .

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
źródło
2
Mówię: Ratuj te bajty! : D
Greg Martin
1
@GregMartin Masz rację. Kogo obchodzi elegancja, gdy można zaoszczędzić 4 bajty! :-) Zrobione
Luis Mendo,
1
@LuisMendo Im krócej, tym lepiej z codegolfem, bez względu na to, jak brzydki się staje. ;)
Kevin Cruijssen
6

Python używający pypng , 140 138 bajtów

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

Przykładowe użycie:

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

Dzięki xnor za zapisanie 2 bajtów.

Alex Hall
źródło
Witamy w Code Golf! Do sprawdzania, czy punkt leży w kręgu, jedna sztuczka jest użycie złożoną normę: abs(x-X+1j*(y-Y))<r.
xnor
3

Matematyka (nie konkuruje)

(idk jak zrobić LaTeX w PPCG, więc użyłem narzędzia LaTeX do png)

Wyjaśnienie

Iloczyn równań wielokrotnych okręgu ( (x-a)^2+(y-b)^2-r^2)> = 0 utworzy wykres, którego potrzebuje to pytanie. W równaniu njest rozmiarem tablicy i (x, y or r)_kjest kth(x, y, or r) elementem.

Przykład

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

(Dziękuję WolframAlpha)

(Wykres nierówności autorstwa WolframAlpha)

Pobierz / Uruchom równanie dla WolframAlpha

Pobieranie skryptu: zakończone

Uruchomiony skrypt: jeszcze nie zrobione

Teraz spraw, aby działał z Mathematica ...

Matthew Roh
źródło
Zastanawiam się, czy to jest ważne?
Matthew Roh
Musisz podać konkretny wcześniej istniejący interpreter, który wykreśli dane wyjściowe w żądanej formie, biorąc pod uwagę te dane wejściowe. Umożliwiłoby to policzenie bajtów. Obecnie problem polega na tym, że ponieważ nie jest powiązany z tłumaczem, nie jest powiązany z konkretnym formatem reprezentującym równanie, a zatem notacja jest nieformalna i niemożliwa do obiektywnego policzenia. Istnieje wiele programów do rysowania wykresów równań, więc warto spróbować znaleźć taki z krótkim formatem wejściowym.
@ ais523 Ohh. Spróbuję, aby działał z 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)]))

Funkcja generuje plik PPM na standardowym wyjściu.

przykład:

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)

przykład

dieter
źródło
1

Common Lisp + Quicklisp + ZPNG 260 + 20 = 280 znaków

Jest to jeden z najszerszych kodów, jakie kiedykolwiek napisałem w CL, a gdybym nie grał w golfa kodowego, zrestrukturyzowałbym to, aby ułatwić czytanie ...

Preludium (20 znaków)

(ql:quickload 'zpng)

Gra w golfa (260 znaków)

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

Nie golfowany:

(Używa defun, aby umożliwić testowanie i dłuższe nazwy zmiennych dla czytelności)

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

Przykładowe użycie:

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

Wyjaśnienie

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

Zwraca true, jeśli punkt (i, j) mieści się w danym okręgu okręgu. Odległość euklidesowa jest obliczana przez przyjęcie wartości bezwzględnej liczby zespolonej, która reprezentuje wektor od (i, j) do środka obwodu.

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

Zamapuj tę funkcję na liście okręgów i sprawdź, czy dany punkt (i, j) mieści się w parzystej liczbie okręgów.

(if ____
     color1 color2)

Wybierz kolor na podstawie tego testu.

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

Zbierz razem płaską listę wszystkich bajtów rgb, zapętlając każdy z nich (i, j) na obrazie i łącząc razem powstałe listy.

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

Konwertuj tę listę bajtów na odpowiednią tablicę bajtów, aby zpng mógł poprawnie ją przetworzyć.

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

Utwórz obiekt png.

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

Utwórz funkcję, aby pobrać szerokość, wysokość, dwa kolory i listę okręgów, i zwróć utworzony obiekt png.

djeis
źródło
0

JavaScript (ES6), 224 bajty

Widziałem rozwiązanie JS + SVG, ale po prostu musiałem stworzyć rozwiązanie oparte na kanwie ;-) Jest to funkcja zwracająca element canvas. Jeśli można podać istniejący element canvas, usuń 40 bajtów.

Zadzwoń jak 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>

Przykładowe dane wyjściowe:

dwukolorowe koła

ETHprodukcje
źródło
0

Löve2D , 353 bajtów.

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
źródło