Lado a lado com o círculo modificado

22

Faça um círculo unitário centrado na origem. Em dois quadrantes vizinhos , espelhe a curva do círculo através das linhas que conectam as intercepções x e y do círculo.

Com a forma resultante, você pode colocar o plano em mosaico:

mosaico do círculo

Eu fiz essa imagem com a incrível sandbox de física 2D Algodoo !

Escreva um programa que produza uma imagem semelhante a esta em algum formato comum de arquivo de imagem sem perdas. Você pode salvar a imagem como um arquivo com o nome de sua escolha ou pode simplesmente exibi-la. Nenhuma entrada deve ser tomada.

Regras:

  • A imagem inteira deve ser dividida em mosaico com os ladrilhos de círculo modificado usando duas cores RGB visualmente distintas: uma para os ladrilhos apontando verticalmente e outra para os ladrilhos apontando horizontalmente.

  • O raio dos ladrilhos do círculo deve ser de pelo menos 32 pixels. (O raio da imagem acima é de cerca de 110 pixels.)

  • A imagem deve ter pelo menos 4 peças de largura e 4 peças de altura. Isso, combinado com a regra acima, significa que as imagens podem ter um tamanho mínimo de 256 × 256 pixels. (A imagem acima é de 4 peças por 4 peças).

  • O mosaico pode ser traduzido por qualquer valor. Por exemplo, o canto superior esquerdo da imagem não precisa ser o vértice onde os blocos se encontram. (O mosaico não deve ser girado, no entanto.)

  • Você pode usar bibliotecas gráficas externas que possuem comandos para desenhar círculos e gerar imagens e similares.

  • As curvas realmente devem aproximar os círculos, como pode ser feito com o algoritmo do círculo do ponto médio , o que a maioria das bibliotecas gráficas fará por você.

  • A suavização de serrilhado nas bordas dos ladrilhos é permitida, mas não necessária.

O menor envio em bytes vence.

Passatempos de Calvin
fonte

Respostas:

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

Gera uma imagem PBM:

saída

Mnemônicos:

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

insira a descrição da imagem aqui
Estou usando o maior número possível de parâmetros padrão para a câmera e a fonte de luz, é por isso que está um pouco escuro. Permite ungolf-lo primeiro

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

É óbvio o que está acontecendo quando aumentamos o deslocamento do eixo do cilindro e mudamos a perspectiva

insira a descrição da imagem aqui

DenDenDo
fonte
1
As bordas não ficarão ligeiramente distorcidas graças à perspectiva 3D?
orlp
6
Com uma altura de 0.1e um deslocamento do 0.001disco é inclinado em $ \ phi = \ arctan (0,01) = 0,57 ° $, olhando de cima os discos aparecem pressionados por um fator de $ \ cos (\ phi) = 0,99995 $, isso é muito menos que um pixel.
DenDenDo
@DenDenDo o pov-ray não consegue colocar a câmera no infinito?
Random832
@ Random832 pode, com camera{orthographic location -9z}. Mas como a cena é basicamente 2D, não faz diferença, você pode renderizá-la com uma visualização angle 170sem distorção no olho de peixe no resultado.
DenDenDo 10/05
11

Gnuplot, 182

Percebi que os limites entre as células parecem muito sinusoidais, então procurei uma solução analítica com uma equação central muito simples
insira a descrição da imagem aqui

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

insira a descrição da imagem aqui
Embora pareça semelhante, os círculos são quadrados demais. Com a mesma idéia, substituo sinpor uma curva feita de arcos quadricíclicos concatenados e giro-a 45 ° substituindo xe ycom x+yex-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

insira a descrição da imagem aqui

DenDenDo
fonte
9

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

Você pode ver o resultado na Galeria livre de contexto .

MtnViewJohn
fonte
Bom, esse é um uso incrível do 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 testar, salve como arquivo html e abra com um navegador. Ou então, execute o trecho

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>

Devido à demanda popular, aqui está a imagem de saída. Afinal, não é tão emocionante ...

Azulejos

