Fliesen Sie das Flugzeug mit diesem modifizierten Kreis


22

Nehmen Sie einen Einheitskreis, der auf dem Ursprung zentriert ist. Spiegeln Sie in zwei benachbarten Quadranten die Kurve des Kreises über die Linien, die die x- und y-Achsen des Kreises verbinden.

Mit der resultierenden Form können Sie die Ebene kacheln:

Kreistessellation

Ich habe dieses Bild mit der fantastischen 2D-Physik-Sandbox Algodoo gemacht !

Schreiben Sie ein Programm, das ein ähnliches Bild in einem gängigen verlustfreien Bilddateiformat ausgibt. Sie können das Bild als Datei mit dem Namen Ihrer Wahl speichern oder es einfach anzeigen. Es sollten keine Eingaben gemacht werden.

Regeln:

  • Das gesamte Bild muss mit den Kacheln mit modifizierten Kreisen unter Verwendung von zwei visuell unterschiedlichen RGB-Farben tesselliert werden: eine für die vertikal zeigenden Kacheln, eine für die horizontal zeigenden Kacheln.

  • Der Radius der Kreiskacheln sollte mindestens 32 Pixel betragen. (Der Radius im obigen Bild beträgt ca. 110 Pixel.)

  • Das Bild sollte mindestens 4 Kacheln breit und 4 Kacheln hoch sein. In Kombination mit der obigen Regel bedeutet dies, dass Bilder eine Mindestgröße von 256 × 256 Pixel haben können. (Das Bild oben zeigt 4 x 4 Kacheln.)

  • Die Tessellation kann beliebig umgerechnet werden. Beispielsweise muss die linke obere Ecke des Bildes nicht der Scheitelpunkt sein, an dem sich Kacheln treffen. (Die Tessellation sollte jedoch nicht gedreht werden.)

  • Sie können externe Grafikbibliotheken verwenden, die Befehle zum Zeichnen von Kreisen und zum Ausgeben von Bildern und dergleichen enthalten.

  • Die Kurven sollten sich wirklich Kreisen annähern, wie dies mit dem Mittelpunktkreis-Algorithmus möglich ist , den die meisten Grafikbibliotheken für Sie tun werden.

  • Anti-Aliasing an den Kanten der Kacheln ist zulässig, aber nicht erforderlich.

Die kürzeste Übermittlung in Bytes gewinnt.

Antworten:


4

gs2, 49 bytes

50 31 05 0d 1f 2a 48 0a 1e 2e 40 83 2c e8 64 2d
1e 73 ed 1e 33 40 20 30 9a a2 22 e8 e9 40 20 30
9a 30 40 20 30 ee 40 20 30 12 32 e9 12 32 55 e8
2b

Erzeugt ein PBM-Image:

Ausgabe

Mnemonik:

# Print header
"P1" space 256 double
2dup new-line

# Make 1/4 circle
64 range dup cartesian-product
square m1 sum sqrt 64 >= m6
64 /

# Make tile
dup reverse + transpose
@2 not m1 m2
dup reverse + transpose
+

# Make quarter of image
dup reverse + z1
dup reverse +

# Loop
2 * m2
2 *

# Format
show-words m1
unlines

36

POV-Ray, 199 163

Old version
camera{location -9*z}light_source{-9*z}#declare L=union{#for(X,-9,9,2)#for(Y,-9,9,2)cylinder{X*x+x+Y*y,<.001*pow(-1,(X+Y)/2),0,.1>+X*x+x+Y*y,1}#end#end}object{L pigment{color x}}object{L rotate z*90}

Same output, but golfed down further by using default light/camera, so I dont even need to specify them
#declare L=union{#for(X,-9,9,2)#for(Y,-9,9,2)cylinder{<X+1,Y,9>,<.001*pow(-1,(X+Y)/2),0,.1>+<X+1,Y,9>,1}#end#end}object{L pigment{color rgb x}rotate z*90}object{L}

Bildbeschreibung hier eingeben
Ich verwende so viele Standardparameter für Kamera und Lichtquelle wie möglich, deshalb ist es ein wenig dunkel. Lässt es zuerst ungolf

