Mosaïque l'avion avec ce cercle modifié

22

Prenez un cercle d'unité centré sur l'origine. Dans deux quadrants voisins , inversez la courbe du cercle à travers les lignes reliant les intersections x et y du cercle.

Avec la forme résultante, vous pouvez carreler l'avion:

pavage de cercle

J'ai fait cette image avec le superbe bac à sable de physique 2D Algodoo !

Écrivez un programme qui produit une image similaire à celle-ci dans un format de fichier d'image sans perte commun. Vous pouvez enregistrer l'image sous forme de fichier avec le nom de votre choix ou simplement l'afficher. Aucune entrée ne doit être prise.

Règles:

  • L' image entière doit être pavée avec les carreaux à cercle modifié en utilisant deux couleurs RVB visuellement distinctes: une pour les carreaux pointant verticalement, une pour les carreaux pointant horizontalement.

  • Le rayon des carreaux de cercle doit être d'au moins 32 pixels. (Le rayon dans l'image ci-dessus est d'environ 110 pixels.)

  • L'image doit avoir au moins 4 carreaux de large et 4 carreaux de haut. Ceci, combiné avec la règle ci-dessus, signifie que les images peuvent avoir une taille minimale de 256 × 256 pixels. (L'image ci-dessus est 4 tuiles par 4 tuiles.)

  • La tessellation peut être traduite de n'importe quel montant. Par exemple, le coin supérieur gauche de l'image n'a pas besoin d'être le sommet où les tuiles se rencontrent. (Cependant, la tessellation ne doit pas être tournée.)

  • Vous pouvez utiliser des bibliothèques graphiques externes qui ont des commandes pour dessiner des cercles et produire des images et similaires.

  • Les courbes devraient vraiment se rapprocher des cercles, comme cela peut être fait avec l' algorithme du cercle médian , que la plupart des bibliothèques graphiques feront pour vous.

  • L'anticrénelage autour des bords des carreaux est autorisé mais pas obligatoire.

La soumission la plus courte en octets l'emporte.

Loisirs de Calvin
la source

Réponses:

4

gs2, 49 octets

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

Génère une image PBM:

sortie

Mnémotechnique:

# 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
Lynn
la source
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}

entrez la description de l'image ici
J'utilise autant de paramètres par défaut pour la caméra et la source lumineuse que possible, c'est pourquoi il fait un peu sombre. Permet de le dé-golfer en premier

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

Il est évident ce qui se passe une fois que nous augmentons le décalage de l'axe du cylindre et changeons la perspective

entrez la description de l'image ici

DenDenDo
la source
1
Les bords ne seront-ils pas légèrement déformés grâce à la perspective 3D?
orlp
6
Avec une hauteur de 0.1et un décalage du 0.001disque est incliné de $ \ phi = \ arctan (0,01) = 0,57 ° $, en regardant du haut les disques apparaissent serrés d'un facteur $ \ cos (\ phi) = 0,99995 $, c'est bien moins qu'un pixel.
DenDenDo
@DenDenDo le pov-ray n'est-il pas capable de mettre une caméra à l'infini?
Random832
@ Random832 il peut, avec camera{orthographic location -9z}. Mais comme la scène est essentiellement 2D, cela ne fait aucune différence, vous pouvez même la rendre avec une visualisation angle 170sans aucune distorsion fisheye dans le résultat.
DenDenDo
11

Gnuplot, 182

J'ai remarqué que les frontières entre les cellules sont très sinusoïdales, alors j'ai opté pour une solution analytique avec une équation de base très simple
entrez la description de l'image ici

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

entrez la description de l'image ici
Bien que cela semble similaire, les cercles sont beaucoup trop carrés. Avec la même idée, je remplace sinpar une courbe faite d'arcs de quart de cercle concaténés et je la fais pivoter de 45 ° en remplaçant xet yavec x+yetx-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

entrez la description de l'image ici

DenDenDo
la source
9

Sans contexte, 99 octets

startshape d CF::Tile=[s 4]CF::Symmetry=CF::pmg,0,1,0path d{ARCTO(-1,1,1)ARCTO(1,1,-1)ARCTO(0,0,1)}

Vous pouvez voir le résultat dans la galerie Context Free .

MtnViewJohn
la source
Bien, c'est une utilisation incroyable de Context Free. :)
Martin Ender
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>

Pour tester, enregistrez en tant que fichier html et ouvrez avec un navigateur. Ou bien, exécutez l'extrait

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>

En raison de la demande populaire, voici l'image de sortie. Pas si excitant après tout ...

Carrelage

