Coloca el avión en mosaico con este círculo modificado


22

Tome un círculo unitario centrado en el origen. En cualquiera de los dos cuadrantes vecinos , refleje la curva del círculo a través de las líneas que conectan las intersecciones x e y del círculo.

Con la forma resultante, puede colocar el plano en mosaico:

mosaico circular

¡Hice esta imagen con el increíble sandbox de física 2D Algodoo !

Escriba un programa que genere una imagen similar a esta en algún formato de archivo de imagen sin pérdida común. Puede guardar la imagen como un archivo con el nombre de su elección o simplemente mostrarla. No se debe tomar ninguna entrada.

Reglas:

  • La totalidad de imagen debe ser teselada con los azulejos de círculo modificado utilizando cualquiera de los dos colores RGB visualmente distintas: una para las baldosas apuntando verticalmente, uno para los azulejos horizontalmente apuntando.

  • El radio de las baldosas circulares debe ser de al menos 32 píxeles. (El radio en la imagen de arriba es de aproximadamente 110 píxeles).

  • La imagen debe tener al menos 4 mosaicos de ancho y 4 mosaicos de alto. Esto, combinado con la regla anterior, significa que las imágenes pueden tener un tamaño mínimo de 256 × 256 píxeles. (La imagen de arriba es de 4 fichas por 4 fichas).

  • La teselación puede traducirse por cualquier cantidad. Por ejemplo, la esquina superior izquierda de la imagen no necesita ser el vértice donde se encuentran los mosaicos. (Sin embargo, la teselación no debe rotarse).

  • Puede usar bibliotecas de gráficos externos que tengan comandos para dibujar círculos y generar imágenes y similares.

  • Las curvas realmente deberían aproximarse a los círculos, como se puede hacer con el algoritmo de círculo de punto medio , que la mayoría de las bibliotecas de gráficos harán por usted.

  • El suavizado alrededor de los bordes de los mosaicos está permitido pero no es obligatorio.

La presentación más corta en bytes gana.

Respuestas:


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

Genera una imagen PBM:

salida

Mnemotécnica:

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

ingrese la descripción de la imagen aquí
Estoy usando tantos parámetros predeterminados para la cámara y la fuente de luz como sea posible, por eso está un poco oscuro. Vamos a deshacerlo primero

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 obvio lo que sucede una vez que aumentamos el desplazamiento del eje del cilindro y cambiamos la perspectiva.

ingrese la descripción de la imagen aquí


1
¿No se distorsionarán ligeramente los bordes gracias a la perspectiva 3D?
orlp

66
Con una altura 0.1y un desplazamiento del 0.001disco inclinado por $ \ phi = \ arctan (0.01) = 0.57 ° $, mirando desde la parte superior los discos aparecen comprimidos por un factor de $ \ cos (\ phi) = 0.99995 $, eso es mucho menos que un píxel.
DenDenDo

@DenDenDo ¿Pov-ray no puede poner una cámara al infinito?
Random832

@ Random832 puede, con camera{orthographic location -9z}. Pero dado que la escena es básicamente 2D, no hay diferencia, incluso puede renderizarla con una visualización angle 170sin ninguna distorsión de ojo de pez en el resultado.
DenDenDo

11

Gnuplot, 182

Noté que los límites entre las celdas se ven muy sinusoidales, así que decidí una solución analítica con una ecuación central muy simple
ingrese la descripción de la imagen aquí

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

ingrese la descripción de la imagen aquí
Si bien se ve similar, los círculos son demasiado cuadrados. Con la misma idea, lo reemplazo sinpor una curva hecha de cuartos de círculo concatenados y lo giro 45 ° reemplazando xy ycon x+yyx-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

ingrese la descripción de la imagen aquí


9

Sin contexto, 99 bytes

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

Puede ver el resultado en la Galería sin contexto .


Agradable, es un uso asombroso 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>

Para probar, guarde como archivo html y ábralo con un navegador. O bien, ejecute el fragmento

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>

Debido a la demanda popular, aquí está la imagen de salida. No es tan emocionante después de todo ...

Azulejos


1
Es posible que desee publicar una imagen para que el código no tenga que ejecutarse cada vez que alguien quiera ver el resultado.
Calvin's Hobbies