camera{location 9*z look_at 0}
light_source{9*z color 1} 
#declare L=union{
    #for(X,-9,9,2)
        #for(Y,-9,9,2)
            cylinder{<1+X,Y,0>,                                 //central axis, start
                     <1+X,Y,0> + <.001*pow(-1,(X+Y)/2), 0, .1>, //central axis, end
                      1}                                        //radius
        #end         
    #end
}                         
object{L pigment{color x}} // x is the <1,0,0> vector, here interpreted as RGB
object{L rotate<0,0,90>}

Es ist offensichtlich, was passiert, wenn wir den Versatz der Zylinderachse erhöhen und die Perspektive ändern

Bildbeschreibung hier eingeben


1
Werden die Kanten dank 3D-Perspektive nicht leicht verzerrt?
Orlp

6
Bei einer Höhe von 0.1und einem Versatz 0.001der Scheibe ist diese um $ \ phi = \ arctan (0.01) = 0.57 ° $ geneigt, wobei die Scheiben von oben mit einem Faktor von $ \ cos (\ phi) = 0.99995 $ zusammengedrückt erscheinen. das ist weit weniger als ein Pixel.
DenDenDo

@DenDenDo Kann pov-ray eine Kamera nicht auf unendlich stellen?
Random832

@ Random832 kann es, mit camera{orthographic location -9z}. Da die Szene im Grunde genommen 2D ist, macht es keinen Unterschied, dass Sie sie sogar mit einer Anzeige rendern können, angle 170ohne dass das Ergebnis durch Fischaugen verzerrt wird.
DenDenDo

11

Gnuplot, 182

Mir ist aufgefallen, dass die Grenzen zwischen den Zellen sehr sinusförmig sind, und so habe ich mich für eine analytische Lösung mit einer sehr einfachen Kerngleichung entschieden
Bildbeschreibung hier eingeben

set view map
set isosamples 900
f(x,y)=.3*sin(x*3.14)+y
splot(ceil(f(x,y))+ceil(f(y,x)))%2?1:NaN   #can only modulo integers

Bildbeschreibung hier eingeben
Während es ähnlich aussieht, sind die Kreise viel zu quadratisch. Mit der gleichen Idee ersetze ich sindurch eine Kurve aus verketteten Viertelkreisbögen und drehe sie durch Ersetzen von xund ydurch x+yund um 45 °x-y

set view map
set samples 800
set isosamples 800
d=.5**.5
c(x,k)=(-1)**k*sqrt(1-(x-d*(1+2*k))**2)-(-1)**k*d  # k-th circle arc
# s(x)=c(x,floor(x/d/2))                           # circlified sinus
# f(x,y)=d*s(x/d)+y
f(x,y)=d*c(x/d,floor(x))+y                         # combined commented functions
splot(ceil(f(x+y,x-y))+ceil(f(x-y,x+y)))%2?1:NaN

Bildbeschreibung hier eingeben



7

HTML + JavaScript, 277

<canvas id=C></canvas><script>r=50,C.width=C.height=9*r,T=C.getContext('2d');
for(f=1,P=Math.PI,i=0;i<45;f=-f,i+=i&7?1:2)x=2*r*(i%8-2),y=2*r*(i>>3),T.moveTo(x,y+f*r),
T.arc(x+r,y+f*r,r,P,-f*P/2,f<0),T.arc(x,y,r,0,P,f>0),T.arc(x-r,y+f*r,r,-f*P/2,0,f<0);
T.fill()</script>

Zum Testen als HTML-Datei speichern und mit einem Browser öffnen. Oder führen Sie das Snippet aus

r=50,C.width=C.height=9*r,T=C.getContext('2d')
for(f=1,P=Math.PI,i=0;i<45;f=-f,i+=i&7?1:2)
  x=2*r*(i%8-2),y=2*r*(i>>3),
  T.moveTo(x,y+f*r),
  T.arc(x+r,y+f*r,r,P,-f*P/2,f<0),
  T.arc(x,y,r,0,P,f>0),
  T.arc(x-r,y+f*r,r,-f*P/2,0,f<0)
T.fill()
<canvas id=C></canvas>

Aufgrund der großen Nachfrage sehen Sie hier das Ausgabebild. Immerhin nicht so aufregend ...

