Zweifarbige überlappende Kreise

22

Schreiben Sie ein Programm oder eine Funktion, die die folgende Eingabe in einem angemessenen Format Ihrer Wahl aufnimmt:

  • Zwei positive ganze Zahlen W und H, die die Breite und Höhe des zu erzeugenden Bildes definieren.

  • Zwei RGB-Farben C1 und C2, mit denen das Bild eingefärbt wird.

  • Eine Liste von 3 Tupeln des Formulars (r, x, y), die Kreise mit Radius rund Mittelpunkt x, yin der Bildebene definieren . rist eine positive ganze Zahl und xund ysind beliebige ganze Zahlen. Das obere linke Pixel des Bildes ist 0, 0und die x-Achse steigt nach rechts und die y-Achse steigt nach unten.

Geben Sie ein Bild mit den Abmessungen W bis H aus, das mit C1 und C2 so gefärbt ist, dass keine zwei benachbarten Bereiche, die durch alle überlappenden Kreise definiert sind, die gleiche Farbe haben.

Zum Beispiel: Wenn die Eingabe ist

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)

dann sehen die Kreisgrenzen so aus:

Beispiel 1 Kreisgrenzen

In dem von den Kreisen erzeugten Bild gibt es sechs verschiedene, zusammenhängende Bereiche. Jede Region muss mit C1 (gelb) oder C2 (lila) so gefärbt sein, dass keine zwei benachbarten Regionen dieselbe Farbe haben.

Hierfür gibt es zwei Möglichkeiten. Der einzige Unterschied besteht darin, dass die Farben vertauscht werden:

Beispiel 1 Ausgabe 1 Beispiel 1 Ausgabe 2

Somit wäre jedes dieser beiden Bilder eine gültige Ausgabe für die Beispieleingabe.

So etwas wie dies wäre ungültig Ausgabe seit zwei gelben Regionen Nachbarn einander.

Ihre Ausgabebilder sollten diesen Richtlinien entsprechen:

  • Neben C1 und C2 kann eine dritte neutrale Farbe wie Schwarz oder Weiß für Kreisgrenzen verwendet werden, sofern sie nicht dicker als 5 Pixel sind. (Im obigen Beispiel sind schwarze, 1 Pixel dicke Grenzen vorhanden.)

  • Kreisgrenzen sind jedoch nicht erforderlich. Die Regionen können direkt benachbart sein:

    Beispiel 1 Ausgabe 3 Beispiel 1 Ausgabe 4

    Beides ist eine weitere gültige Ausgabe des obigen Beispiels.

  • Kreise sollten so genau wie möglich sein, wobei Kreiszeichnungsalgorithmen oder was auch immer Ihre Grafikbibliothek bereitstellt, verwendet werden.

  • Im Allgemeinen ist keine Pixel-Perfektion erforderlich, aber wenn die Eingabeparameter immer größer skaliert werden, sollte das resultierende Bild immer genauer werden.

  • Anti-Aliasing ist zulässig, aber nicht erforderlich.

  • Gitternetzlinien, Achsenbeschriftungen usw. im Hintergrund sind nicht zulässig.

Der kürzeste Code in Bytes gewinnt.

Mehr Beispiele

Alle verwenden diese Eingaben mit verschiedenen Kreisen:

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

In jedem Beispiel können die Farben getauscht werden und bleiben gültig.

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 ich J. ex J K. ex K L. ex L

Stellen Sie sicher, dass sich Ihre Ausgabe ähnlich wie in diesen Beispielen verhält.

Calvins Hobbys
quelle
Es sieht gut aus, können wir in ASCII ausgeben, zum Beispiel C1 ist 1 und C2 ist 0?
Matthew Roh
@MatthewRoh Nein. Ich weiß, das wäre praktisch, aber Bilder sind erforderlich.
Calvins Hobbys
1
Ok, dann kann ich wohl zählentikz
Wheat Wizard
1
@MatthewRoh, netpbm ist ein häufig verwendetes Bildformat auf dieser Site.
Peter Taylor
2
@ Luis Ok. Kleine Eingabevariationen wie diese oder mit der y-Achse nach oben sind in Ordnung.
Calvins Hobbys

Antworten:

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