edc65
fonte
1
Você pode postar uma imagem para que o código não precise ser executado toda vez que alguém quiser ver a saída.
Hobbies de Calvin
@ Calvin'sHobbies oh bem, é rápido o suficiente e roda em todos os navegadores modernos. Eu vou fazer a imagem maior, em vez
edc65
Isso é verdade. Eu pensei que ele usava =>muitas postagens e só funcionava no Firefox. Mas não se preocupe.
Hobbies de Calvin
1
Melhor motivo para postar uma imagem: esses trechos não funcionam muito bem no celular :(
Sp3000 9/15/15
6

IDL 8.3, 201 193 183 bytes

A imagem é enviada para uma janela gráfica IDL; Tirei uma captura de tela, abaixo.

EDIT: graças a @AlexA. e @ Sp3000, por me ajudar a raspar alguns 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

insira a descrição da imagem aqui

sirpercival
fonte
6

Mathematica: 86 bytes (ou 82 bytes)

Graças ao infinito @alephalpha por um método inteligente baseado em array:

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

Dentro da matriz há uma função anônima, que usa um truque inteligente para adicionar seus argumentos ( +##) e determinar se a soma é ímpar. Esse booleano é usado como condicional a um padrão que substitui todo o bloco 'branco' pelo bloco 'preto' transformado. A partir daí, ArrayFlattenjunta os ladrilhos e os Imageexibe.

Observe o uso do menor Threadpara substituir Transpose. Ainda podemos salvar 4 bytes usando o símbolo de transposição.

Anterior: 97 bytes (ou 90 bytes)

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

Você pode reduzir o número de bytes substituindo pelo Transpose@#símbolo sobrescrito-t (ponto de código U + F3C7, atalho ESCtrESC). No UTF-8, o total é de 90 bytes em 88 caracteres .

insira a descrição da imagem aqui

Começamos com DiskMatrix, o que gera uma matriz binária:

DiskMatrix@32 // Image

insira a descrição da imagem aqui

Em seguida, deslocamos circularmente as linhas da matriz para produzir a célula unitária para o lado a lado:

RotateLeft[DiskMatrix@32, 32] // Image

insira a descrição da imagem aqui

Se o avião é um tabuleiro de xadrez, esses são os quadrados 'brancos'. Para os quadrados "pretos", precisamos inverter as cores e girar 90 graus. Podemos inverter subtraindo de 1 ( 1 - 1 -> 0e 1 - 0 -> 1) e girando assumindo a transposição:

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

insira a descrição da imagem aqui

Se as dimensões da imagem forem pares (como o tamanho mínimo, 4), um bloco na borda direita será o mesmo que o próximo na borda esquerda. No entanto, adicionar um bloco para obter um tamanho ímpar (5) e concatenar as linhas produz um padrão alternado regular.

Isso sugere que podemos obter a imagem completa envolvendo uma única linha de blocos alternados Partition. Usamos Tablepara fazer uma lista de 13pares de ladrilhos preto / branco e Joinachatar a lista de pares para uma lista de 26 ladrilhos. Em seguida, Partitiona lista em um 5por 5matriz de azulejos ( Partitiondevoluções da fuga 26 th telhas):

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

insira a descrição da imagem aqui

Finalmente, ArrayFlattentransforma a matriz de matrizes de mosaico em uma matriz plana e Imageexibe o resultado.

Anterior: 111 bytes

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

insira a descrição da imagem aqui

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

Java, 550 540 508 504 bytes

Este é um 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);}}

Expandido com clichê:

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: um pequeno programa de aplicativo que pode ser chamado para uso enquanto estiver trabalhando em outro aplicativo.

Imagem de exemplo:

insira a descrição da imagem aqui

Explicação:

Isso funciona usando um método para imprimir cada bloco. Antes da criação do método, ele recebe um objeto gráfico que usa um sistema de coordenadas centralizado no canto superior esquerdo de cada bloco:

Para criar um bloco, usamos o seguinte 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);
}

No entanto, todos os outros ladrilhos devem ser refletidos horizontalmente para produzir a imagem correta.

Para refletir um bloco, simplesmente modificamos o graphicsobjeto fornecido com este código:

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

Obrigado @CoolGuy por 4 bytes.