@ Calvin'sHobbies oh bueno, es lo suficientemente rápido y se ejecuta en todos los navegadores modernos. En su lugar
agrandaré

Es verdad. Pensé que usaba =>muchas de tus publicaciones y solo funcionaría en Firefox. Pero no te preocupes.
Aficiones de Calvin

1
Mejor razón para publicar una imagen: estos fragmentos no funcionan muy bien en dispositivos móviles :(
Sp3000

6

IDL 8.3, 201 193 183 bytes

La imagen se envía a una ventana de gráficos IDL; Tomé una captura de pantalla, a continuación.

EDITAR: gracias a @AlexA. y @ Sp3000 por ayudarme a reducir algunos 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

ingrese la descripción de la imagen aquí


6

Mathematica: 86 bytes (o 82 bytes)

Gracias al infinito @alephalpha por un método inteligente basado en una matriz:

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

Dentro de la matriz hay una función anónima, que utiliza un truco inteligente para agregar sus argumentos ( +##) y determinar si la suma es impar. Ese booleano se usa como condicional a un patrón que reemplaza todo el mosaico 'blanco' con el mosaico 'negro' transformado. A partir de ahí, ArrayFlattenune los mosaicos y los Imagemuestra.

Tenga en cuenta el uso del más corto Threadpara reemplazar Transpose. Todavía podemos guardar 4 bytes usando el símbolo de transposición en su lugar.

Anterior: 97 bytes (o 90 bytes)

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

Puede reducir el número de bytes reemplazando Transpose@#con el símbolo superíndice-t (punto de código U + F3C7, acceso directo ESCtrESC). En UTF-8 eso lleva el total a 90 bytes en 88 caracteres .

ingrese la descripción de la imagen aquí

Comenzamos con DiskMatrix, que genera una matriz binaria:

DiskMatrix@32 // Image

ingrese la descripción de la imagen aquí

Luego, desplazamos circularmente las filas de la matriz para producir la celda unitaria para el mosaico:

RotateLeft[DiskMatrix@32, 32] // Image

ingrese la descripción de la imagen aquí

Si el avión es un tablero de ajedrez, estos son los cuadrados 'blancos'. Para los cuadrados 'negros', necesitamos invertir los colores y rotar 90 grados. Podemos invertir restando de 1 ( 1 - 1 -> 0y 1 - 0 -> 1), y rotar tomando la transposición:

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

ingrese la descripción de la imagen aquí

Si las dimensiones de la imagen son uniformes (como el tamaño mínimo, 4), un mosaico en el borde derecho será el mismo que el siguiente en el borde izquierdo. Sin embargo, agregar un mosaico para obtener un tamaño impar (5) y luego concatenar las filas produce un patrón alterno regular.

Esto sugiere que podemos obtener la imagen completa envolviendo una sola fila de mosaicos alternos con Partition. Utilizamos Tablepara hacer una lista de pares de fichas en 13blanco y negro, y Joinpara aplanar la lista de pares a una lista de 26 fichas. Luego Partitionla lista en un 5por 5matriz de azulejos ( Partitiondescartes el trasero 26 º azulejo):

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

ingrese la descripción de la imagen aquí

Finalmente ArrayFlattenconvierte la matriz de matrices de mosaico en una matriz plana y Imagemuestra el resultado.

Anterior: 111 bytes

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

ingrese la descripción de la imagen aquí


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

4

Java, 550 540 508 504 bytes

Este es un applet de 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);}}

Ampliado con repetitivo:

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 pequeño programa de aplicación que se puede utilizar para trabajar mientras se trabaja en otra aplicación.

Imagen de ejemplo:

ingrese la descripción de la imagen aquí

Explicación:

Esto funciona utilizando un método para imprimir cada mosaico. Antes de crear el método, se le asigna un objeto gráfico que utiliza un sistema de coordenadas centrado en la esquina superior izquierda de cada mosaico:

Para crear un mosaico, utilizamos el siguiente método:

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

Sin embargo, cualquier otro mosaico debe reflejarse horizontalmente para producir la imagen correcta.

Para reflejar un mosaico, simplemente modificamos el graphicsobjeto suministrado con este código:

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

Gracias @CoolGuy por 4 bytes.