Reine Funktion mit vier Argumenten: der Breite, der Höhe (beide Ganzzahlen), einem geordneten Zahlenpaar zwischen 0 und 1 (das die beiden RGB-Farben darstellt) und einer Liste von Elementen der Form {r, {x, y}}zur Aufzeichnung der Radien und Mitten von die Kreise. Beispielsweise würde das erste Beispiel im OP mit den Argumenten aufgerufen [300, 200, {{1, 0.784, 0}, {0.5, 0, 1}}, {{25, {50, 80}}, {40, {80, 120}}, {300, {-100, 6}}, {17, {253, 162}}}]. Die positive y-Achse zeigt in Mathematica nach oben.

Norm[{x,y}-#2]<#erkennt, ob sich ein Punkt innerhalb eines gegebenen Kreises befindet; Boole[...]Pikonvertiert das Trueoder Falsezu πoder 0. Nachdem Sie diese πs / 0s über alle Eingabekreise berechnet haben, addieren TrSie sie und Coskonvertieren Sie gerade Vielfache von π zu 1, ungerade Vielfache von π zu –1. ContourPlot[...,Contours->{0}]Färbt dann den entsprechenden Bereich der Ebene in zwei Farben, je nachdem, ob der Wert größer oder kleiner als ist 0. AspectRatio->Automaticlässt Kreise wie Kreise aussehen; PlotPoints->5!gibt eine anständige Genauigkeit (steigern Sie es auf, 9!wenn Sie wirklich ein erstaunliches Bild wollen, weit in der Zukunft!); Frame->Falsebeseitigt die Äxte; und ContourShading->RGBColor@@@#3verwendet die Eingabefarben für die Konturen.

Beispielausgabe mit dem ersten Farbpaar (da sie nett sind), aber der letzten Gruppe von Kreisen:

Beispielausgabe

Greg Martin
quelle
11

JavaScript / SVG / HTML5, 219 Byte

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
quelle
10

BBC Basic, 120 117 Bytes

Laden Sie den Interpreter unter http://www.bbcbasic.co.uk/bbcwin/bbcwin.html herunter

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 verfügt über eine Reihe von Farbmodi, mit denen Sie Rastergrafiken gemäß den grundlegenden Logikoperationen zeichnen können: ODER, UND, XOR usw.

Es unterstützt auch die Neuprogrammierung von Paletten, dh, hier können die Farben eines zweifarbigen Bildes auf eine von 4096 Farben neu programmiert werden. Die hier verwendete Implementierung weist einige (undokumentierte) Unterschiede zur ursprünglichen BBC-Implementierung auf, bei der die EOR-Operatoren nicht erforderlich wären.

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

Typischer Ausgabebildschirm

Beispielbild, um den Faktor 10 in Einheiten / Faktor 5 in Pixeln vergrößert (BBC basic verwendet 1 Pixel = 2 Einheiten.)

Bildbeschreibung hier eingeben

Level River St
quelle
10

MATL , 30 29 25 Bytes

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

Eingabeformat:

  • Colormap als Matrix von Werten zwischen 0 und 255, wobei jede Zeile eine Farbe definiert
  • W
  • H
  • Spaltenvektor von 1-basierten Mittelpunktskoordinaten als komplexe Werte ( x ist der Realteil, y ist der Imaginärteil)
  • Spaltenvektor der Radien.

Probieren Sie es bei MATL Online! Oder überprüfen Sie den letzten Testfall . (Der Interpreter ist noch experimentell. Möglicherweise müssen Sie die Seite aktualisieren und es erneut versuchen, wenn es nicht funktioniert.)

Erläuterung

Der Code verwendet komplexe Zahlen, um das Gitter von Punkten zu definieren und Entfernungen zu berechnen, und verwendet Array-Operationen beim Rundsenden in hohem Maße .

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
quelle
2
Ich sage Save Those Bytes! : D
Greg Martin
1
@ GregMartin Sie haben Recht. Wer kümmert sich um Eleganz, wenn 4 Bytes gespeichert werden können! :-) Fertig
Luis Mendo
1
@ LuisMendo Je kürzer desto besser mit Codegolf, egal wie hässlich es wird. ;)
Kevin Cruijssen
6

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

Anwendungsbeispiel:

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

Danke an xnor für das Speichern von 2 Bytes.

