Imagens binárias de contagens de triângulos

18

Meus desafios tendem a ser um pouco difíceis e pouco atraentes. Então, aqui, algo fácil e divertido.

A sequência de Alcuin

A sequência de Alcuin A(n) é definida pela contagem de triângulos. A(n)é o número de triângulos com lados inteiros e perímetro n. Esta sequência é chamada após Alcuin de York.

Os primeiros elementos desta sequência, começando com n = 0são:

0, 0, 0, 1, 0, 1, 1, 2, 1, 3, 2, 4, 3, 5, 4, 7, 5, 8, 7, 10, 8, ...

Por exemplo A(9) = 3, porque os únicos triângulos com lados inteiros e perímetro 9são 1 - 4 - 4, 3 - 3 - 3e 2 - 3 - 4. Você pode ver os três triângulos válidos abaixo.

Triângulos com lados inteiros e perímetro 9

Há algum padrão bastante interessante nessa sequência. Por exemplo A(2*k) = A(2*k - 3).

Para mais informações, consulte A005044 no OEIS.

Desafio

Mas seu desafio é sobre a representação binária desses números. Se convertermos cada número de sequência em sua representação binária, colocá-los em vetores de coluna e alinhá-los, cria uma imagem binária bastante interessante.

Na figura a seguir, você pode ver a representação binária dos números de sequência A(0), A(1), ..., A(149). Na primeira coluna, você pode ver a representação binária de A(1), na segunda coluna, a representação de A(1)e assim por diante.

Representação binária da sequência de Alcuin de n = 0 a 149

Você pode ver algum tipo de padrão de repetição nesta imagem. Até parece meio fractais, se você olhar, por exemplo, a imagem com os números de sequência A(600), A(601), ..., A(899).

Representação binária da sequência de Alcuin de n = 600 a 899

Seu trabalho é gerar essa imagem. Sua função, seu script receberá dois números inteiros 0 <= m < ne deve gerar a imagem binária da sequência de Alcuin A(m), A(m+1), A(m+2), ..., A(n-2), A(n-1). Então a entrada 0, 150gera a primeira imagem, a entrada 600, 900a segunda imagem.

Você pode usar qualquer formato gráfico popular que desejar. Digamos que todos os formatos que podem ser convertidos para png usando image.online-convert.com . Como alternativa, você pode exibir a imagem na tela. Nenhuma linha branca inicial é permitida!

Isso é código-golfe. Portanto, o código mais curto (em bytes) vence.

Jakube
fonte
3
Eh, eu estava interessado em fazer esse desafio até chegar à parte sobre a criação de uma imagem binária. Parece um passo estranho. Não me apetece aprender uma biblioteca para criação de imagens em Python, e espero que, se o fizesse, não haveria muito para jogar golfe.
Xnor
1
@xnor: Em seguida, use um formato de imagem simples como PBM .
Jakube
É white=1 and black=0ou o contrário?
Maltysen
@Maltysen white=0 and black=1. Então, o contrário. A(0)produz uma coluna branca, A(9)=3produz uma coluna branca com 2 pixels pretos na parte inferior.
Jakube
1
Tem certeza de que a primeira imagem está correta? Tem 0,0,0,1,0,2enquanto a lista no início da pergunta diz 0,0,0,1,0,1.
Maltysen

Respostas:

2

J ( 52 45 (página de código 437))

Isso seria permitido (eu acho)