edc65
la source
1
Vous voudrez peut-être publier une image afin que le code ne doive pas être exécuté chaque fois que quelqu'un veut voir la sortie.
Calvin's Hobbies
@ Calvin'sHobbies eh bien, il est assez rapide et fonctionne dans tous les navigateurs modernes. Je vais agrandir l'image à la place
edc65
C'est vrai. Je pensais que cela utilisait =>beaucoup de vos messages et ne fonctionnerait que dans Firefox. Mais pas de soucis.
Calvin's Hobbies
1
Meilleure raison pour publier une image: ces extraits ne fonctionnent pas très bien sur mobile :(
Sp3000
6

IDL 8.3, 201 193 183 octets

L'image est sortie dans une fenêtre graphique IDL; J'ai pris une capture d'écran ci-dessous.

EDIT: merci à @AlexA. et @ Sp3000 pour m'avoir aidé à raser quelques octets

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

entrez la description de l'image ici

sirpercival
la source
6

Mathematica: 86 octets (ou 82 octets)

Merci à l'infini @alephalpha pour une méthode intelligente basée sur un tableau:

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

À l'intérieur du tableau se trouve une fonction anonyme, qui utilise une astuce pour ajouter ses arguments ( +##) et déterminer si la somme est impaire. Ce booléen est utilisé comme conditionnel à un motif qui remplace la tuile «blanche» entière par la tuile «noire» transformée. De là, ArrayFlattenrassemble les tuiles et les Imageaffiche.

Notez l'utilisation du plus court Threadà remplacer Transpose. Nous pouvons toujours enregistrer 4 octets en utilisant le symbole de transposition à la place.

Précédent: 97 octets (ou 90 octets)

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

Vous pouvez réduire le nombre d'octets en le remplaçant Transpose@#par le symbole en exposant-t (point de code U + F3C7, raccourci ESCtrESC). En UTF-8, cela porte le total à 90 octets en 88 caractères .

entrez la description de l'image ici

Nous commençons par DiskMatrix, qui génère une matrice binaire:

DiskMatrix@32 // Image

entrez la description de l'image ici

Nous déplaçons ensuite de façon circulaire les lignes de la matrice pour produire la cellule unitaire du pavage:

RotateLeft[DiskMatrix@32, 32] // Image

entrez la description de l'image ici

Si l'avion est un échiquier, ce sont les carrés «blancs». Pour les carrés «noirs», nous devons inverser les couleurs et faire une rotation de 90 degrés. On peut inverser en soustrayant de 1 ( 1 - 1 -> 0et 1 - 0 -> 1), et tourner en prenant la transposition:

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

entrez la description de l'image ici

Si les dimensions de l'image sont égales (comme la taille minimale, 4), alors une tuile sur le bord droit sera la même que la suivante sur le bord gauche. Cependant, ajouter une tuile pour obtenir une taille impaire (5) puis concaténer les rangées produit un motif alterné régulier.

Cela suggère que nous pouvons obtenir l'image complète en enveloppant une seule rangée de tuiles alternées avec Partition. Nous utilisons Tablepour faire une liste de 13paires de tuiles noir / blanc, et Joinpour aplatir la liste de paires en une liste de 26 tuiles. Ensuite , nous avons Partitionla liste en une 5par 5matrice de tuiles ( Partitionrejets de la queue 26 e tuile):

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

entrez la description de l'image ici

Enfin, ArrayFlattentransforme la matrice des matrices de tuiles en une matrice plate et Imageaffiche le résultat.

Précédent: 111 octets

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

entrez la description de l'image ici

2012rcampion
la source
Image@ArrayFlatten@Array[RotateLeft[DiskMatrix@32,32]/.a_/;OddQ[+##]:>1-Thread@a&,{5,5}]
alephalpha
4

Java, 550 540 508 504 octets

Ceci est une applet java.

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);}}

Développé avec passe-partout:

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: Un petit programme d'application qui peut être appelé pour une utilisation tout en travaillant dans une autre application.

Exemple d'image:

entrez la description de l'image ici

Explication:

Cela fonctionne en utilisant une méthode pour imprimer chaque tuile. Avant la création de la méthode, un objet graphique lui est attribué qui utilise un système de coordonnées centré sur le coin supérieur gauche de chaque mosaïque:

Pour créer une tuile, nous utilisons la méthode suivante:

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);
}

Cependant, toutes les autres tuiles doivent être réfléchies horizontalement afin de produire l'image correcte.

Pour refléter une tuile, nous modifions simplement l' graphicsobjet fourni avec ce code:

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

Merci @CoolGuy pour 4 octets.

Le numéro un
la source
1
Vous pouvez le xyint a = 98, b = 49,x,y;
jouer
4

Mathematica 299 256