O número um
fonte
1
Você pode golfe mais declarando xe ycomo campos da classe:int a = 98, b = 49,x,y;
Spikatrix
4

Mathematica 299 256

Wordy, mas foi bom descobrir.

O bloco básico é r (mostrado abaixo), que é uma região exibida pelo RegionPlot. Uma reflexão esquerda-direita do bloco é feita e unida a r. A figura montada de dois ladrilhos é então repetida para ladrilhar o espaço.

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}

telha

DavidC
fonte
1

C, 237 209 180 bytes

180 bytes. Esta versão inclui as alterações sugeridas por edc65 em um comentário. Emite 9 avisos do compilador ao criar em um Mac com clang e opções padrão:

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, usando algumas sugestões de comentários de Martin. Compila sem avisos com 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("");}}

Versão 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):

insira a descrição da imagem aqui

Código original com espaço em branco para melhor legibilidade:

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

Isso não usa nenhuma biblioteca de gráficos, a renderização está completamente contida no código.

A idéia básica é simplesmente fazer um loop sobre todos os 256x256 pixels e ver se eles estão dentro / fora do arco circular do sub-quadrado 32x32 em que estão. Os 5 bits inferiores das coordenadas gerais de pixel definem as coordenadas relativas do pixel dentro o sub-quadrado. O teste interno / externo de (x, y)estar dentro do arco com raio ré o padrão:

x * x + y * y < r * r

A maior parte da lógica é colocar o centro do arco no canto correto do sub-quadrado e determinar qual cor está dentro / fora.

Alguns comentários sobre a solução:

  • O código gera a imagem no formato PBM ASCII. Carreguei o resultado no GIMP e fiz uma cópia e colagem no Paint para gerar o arquivo real que publiquei aqui. Portanto, o formato foi convertido, mas o conteúdo é exatamente como a saída original.
  • Se você olhar atentamente, poderá perceber que a qualidade não é ótima. Isso ocorre porque o cálculo interno / externo é feito para o canto do pixel, em vez do centro do pixel, fazendo com que tudo fique com 1/2 pixel de diferença. Eu não acho que seria muito difícil fazer melhor, mas isso tornaria o código um pouco mais longo. E como não havia requisitos de qualidade específicos, acredito que isso seja suficiente.
  • O código foi compilado usando clang em um Mac. A versão mais recente fornece avisos, a versão inicial não.
  • Esta é a primeira vez que tentei um desses, então provavelmente perdi alguns truques para salvar o último byte possível.
Reto Koradi
fonte
3
Bem-vindo ao PPCG! Eu não sou um grande jogador de golfe C, mas acho que posso ver algumas melhorias: agrupe suas declarações como int a,b,c,d,x,y;... Acho que você pode até fazer main(a,b,c,d,x,y)isso. Lembro-me de algo que o tipo padrão é int. Depois de se livrar disso, você pode mover as atribuições para d, x e y para a forinstrução de incremento do interior , como d=c+32&64,...,++c(provavelmente até mover ++para outro lugar onde você menciona de cqualquer maneira), e então pode omitir os colchetes de o interior for. Bom trabalho, btw! :)
Martin Ender
Obrigado! Vi o truque ao declarar argumentos sem tipos em uma lista de dicas, mas parecia tão sujo que não consegui ir lá. ;) Não acho que ter argumentos fora do padrão main()seja compatível com o padrão. Eu certamente deveria agrupar as declarações. E mover os incrementos também economizará alguns bytes. O puts()para a nova linha está no loop externo, então não tenho certeza se posso me livrar dos aparelhos.
Reto Koradi
Normalmente, estamos de acordo, desde que compilados em algum compilador comum (para que ele não precise ser totalmente C padrão). Também sim, acho que você não pode se livrar dos aparelhos externos, mas deve ser capaz de remover os internos.
Martin Ender
Reduzimos para 210 bytes. Obrigado pelas idéias.
Reto Koradi
1
Dicas: stdionão é necessário, use a declaração de função padrão. inté padrão para globais e pode ser omitido (variáveis ​​e principal). Primeiro putspode entrar no for. c var não é usado dentro do loop interno; portanto, aumente a condição. 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 com muitos avisos, mas runs)
edc65