Alex Hall
quelle
Willkommen beim Code Golf! Denn in einem Kreis , wenn ein Punkt liegt Überprüfung, ist ein Trick komplexe Norm zu verwenden: abs(x-X+1j*(y-Y))<r.
xnor
3

Mathe (nicht wettbewerbsfähig)

(idk wie man LaTeX in PPCG macht, also habe ich ein LaTeX to png Tool benutzt)

Erläuterung

Das Produkt mehrerer Kreisgleichungen ( (x-a)^2+(y-b)^2-r^2)> = 0 ergibt ein Diagramm, das diese Frage benötigt. In der Gleichung nist die Größe des Arrays und (x, y or r)_kist das kth- (x, y, or r)Element.

Beispiel

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

(Danke WolframAlpha)

(Ungleichungsplot von WolframAlpha)

Gleichung für WolframAlpha abrufen / ausführen

Skript abrufen: Fertig

Laufendes Skript: Noch nicht fertig

Lass es jetzt mit Mathematica funktionieren ...

Matthew Roh
quelle
Ich frage mich, ob das gültig ist?
Matthew Roh
Sie müssen einen bestimmten bereits vorhandenen Interpreter auflisten, der die Ausgabe in der gewünschten Form darstellt, wenn Sie diese Eingabe vornehmen. Das würde es möglich machen, die Bytes darin zu zählen. Gegenwärtig ist das Problem, dass es nicht an ein bestimmtes Format für die Darstellung der Gleichung gebunden ist, da es nicht an einen Interpreter gebunden ist. Daher ist die Notation informell und objektiv nicht zu zählen. Es gibt viele Programme zum Zeichnen von Gleichungsgraphen. Es lohnt sich also möglicherweise, eines mit einem knappen Eingabeformat zu finden.
@ ais523 Ohh. Ich werde versuchen, es mit WolframAlpha zum Laufen zu bringen.
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)]))

Die Funktion erzeugt eine PPM-Datei auf der Standardausgabe.

Beispiel:

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)

Beispiel

Dieter
quelle
1

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

Dies ist einer der umfangreichsten Codes, die ich jemals in CL geschrieben habe. Wenn ich keinen Code-Golf gespielt hätte, hätte ich dies umstrukturiert, um das Lesen zu vereinfachen ...

Vorspiel (20 Zeichen)

(ql:quickload 'zpng)

Golf (260 Zeichen)

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

(Verwendet Defun, um Tests und längere Variablennamen für die Lesbarkeit zu ermöglichen.)

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

Beispiel Verwendung:

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

Erklärung

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

Gibt true zurück, wenn der Punkt (i, j) innerhalb des angegebenen Kreises circ liegt. Der euklidische Abstand wird berechnet, indem der Absolutwert der komplexen Zahl, die den Vektor von (i, j) zum Mittelpunkt des Kreises darstellt, genommen wird.

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

Ordnen Sie diese Funktion in der Kreisliste zu und prüfen Sie, ob der angegebene Punkt (i, j) in eine gerade Anzahl von Kreisen fällt.

(if ____
     color1 color2)

Wählen Sie die Farbe basierend auf diesem Test.

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

Sammeln Sie eine flache Liste aller RGB-Bytes, indem Sie alle (i, j) im Bild durchlaufen und die resultierenden Listen zusammenfügen.

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

Konvertieren Sie diese Liste von Bytes in ein geeignetes Array von Bytes, damit zpng sie richtig aufnehmen kann.

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

Erstellen Sie das PNG-Objekt.

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

Erstellen Sie die Funktion, um die Breite, Höhe, zwei Farben und die Liste der Kreise zu übernehmen und das erstellte PNG-Objekt zurückzugeben.

djeis
quelle
0

JavaScript (ES6), 224 Byte

Ich habe die JS + SVG-Lösung gesehen, musste aber nur eine Canvas-basierte Lösung erstellen ;-) Dies ist eine Funktion, die ein Canvas-Element zurückgibt. Wenn ein vorhandenes Zeichenflächenelement bereitgestellt werden kann, entfernen Sie 40 Byte.

Rufen Sie gerne an 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>

Beispielausgabe:

zweifarbige Kreise

ETHproductions
quelle
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")
Ein Taco
quelle