[:|:' █'{~[:#:[:([:<.48%~*:+24+6*]*2|])(}.i.)

Hex dump

(Nada realmente especial, o quadrado preto é DB 16 ou 219 10 na página de código 437.)

0000: 5b 3a 7c 3a 27 20 db 27 7b 7e 5b 3a 23 3a 5b 3a   [:|:' .'{~[:#:[:
0010: 28 5b 3a 3c 2e 34 38 25 7e 2a 3a 2b 32 34 2b 36   ([:<.48%~*:+24+6
0020: 2a 5d 2a 32 7c 5d 29 28 7d 2e 69 2e 29            *]*2|])(}.i.)

Uso

Isso resulta da seguinte maneira (as tags de código estragam tudo adicionando espaço entre as linhas):

   A=:[:|:' █'{~[:#:[:([:<.48%~*:+24+6*]*2|])(}.i.)
   0 A 100
                                                                             █ █████████████████████                                          
                                                     █ ██████████████████████ █              █ █████                          
                                     █ ██████████████ █          █ ██████████ █      █ ██████ █                   
                         █ ██████████ █      █ ██████ █    █ ████ █    █ ████ █  █ ██ █  █ ██ █  █ █  
                 █ ██████ █    █ ████ █  █ ██ █  █ ██ █  █  █  █  █  █  ██ ██ ██  ██  ██  ██  ██  ██
           █ ████ █  █ ██ █  █  █  █  ██  ██  ██  ██  ██  █  █  █  █ ██ █  █ ████ █                               
       █ ██ █  █  ██  ██  ██  █  █ ██ █                █ ██ █  █  ██  ██  ██  █  █ ██ █                                   
   █ ██ ██  ██ ██ █        █ ██ ██  ██ ██ █        █ ██ ██  ██ ██ █        █ ██ ██  ██ ██ █        █    
   2000 A 2100
████████████████████████████████████████████████████████████████████████████████████████████████████

████████████████████████████████████████████████████████████████████████████████████████████████████
                                                                             █ █████████████████████
                             █ ██████████████████████████████████████████████ █
     █ ██████████████████████ █                      █ ██████████████████████ █
█████ █          █ ██████████ █          █ ██████████ █          █ ██████████ █          █ █████████
 ████ █    █ ████ █    █ ████ █    █ ████ █    █ ████ █    █ ████ █    █ ████ █    █ ████ █    █ ███
█  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █
██  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █ ██ ██ █
 █ ██ ██ ██ ██ ██ █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  █  ██ ██ ██ ██ ██  █  █
  ██ ██ ██  █  █  ██ ██ ██  █  █  █  █  █  █  █  █  █  █  █  █  █  █ ██ ██ ██ █  █  █  █ ██ █  █ ██
 █ ██ █  █ ██ █  █ ██ █  █ ██ █  █  █  █  █  █  █  █  █  █  ██ ██ ██  █  █  ██  ██ ██ ██  ██  ██  ██
  ██  ██  ██  ██  ██  ██  ██  ██ ██ ██  █  █  █  █  █  █ ██ █  █ ██ █  █ ████ █    █ ██████ █
█ █                        █ ████ █  █ ██ █  █  █  █  ██  ██  ██  ██  ██  █  █  █  █ ██ █  █ ████ █
 █ ██ █                █ ██ █  █  ██  ██  ██  █  █ ██ █                █ ██ █  █  ██  ██  ██  █  █ █
██  ██ ██ █        █ ██ ██  ██ ██ █        █ ██ ██  ██ ██ █        █ ██ ██  ██ ██ █        █ ██ ██

No console J padrão, não há espaçamento entre as linhas, então chamo a regra 'Como alternativa, você pode exibir a imagem na tela'. (Em nenhum lugar foi dito que essa imagem precisava ser representada internamente como um formato de imagem sensível)

EDIT: Jconsole (ao contrário de JQT) usa a página de códigos 437 como padrão e renderiza os retângulos corretamente ao usá-los a partir de uma sequência.

ɐɔıʇǝɥʇuʎs
fonte
9

Mathematica, 126 122 121 89 bytes

Image[1-Thread@IntegerDigits[l=Round[(#+3#~Mod~2)^2/48]&/@Range@##,2,⌈2~Log~Max@l⌉]]&

Isso define uma função sem nome, tendo os dois números inteiros como parâmetros e exibindo a imagem na tela. Ele plota cada quadrado como um único pixel, mas se você quiser, pode aumentar o zoom.

Agora estou usando uma fórmula explícita dada no artigo da OEIS (primeira na seção Mathematica, obrigado a David Carraher por apontar isso). Também é incrivelmente rápido agora.

Aqui está o código recuado com alguns comentários:

Image[1-Thread@IntegerDigits[   (* 3. Convert each number to padded binary, transpose
                                      invert colours, and render as Image. *)
    l = Round[
      (#+3#~Mod~2)^2/48
    ] & /@ Range@##,            (* 1. Turn input into a range and get the Alcuin
                                      number for each element. *)
    2,
    ⌈2~Log~Max@l⌉               (* 2. Determine the maximum number of binary digits. *)
]] &

Aqui está a saída para 0, 600:

insira a descrição da imagem aqui

Martin Ender
fonte
Apenas sobre o mesmo tamanho (porque esquerda e teto direito deve ser explicitada):Image[1 - Thread@IntegerDigits[ l = Round[If[EvenQ[#], #^2, (# + 3)^2]/48] & /@ Range@##, 2, \[LeftCeiling]2~Log~Max@l\[RightCeiling]]] &
DavidC
@DavidCarraher Obrigado, eu joguei um pouco mais. :) (Deveria ter conferido o artigo da OEIS).
Martin Ender
8

CJam ( 56 55 53 caracteres) / GolfScript (64 caracteres)

CJam:

"P1"q~,>{_1&3*+_*24+48/}%_:e>2b,\2_$#f+2fbz(,@@:~~]N*

GolfScript:

"P1"\~,>{.1&3*+.*24+48/}%.$-1=2base,\{2.$?+2base}%zip(,@@{~}/]n*

Ambos produzem saída no formato NetPBM e são essencialmente portas um do outro.

Dissecação

CJam                 GolfScript           Explanation

"P1"                 "P1"\                NetPBM header
q~,>                 ~,>                  Create array [m .. n-1]
{_1&3*+_*24+48/}%    {.1&3*+.*24+48/}%    Map the sequence calculation
_:e>2b,\             .$-1=2base,\         Compute image height H as highest bit
                                          in largest number in sequence
2_$#f+2fb            {2.$?+2base}%        Map sequence to bits, ensuring that
                                          each gives H bits by adding 2^H
z(,@@                zip(,@@              Transpose and pull off dummy row to use
                                          its length as the "width" in the header
:~~                  {~}/                 Flatten double array and dump on stack
]N*                  ]n*                  Separate everything with whitespace

Agradecimentos ao Optimizer para CJam 56 -> 53.

Peter Taylor
fonte
1
Qualquer motivo para você não ter "P1" no início e, assim, economizar 1 byte, evitando o ``?
Optimizer
@Otimizador, muito acostumado a pensar em GS.
22715 Peter
Não é bem assim: a altura precisa aparecer na saída. Mas ainda há uma economia a ser feita com o encurtamento do mapa.
Peter Taylor
51:'PoXq~{_1&3*+_*24+48/}%>_:e>2b,\2_$#f+2fbz(,@@]e_N*
Otimizador
5

Pitão - 101 60 59

Saídas a .pbm. Provavelmente pode ser jogado mais.

Km.B/++24*dd**6%d2d48rvzQJCm+*\0-eSmlkKlddK"P1"lhJlJjbmjbdJ

Altamente não-destruído, porque eu vou traduzir para Pyth.

Explicação a seguir. Agora, observe o código Python equivalente.

Ele usa o algoritmo OEIS para calcular a sequência e depois converte em binário, preenche os números, faz uma rotação de matriz e formata-a em uma pbmimagem. Como não estou usando força bruta, é incrivelmente rápido.

         K=
 m          rvzQ      Map from eval input to eval input
  .B                  Binary rep
   /      48          Divided by 48
    ++                Triple sum      
     24               Of 24,
     *dd              Square of d
     **               Triple product
      6               6
      %d2             Modulo d%2
      d               Var d
J                     Set J=
 C                    Matrix rotation from columns of row to rows of columns
  m           K       Map K (This does padding)
   +                  String concat
    *                 String repeat
     \0               "0"
     -     ld         Subtract the length of the column from
      eS              The max
       mlkK           Of all the column lengths
    d                 The column
"P1"                  Print header "P1"
l                     Length of
 hJ                   First row
lJ                    Number of columns
jb                    Join by linebreaks
 m  J                 Map on to J
  jb                  Joined columns by linb
   d

Aqui está o 600,900exemplo:

600 - 900

Experimente aqui online .

Maltysen
fonte
4

R - 127 125

Não tenho certeza se isso está de acordo com as regras totalmente. Ele não gera uma imagem em um arquivo, mas cria uma varredura e a plota em um dispositivo de saída.

Eu encontrei a mesma fórmula que Martin, mas aqui .

Ele usa uma função sem nome.

require(raster);function(m,n)plot(raster(mapply(function(n)rev(as.integer(intToBits(round((n+n%%2*3)^2/48)))),m:n),0,n,0,32))

Execute da seguinte maneira

require(raster);(function(m,n)plot(raster(mapply(function(n)rev(as.integer(intToBits(round((n+n%%2*3)^2/48)))),m:n),0,n,0,32)))(0,600)

Produz o seguinte gráfico

insira a descrição da imagem aqui

MickyT
fonte
Você pode eliminar 7 bytes por não anexar rasterao espaço para nome, pois raster()é a única coisa específica nesse pacote. Em vez disso, faça raster::raster(...).
Alex A.
@AlexA. Obrigado, vai fazer essa edição
MickyT
@AlexA. Infelizmente, eu apenas tentei e erros para mim. Eu suspeito que é porque raster requer sp também. Vou ver se consigo encontrá-lo.
MickyT
Vadio. Desculpe por ter desviado você.
Alex A.
3

Python 2 + PIL , 255 184

Minha primeira versão usou o PIL para mostrar uma imagem:

i,R,B=input,range,lambda x:bin((x*x+6*x*(x%2)+24)/48)[2:]
def F(k,v):i.load()[k]=v
a,b=i(),i();h=len(B(b));from PIL import Image;i=Image.new('P',(b-a,h))
[F((x-a,y),int(B(x).zfill(h)[y])) for x in R(a,b) for y in R(h)]
i.putpalette([255]*3+[0]*3)
i.show()

A nova versão apenas produz uma imagem PPM em preto e branco no stdout:

i,R,B=input,range,lambda x:bin((x*x+6*x*(x%2)+24)/48)[2:]
def p(s):print s
a,b=i(),i();h=len(B(b));p('P1 %i %i'%(b-a,h))
[p(' '.join([B(x).zfill(h)[y] for x in R(a,b)])) for y in R(h)]
dieter
fonte
Alguns caracteres são salvos para a versão PPM: você não precisa de um espaço antes for. Você pode evitar parênteses x%2alterando a ordem para x%2*.... É mais curto não definir impressão como uma função e apenas usar dois forloops aninhados , print ...,para evitar novas linhas e um espaço printem branco para iniciar uma nova linha. Um truque para forçar expansões binárias a terem comprimento hsem zfillé adicionar e 2**h, em seguida, extrair os últimos hdígitos.
Xnor
2

JAVASCRIPT - 291

Código:

(function(a,b,c){c.width=b;t=c.getContext('2d');t.strokeStyle='black';for(i=a;i<=b;i++){g=(Math.floor(((i*i)+6*i*(i%2)+24)/48)>>>0).toString(2);l=g.length;for(j=0;j<l;j++){if(g[l-1-j]=='1'){t.rect(i-a,j,1,1);t.fill();}}}document.body.appendChild(c);})(0,300,document.createElement('canvas'))

Explicação:

(function (a, b, c) {
    //setting canvas width
    c.width = b;
    //get context 2d of canvas
    t = c.getContext('2d');
    //setting storke style.
    t.strokeStyle = 'black';
    //looping from a to b
    for (i = a; i <= b; i++) {
        //calculating A(i) and converting it to a binary string
        g = (Math.floor(((i * i) + 6 * i * (i % 2) + 24) / 48) >>> 0).toString(2);
        //looping through that string
        for (j = 0; j < g.length; j++) {
            //since canvas is upside down and the first digit is actually the last digit:
            if (g[g.length - 1 - j] == '1') {
                //we create the 1 by 1 rect
                t.rect(i - a, j, 1, 1);
                //we draw the rect
                t.fill();
            }
        }
    }
    //we append everything to the body
    document.body.appendChild(c);
    //parameters are put here
})(0, 300, document.createElement('canvas'))

Resultado:

Sim, o resultado está de cabeça para baixo, mas é porque 0,0em um js canvascanto superior esquerdo. : 3 Sequência de Alquin

Demo:

Demonstração sobre jsfiddle

kemicofa apoia Monica
fonte