Fliesen


1
Möglicherweise möchten Sie ein Bild veröffentlichen, damit der Code nicht jedes Mal ausgeführt werden muss, wenn jemand die Ausgabe sehen möchte.
Calvins Hobbys

@ Calvin'sHobbies na ja, es ist schnell genug und läuft in jedem modernen Browser. Ich werde das Bild stattdessen größer machen
edc65

Das ist richtig. Ich dachte, dass es =>wie viele Ihrer Beiträge verwendet und nur in Firefox funktionieren würde. Aber keine Sorge.
Calvins Hobbys

1
Besserer Grund für das Posten eines Bildes: Diese Snippets funktionieren auf Mobilgeräten nicht sehr gut :(
Sp3000

6

IDL 8.3, 201 193 183 Bytes

Das Bild wird in ein IDL-Grafikfenster ausgegeben. Ich habe unten einen Screenshot gemacht.

EDIT: danke an @AlexA. und @ Sp3000 für die Hilfe beim Rasieren einiger Bytes

p=!pi/99*[0:99]
q=p[49:0:-1]
o=p[99:50:-1]
window,xs=(ys=400)
for i=0,24 do cgpolygon,i mod 5*100+50*[cos(p),cos(q)-1,cos(o)+1],i/5*100+(-1)^i*50*[sin(p),sin(q)-1,sin(o)-1],/d,/fi
end

Bildbeschreibung hier eingeben


6

Mathematica: 86 Bytes (oder 82 Bytes)

Vielen Dank an @alephalpha für eine clevere Array-basierte Methode:

Image@ArrayFlatten@Array[DiskMatrix@32~RotateLeft~32/.a_/;OddQ@+##:>1-Thread@a&,{5,5}]

In dem Array befindet sich eine anonyme Funktion, die mit einem cleveren Trick die Argumente ( +##) hinzufügt und feststellt, ob die Summe ungerade ist. Dieser Boolesche Wert wird als Bedingung für ein Muster verwendet, das die gesamte "weiße" Kachel durch die transformierte "schwarze" Kachel ersetzt. Von dort aus werden ArrayFlattendie Kacheln zusammengefügt und Imageangezeigt.

Beachten Sie die Verwendung der kürzeren Threadzu ersetzen Transpose. Wir können weiterhin 4 Bytes sparen, indem wir stattdessen das Transponierungssymbol verwenden.

Zurück: 97 Bytes (oder 90 Bytes)

Image@ArrayFlatten@Partition[
 Join@@Table[{#,1-Transpose@#}&@RotateLeft[DiskMatrix@32,32],{13}],5]

Sie können die Anzahl der Bytes verringern, indem Sie sie Transpose@#durch das hochgestellte t-Symbol ersetzen (Codepunkt U + F3C7, Tastenkürzel ESCtrESC). In UTF-8 ergibt das 90 Bytes in 88 Zeichen .

Bildbeschreibung hier eingeben

Wir beginnen mit DiskMatrix, die eine binäre Matrix erzeugt:

DiskMatrix@32 // Image

Bildbeschreibung hier eingeben

Wir verschieben dann die Zeilen der Matrix kreisförmig, um die Einheitszelle für die Kachelung zu erzeugen:

RotateLeft[DiskMatrix@32, 32] // Image

Bildbeschreibung hier eingeben

Wenn das Flugzeug ein Schachbrett ist, sind dies die "weißen" Quadrate. Für die "schwarzen" Quadrate müssen wir die Farben umkehren und um 90 Grad drehen. Wir können invertieren, indem wir von 1 ( 1 - 1 -> 0und 1 - 0 -> 1) subtrahieren , und rotieren, indem wir die Transponierte nehmen:

Image /@ {#, 1 - Transpose@#} &@RotateLeft[DiskMatrix@32, 32]

Bildbeschreibung hier eingeben

Wenn die Abmessungen des Bildes gerade sind (wie die Mindestgröße 4), entspricht eine Kachel am rechten Rand der nächsten am linken Rand. Wenn Sie jedoch eine Kachel hinzufügen, um eine ungerade Größe (5) zu erhalten, und dann die Zeilen verketten, wird ein regelmäßiges Wechselmuster erzeugt.

Dies legt nahe, dass wir das vollständige Bild erhalten können, indem wir eine einzelne Reihe abwechselnder Kacheln mit umwickeln Partition. Wir verwenden Table, um eine Liste von 13Schwarz / Weiß-Kachelpaaren Joinzu erstellen und die Liste der Paare auf eine Liste von 26 Kacheln zu reduzieren. Dann haben wir Partitiondie Liste in eine 5von 5Matrix von Kacheln ( Partitionverwirft die 26 Hinter th Kachel):

Map[Image] /@ 
  Partition[
   Join @@ Table[{#, 1 - #\[Transpose]} &@
      RotateLeft[DiskMatrix@32, 32], {13}], 5] // MatrixForm

Bildbeschreibung hier eingeben

Schließlich ArrayFlattenstellt sich die Matrix der Fliese Matrizen in eine flache Matrix und Imagezeigt das Ergebnis an .

Zurück: 111 Bytes

Image[ArrayFlatten[{{#, #}, {#, #}}] &[
  Join[#, Reverse@#, 2] &[
   Join[1 - Transpose@#, #] &@RotateLeft[DiskMatrix[32], 32]]]]

Bildbeschreibung hier eingeben


Image@ArrayFlatten@Array[RotateLeft[DiskMatrix@32,32]/.a_/;OddQ[+##]:>1-Thread@a&,{5,5}]
Alephalpha

4

Java, 550 540 508 504 Bytes

Dies ist ein Java-Applet.

import java.awt.*;public class T extends java.applet.Applet{int a=98,b=49,x,y;public void paint(Graphics g){for(x=0;x<5;x++)for(y=0;y<5;y++)a(g.create(x*a,y*a,a,a),x%2^y%2);}void a(Graphics g,int c){if(c>0){g.translate(a,0);((Graphics2D)g).scale(-1,1);}g.setColor(Color.red);g.fillRect(0,0,b,b);g.fillRect(b,b,b,b);g.setColor(Color.blue);g.fillRect(b,0,b,b);g.fillRect(0,b,b,b);g.fillArc(0,-b,a,a,180,90);g.fillArc(0,b,a,a,0,90);g.setColor(Color.red);g.fillArc(-b,0,a,a,0,-90);g.fillArc(b,0,a,a,90,90);}}

Erweitert mit Boilerplate:

import java.awt.*;
public class T extends java.applet.Applet{
    int a = 98, b = 49, x, y; //Make these larger for better quality pictures. a = b * 2
    public void paint(Graphics g) {
        for (x=0; x < 5; x++)      //Make these larger for more tiles.
            for (y=0; y < 5; y++)  //
                a(g.create(x * a, y * a, a, a), x % 2 ^ y % 2);
    }

    void a(Graphics g, int c) {
        if (c > 0) {
            g.translate(a, 0);
            ((Graphics2D) g).scale(-1, 1);
        }
        g.setColor(Color.red);            //Change colors for nicer looking colors.
        g.fillRect(0, 0, b, b);
        g.fillRect(b, b, b, b);
        g.setColor(Color.blue);
        g.fillRect(b, 0, b, b);
        g.fillRect(0, b, b, b);
        g.fillArc(0, -b, a, a, 180, 90);
        g.fillArc(0, b, a, a, 0, 90);
        g.setColor(Color.red);
        g.fillArc(-b, 0, a, a, 0, -90);
        g.fillArc(b, 0, a, a, 90, 90);
    }
}

Applet: Ein kleines Anwendungsprogramm, das für die Arbeit in einer anderen Anwendung aufgerufen werden kann.

Beispielbild:

Bildbeschreibung hier eingeben

Erläuterung:

Dies funktioniert mithilfe einer Methode zum Drucken der einzelnen Kacheln. Bevor die Methode erstellt wird, erhält sie ein Grafikobjekt, das ein Koordinatensystem verwendet, das in der oberen linken Ecke jeder Kachel zentriert ist:

Um eine Kachel zu erstellen, verwenden wir die folgende Methode:

void a(Graphics g, int c) {
    g.setColor(Color.red);
    g.fillRect(0, 0, b, b);
    g.fillRect(b, b, b, b);
    g.setColor(Color.blue);
    g.fillRect(b, 0, b, b);
    g.fillRect(0, b, b, b);
    g.fillArc(0, -b, a, a, 180, 90);
    g.fillArc(0, b, a, a, 0, 90);
    g.setColor(Color.red);
    g.fillArc(-b, 0, a, a, 270, 90);
    g.fillArc(b, 0, a, a, 90, 90);
}

Jede andere Kachel muss jedoch horizontal reflektiert werden, um das richtige Bild zu erhalten.

Um eine Kachel wiederzugeben, ändern wir einfach das bereitgestellte graphicsObjekt mit dem folgenden Code:

g.translate(a, 0);
((Graphics2D) g).scale(-1, 1);

Danke @CoolGuy für 4 Bytes.


1
Sie können es mehr Golf, indem Sie xund yals Felder der Klasse:int a = 98, b = 49,x,y;
Spikatrix

4

Mathematica 299 256

Wordy, aber es war schön herauszufinden.

Die Grundkachel ist r (siehe unten), eine Region, die von RegionPlot angezeigt wird. Ein Links-Rechts-Spiegelbild der Kachel wird erstellt und mit r verbunden. Die zusammengesetzte Figur aus zwei Kacheln wird dann wiederholt, um den Raum zu kacheln.

r

a_~f~b_ := (x + a)^2 + (y + b)^2 <= 1;
a = ImageAssemble;
r = RegionPlot[(0~f~0 && y <= 0 && ! f[-1, 1]) \[Or] (0~f~2 && 
      y >= -2 && ! f[1, 1]), {x, -1, 1}, {y, -2, 0}, Frame -> False,
    BoundaryStyle -> None];
s = ImageCrop@Rasterize@r;
t = s~ImageReflect~Right;
i = a@{s, t};
j = a@{t, s};
a@{k = {i, i, i, i}, m = {j, j, j, j}, k, m, k, m}

Fliese


1

C 237 209 180 Bytes

180 Bytes. Diese Version enthält Änderungen, die von edc65 in einem Kommentar vorgeschlagen wurden. Es gibt 9 Compiler-Warnungen, wenn auf einem Mac mit Klirr- und Standardoptionen gebaut wird:

a,b,c,d,x,y;main(){for(puts("P1 256 256");b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c++<256;)putchar(48+(x*x+y*y<962^b==d));puts("");}}

209 Bytes, unter Verwendung einiger Vorschläge aus Kommentaren von Martin. Kompiliert ohne Warnung mit clang:

#include <stdio.h>
int a,b,c,d,x,y;int main(){puts("P1 256 256");for(;b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c<256;++c)putchar(48+(x*x+y*y<962^b==d));puts("");}}

Originalversion, 237 Bytes:

#include <stdio.h>
int main(){puts("P1 256 256");for(int a=0;a<256;++a){int b=a+32&64;for(int c=0;c<256;++c){int d=c+32&64;int x=(a&64)-d?31-a&31:a&31;int y=(c&64)-b?c&31:31-c&31;putchar(48+(x*x+y*y<962^b==d));}puts("");}}

Ergebnis (256 x 256):

Bildbeschreibung hier eingeben

Originalcode mit Leerzeichen zur besseren Lesbarkeit:

#include <stdio.h>
int main()
{
    puts("P1 256 256");
    for (int a = 0; a < 256; ++a)
    {
        int b = a + 32 & 64;
        for (int c = 0; c < 256; ++c)
        {
            int d = c + 32 & 64;
            int x = (a & 64) - d ? 31 - a & 31 : a & 31;
            int y = (c & 64) - b ? c & 31 : 31 - c & 31;
            putchar(48 + (x * x + y * y < 962 ^ b == d));
        }
        puts("");
    }
}

Hierbei wird keine Grafikbibliothek verwendet, das Rendering ist vollständig im Code enthalten.

Die Grundidee besteht darin, einfach alle 256 x 256 Pixel zu durchlaufen und zu prüfen, ob sie sich innerhalb / außerhalb des Kreisbogens des 32 x 32-Teilquadrats befinden, in dem sie sich befinden. Die unteren 5 Bits der gesamten Pixelkoordinaten definieren die relativen Koordinaten des Pixels innerhalb das Unterquadrat. Der Innen- / Außentest (x, y), innerhalb des Bogens mit Radius zu sein, rist dann der Standard:

x * x + y * y < r * r

Die meiste Logik besteht darin, den Mittelpunkt des Bogens in der richtigen Ecke des Unterquadrats zu platzieren und zu bestimmen, welche Farbe innen / außen ist.

Einige Kommentare zur Lösung:

  • Der Code generiert das Bild im PBM-ASCII-Format. Ich habe das Ergebnis in GIMP geladen und in Paint kopiert und eingefügt, um die tatsächliche Datei zu generieren, die ich hier gepostet habe. Das Format wurde also konvertiert, aber der Inhalt entspricht genau der ursprünglichen Ausgabe.
  • Wenn Sie genau hinschauen, werden Sie feststellen, dass die Qualität nicht besonders gut ist. Dies liegt daran, dass die Innen- / Außenberechnung für die Ecke des Pixels und nicht für die Pixelmitte durchgeführt wird, wodurch das Ganze um 1/2 Pixel versetzt wird. Ich denke nicht, dass es sehr schwierig wäre, es besser zu machen, aber es würde den Code etwas länger machen. Und da es keine spezifischen Qualitätsanforderungen gab, halte ich dies für ausreichend.
  • Code wurde mit clang auf einem Mac kompiliert. Neueste Version gibt Warnungen, erste Version nicht.
  • Dies ist das erste Mal, dass ich einen dieser Versuche unternommen habe. Vermutlich habe ich ein paar Tricks verpasst, um das letzte mögliche Byte zu speichern.

3
Willkommen bei PPCG! Ich bin kein großer C-Golfer, aber ich glaube, ich kann ein paar Verbesserungen feststellen: Gruppieren Sie Ihre Erklärungen wie int a,b,c,d,x,y;... Ich glaube, Sie können sogar einfach tun, main(a,b,c,d,x,y)ich erinnere mich an etwas, das der Standardtyp int ist. Sobald Sie das los sind, können Sie die Zuweisungen zu d, x und y in die forInkrement-Anweisung des Inneren verschieben d=c+32&64,...,++c(wahrscheinlich sogar an ++eine andere Stelle, an der Sie csowieso erwähnen ), und dann können Sie die geschweiften Klammern von weglassen das Innere for. Gute Arbeit, übrigens! :)
Martin Ender

Vielen Dank! Ich sah den Trick darin, Argumente ohne Typ in einer Liste von Tipps zu deklarieren, aber es schien so dreckig, dass ich mich nicht dazu bringen konnte, dorthin zu gehen. ;) Ich halte es nicht für main()standardkonform , nicht standardkonforme Argumente zu haben . Ich sollte die Erklärungen auf jeden Fall zusammenfassen. Durch das Verschieben der Inkremente werden auch einige Bytes gespart. Die puts()für die Newline befindet sich in der äußeren Schleife, daher bin ich mir nicht sicher, ob ich die Klammern loswerden kann.
Reto Koradi

Wir sind normalerweise damit einverstanden, solange es in einem gängigen Compiler kompiliert wird (es muss also nicht unbedingt Standard-C sein). Auch ja, ich glaube nicht, dass Sie die äußeren Zahnspangen loswerden können, aber Sie sollten in der Lage sein, die inneren zu entfernen.
Martin Ender

Ich habe es auf 210 Bytes reduziert. Danke für die Ideen.
Reto Koradi

1
Hinweise: stdionicht erforderlich, Standardfunktionserklärung verwenden. intist die Standardeinstellung für globale Variablen und kann weggelassen werden (Variablen und main). Zuerst putskann man in die für gehen. c var wird in der inneren Schleife nicht verwendet, erhöhen Sie also die Bedingung. 180: a,b,c,d,x,y;main(){for(puts("P1 256 256");b=a+32&64,a<256;++a){for(c=0;d=c+32&64,x=(a&64)-d?31-a&31:a&31,y=(c&64)-b?c&31:31-c&31,c++<256;)putchar(48+(x*x+y*y<962^b==d));puts("");}}(kompiliert mit vielen Warnungen, wird aber ausgeführt)
edc65
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.