1
Puedes jugar más golf declarando xy ycomo campos de la clase:int a = 98, b = 49,x,y;
Spikatrix

4

Mathematica 299 256

Wordy pero fue agradable descubrirlo.

El mosaico básico es r (que se muestra a continuación), que es una región que muestra RegionPlot. Se realiza un reflejo izquierda-derecha del mosaico y se une con r. La figura ensamblada de dos mosaicos se repite para mosaico del espacio.

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}

azulejo


1

C, 237 209 180 bytes

180 bytes. Esta versión incluye cambios sugeridos por edc65 en un comentario. Da 9 advertencias del compilador cuando se construye en una Mac con clang y opciones predeterminadas:

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, utilizando algunas sugerencias de los comentarios de Martin. Compila sin advertencias con 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("");}}

Versión original, 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("");}}

Resultado (256x256):

ingrese la descripción de la imagen aquí

Código original con espacios en blanco para una mejor legibilidad:

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

Esto no utiliza ninguna biblioteca de gráficos, la representación está completamente contenida en el código.

La idea básica es simplemente recorrer todos los 256x256 píxeles y ver si están dentro / fuera del arco circular del subcuadrado de 32x32 en el que se encuentran. Los 5 bits inferiores de las coordenadas globales de píxeles definen las coordenadas relativas del píxel dentro El sub-cuadrado. La prueba interior / exterior de (x, y)estar dentro del arco con radio res entonces el estándar:

x * x + y * y < r * r

La mayor parte de la lógica es colocar el centro del arco en la esquina correcta del subcuadrado y determinar qué color está adentro / afuera.

Algunos comentarios sobre la solución:

  • El código genera la imagen en formato PBM ASCII. Cargué el resultado en GIMP, e hice una copia y pegué en Paint para generar el archivo real que publiqué aquí. Por lo tanto, el formato se convirtió, pero el contenido es exactamente como el resultado original.
  • Si observa de cerca, puede notar que la calidad no es excelente. Esto se debe a que el cálculo interno / externo se realiza para la esquina del píxel, en lugar del centro del píxel, lo que hace que todo esté 1/2 píxel apagado. No creo que sea muy difícil hacerlo mejor, pero haría que el código sea un poco más largo. Y como no había requisitos de calidad específicos, creo que esto es suficiente.
  • El código fue compilado usando clang en una Mac. La última versión da advertencias, la versión inicial no.
  • Esta es la primera vez que intento uno de estos, por lo que probablemente me perdí algunos trucos para guardar el último byte posible.

3
Bienvenido a PPCG! No soy un gran jugador de golf C, pero creo que puedo ver algunas mejoras: agrupe sus declaraciones como int a,b,c,d,x,y;... Creo que incluso podría hacerlo main(a,b,c,d,x,y). Recuerdo algo que el tipo predeterminado es int. Una vez que se haya librado de eso, puede mover las asignaciones a d, x e y dentro de la fordeclaración de incremento interno como d=c+32&64,...,++c(probablemente incluso moverla ++a otro lugar donde mencione de ctodos modos), y luego puede omitir las llaves de el interior for. Buen trabajo, por cierto! :)
Martin Ender

¡Gracias! Vi el truco con declarar argumentos sin tipos en una lista de consejos, pero parecía tan sucio que no pude llegar allí. ;) No creo que tener argumentos no estándar main()sea ​​compatible con el estándar. Ciertamente debería agrupar las declaraciones. Y mover los incrementos también ahorrará un par de bytes. El puts()para la nueva línea está en el bucle externo, por lo que no estoy seguro de si puedo deshacerme de las llaves.
Reto Koradi

Por lo general, estamos de acuerdo con él siempre que se compile en algún compilador común (por lo que no tiene que ser completamente C estándar). Además, sí, no creo que puedas deshacerte de los frenos externos, pero deberías poder quitar los internos.
Martin Ender

Lo bajé a 210 bytes. Gracias por las ideas
Reto Koradi

1
Sugerencias: stdiono es necesario, utilice la declaración de función predeterminada. intes el valor predeterminado para los globales y se puede omitir (variables y principal). Primero putspuede entrar al for. c var no se usa dentro del bucle interno, por lo tanto, incremente la condición. 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("");}}(compila con muchas advertencias pero se ejecuta)
edc65
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.