Wordy mais c'était agréable à comprendre.

La vignette de base est r (illustrée ci-dessous), qui est une région affichée par RegionPlot. Une réflexion gauche-droite de la tuile est faite et jointe à r. La figure assemblée de deux tuiles est alors répétée pour carreler l'espace.

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}

tuile

DavidC
la source
1

C, 237 209 180 octets

180 octets. Cette version inclut les modifications suggérées par edc65 dans un commentaire. Il donne 9 avertissements du compilateur lors de la construction sur un Mac avec des options clang et par défaut:

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 octets, en utilisant quelques suggestions de commentaires de Martin. Compile sans avertissements avec 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("");}}

Version originale, 237 octets:

#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("");}}

Résultat (256x256):

entrez la description de l'image ici

Code original avec des espaces pour une meilleure lisibilité:

#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("");
    }
}

Cela n'utilise aucune bibliothèque graphique, le rendu est entièrement contenu dans le code.

L'idée de base est de simplement boucler sur tous les 256x256 pixels et de voir s'ils sont à l'intérieur / à l'extérieur de l'arc circulaire du sous-carré 32x32 dans lequel ils se trouvent. Les 5 derniers bits des coordonnées globales des pixels définissent les coordonnées relatives du pixel à l'intérieur le sous-carré. Le test intérieur / extérieur d' (x, y)être à l'intérieur de l'arc avec rayon rest alors la norme:

x * x + y * y < r * r

La plupart de la logique consiste à placer le centre de l'arc dans le coin correct du sous-carré et à déterminer quelle couleur est à l'intérieur / à l'extérieur.

Quelques commentaires sur la solution:

  • Le code génère l'image au format PBM ASCII. J'ai chargé le résultat dans GIMP et j'ai fait un copier-coller dans Paint pour générer le fichier réel que j'ai publié ici. Le format a donc été converti, mais le contenu est exactement comme la sortie d'origine.
  • Si vous regardez attentivement, vous remarquerez peut-être que la qualité n'est pas excellente. En effet, le calcul intérieur / extérieur est effectué pour le coin du pixel, au lieu du centre du pixel, ce qui fait que le tout est à 1/2 pixel. Je ne pense pas qu'il serait très difficile de faire mieux, mais cela rendrait le code un peu plus long. Et comme il n'y avait pas d'exigences de qualité spécifiques, je pense que cela suffit.
  • Le code a été compilé à l'aide de clang sur un Mac. La dernière version donne des avertissements, pas la version initiale.
  • C'est la première fois que j'essaie l'un d'entre eux, j'ai donc probablement raté quelques astuces pour enregistrer le dernier octet possible.
Reto Koradi
la source
3
Bienvenue chez PPCG! Je ne suis pas un grand golfeur en C, mais je pense que je peux voir quelques améliorations: groupez vos déclarations comme int a,b,c,d,x,y;... Je pense que vous pourriez même être capable de le faire main(a,b,c,d,x,y)Je me souviens de quelque chose que le type par défaut est int. Une fois que vous êtes débarrassé de cela, vous pouvez déplacer les affectations vers d, x et y dans l' forinstruction d'incrémentation de l'intérieur comme d=c+32&64,...,++c(probablement même déplacer le ++dans un autre endroit où vous mentionnez de ctoute façon), puis vous pouvez omettre les accolades de l'intérieur for. Beau travail, btw! :)
Martin Ender
Merci! J'ai vu l'astuce de déclarer des arguments sans types dans une liste de conseils, mais cela semblait si sale que je ne pouvais pas m'y rendre. ;) Je ne pense pas que le fait d'avoir des arguments non standard main()soit conforme aux standards. Je devrais certainement regrouper les déclarations. Et le déplacement des incréments permettra également d'économiser quelques octets. Le puts()pour la nouvelle ligne est dans la boucle externe, donc je ne sais pas si je peux me débarrasser des accolades.
Reto Koradi
Nous sommes généralement d'accord avec cela tant qu'il compile dans un compilateur commun (il ne doit donc pas être entièrement C standard). De plus, oui, je ne pense pas que vous puissiez vous débarrasser des accolades extérieures, mais vous devriez pouvoir retirer celles intérieures.
Martin Ender
Je l'ai réduit à 210 octets. Merci pour les idées.
Reto Koradi
1
Astuces: stdiopas nécessaire, utilisez la déclaration de fonction par défaut. intest par défaut pour les globaux et peut être omis (variables et main). Le premier putspeut aller à l'intérieur du for. c var n'est pas utilisé à l'intérieur de la boucle interne, donc incrémente en condition. 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("");}}(compile avec de nombreux avertissements mais s'exécute)
edc65