Pontos fractal em uma linha


12

Às vezes, quando estou realmente entediado ( muito entediado), gosto de desenhar um segmento de linha e desenhar pontos nele.

Primeiro, eu desenho um segmento de linha de um determinado tamanho, que é 2 ^ N para algum valor de N. A linha será representada por uma série de .caracteres.

................

Então, traço um ponto no lado esquerdo. Os pontos serão representados por Xcaracteres.

X...............

Então, sigo um padrão. Começando no ponto plotado mais recentemente (que chamarei de A), avanço para o próximo ponto plotado (B) na linha (contornando conforme necessário). Então, eu avanço para o próximo ponto plotado na linha (C). Então, traço um novo ponto a meio caminho entre este terceiro ponto (C) e o próximo ponto já plotado (D).

Sempre que você contorna a linha, o "meio" é determinado da maneira de quebra. O ponto recém-plotado está sempre à direita de C.

Digamos que a seguinte linha fosse minha linha atual. Aqui está como eu traçaria os próximos dois pontos. Neste exemplo, vou rotular cada ponto importante com uma letra.

X...A...X.X...X.
    ^

X...A...B.X...X.
        ^

X...A...B.C...X.
          ^

X...A...B.C...D.
            ^

X...X...X.X.A.X.
            ^

X...X...X.X.A.B.
              ^

C...X...X.X.A.B.
^

C...D...X.X.A.B.
  ^

X.A.X...X.X.X.X.
  ^

Voltando ao exemplo anterior, o próximo ponto será plotado no meio da linha.

X.......X.......

Talvez esse seja um caso especial: avançar para o próximo ponto simplesmente deixa você onde começou. O único ponto intermediário útil é o ponto intermediário "cíclico" (o ponto intermediário da linha), em vez de plotar um ponto em cima de si.

Abaixo está a série de pontos que eu traçaria na linha daqui até o fim.

X.......X.......
X.......X...X...
X.......X.X.X...
X...X...X.X.X...
X...X...X.XXX...
X.X.X...X.XXX...
X.X.X...XXXXX...

Não há mais espaço para plotar o próximo ponto, pois ele teria que ser entalado entre dois pontos adjacentes; portanto, alcancei a profundidade máxima para o valor especificado de N = 4. A última linha da lista acima está "completa" . "

O desafio

O objetivo é escrever o programa mais curto / função nomeada que imprimirá / retornará a linha concluída para um determinado valor de N. O exemplo acima mostra N = 4.

Entrada

A entrada será um único número inteiro não negativo N. O comprimento da linha gerada será então 2 ^ N.

Resultado

A saída será a linha completa de comprimento 2 ^ N, formada por .e Xcaracteres. Uma nova linha à direita não importa.

Exemplo de E / S

0
X

1
XX

2
X.XX

3
X.X.XXX.

4
X.X.X...XXXXX...

5
X.X.X...X...X...X.XXX.XXX.......

Respostas:


4

Python 2, 137

n=input()
l=[0]*2**n;i=0
while~i%2:i=i/2%2**n;l[i]=1;i=sum([k for k,v in enumerate(l*4)if(k>i)*v][1:3])
print''.join(['.X'[x]for x in l])

Bem direto.

Pyth, 49

Mais ou menos uma tradução. A principal diferença é que eu não uso uma lista representando a linha, uso uma string.

J*\.^2QW!%Z2K%/Z2lJ=JXJK\X=Zs<tf&q\X@JT>TKU*4J2)J

Experimente online .

                         Q=input(); Z=0 #implicit
J*\.^2Q                  J = "."*(2^Q)
W!%Z2                    while !(Z%2):
  K%/Z2lJ                  K=(Z/2)%(len(J))
  =JXJK\X                  change J, the point at index K is changed to a "X"
       f          U*4J     filter all elements T in [0, 1, 2, ..., 4*len(J)-1]:
        &q\X@JT>TK           where J[T]=='X' and T>K
     <t               2    only us the second and third element
  =Zs                      and store the sum to Z
)J                       end while and print J

4

Clipe , 95

[z?zF#2(z*2*:(#2(z'.'X]'X]]n[Fa[b[q[j[r?=rirFrsrb'X]b]][t[u+*<ut*Blb/+tu2]]g+2jqg+3jq]#qa]%b'X}

3

GolfScript (61 bytes)

~2\?,[]0{.@|$4*.@?2+1$>2<.+~<!4$,*++.2/\1&!}do;`{&!'X.'1/=}+%

O número de iterações de loop necessárias parece ser A061419 , mas o loop é menor que o cálculo. Um divmod salvaria um caractere dentro do loop do. A parte que parece mais esbanjadora é a conversão de saída, mas não vejo como melhorá-la.



2

Java, 209 207 195 191 bytes

Estou surpreso por ter conseguido ficar tão curto. Provavelmente ainda há espaço para melhorias. Como de costume, sugestões serão apreciadas :)

Isso retorna a char[]. Ligue usando a(n).

char[]a;int b,c,d,e=2;char[]a(int f){java.util.Arrays.fill(a=new char[b=1<<f],'.');for(a[0]=88;d+1<e;c=(d+e)/2,a[c%b]=88)e=b(d=b(b(c)));return a;}int b(int f){for(;;)if(a[++f%b]>87)return f;}

Recuado:

char[] a;
int b, c, d, e = 2;

char[] a(int f){
    java.util.Arrays.fill(
            a = new char[
                    b = 1 << f
                    ]
            , '.'
    );
    for(
            a[0] = 88;
            d + 1 < e;
                c = (d + e) / 2,
                a[c % b] = 88
        )
        e = b(
                d = b(
                        b(c)
                )
        );
    return a;
}

int b(int f){
    for (;;)
        if (a[++f % b] > 87)
            return f;
}

12 bytes graças a Peter :)
4 bytes graças a TNT;)


(c%b+b)%b? Você espera cser negativo?
Peter Taylor

c=0e d=0pode ser reduzido para apenas ce d. inttipos definidos no nível da classe são automaticamente inicializados como 0.
TNT

1

Haskell, 182 bytes

(a:b)%(c:d)|a<c=a:b%(c:d)|1<2=c:(a:b)%d
f i=putStr$map(!(0:g[0,n..]))[0..n-1]where n=2^i;e!l|e`elem`l='X'|1<2='.';g(_:_:c:d:r)|m==c=[]|1<2=mod m n:g((d:r)%[m,m+n..])where m=div(c+d)2

Uso: f 5. Saída: X.X.X...X...X...X.XXX.XXX........

Infelizmente, Haskell não tem uma função de mesclagem nas bibliotecas padrão, então tenho que fornecer minha própria (-> %). Felizmente, tenho que mesclar apenas listas infinitas, para não precisar cobrir os casos básicos, ou seja, listas vazias. Ainda custa 40 bytes.

Como funciona: em vez de definir os Xs diretamente em uma matriz, mantenho uma lista de posições onde elas estão. Além disso, eu não passo em volta, 2^Nmas continuo aumentando as posições em direção ao infinito (por exemplo, para N = 2 com um Xna frente, a lista de posições se parece [0,4,8,12,16,20,…]). Pego o 3º e o 4º elemento ( ce d), calculo a nova posição (c+d)/2, mantenho-a para a lista de saída, mesclo a lista de posições antiga da posição 4 (a d) com uma nova começando (c+d)/2e retornando. Eu paro quando (c+d)/2é igual c. Finalmente, adiciono 0a à lista de saída e imprimo Xs nas posições indicadas e em .outros lugares.

step by step example, N=2

step  position list       (c+d)/2  output     lists to merge (pos. list for next round)
                                   list       old list from d on / new list from (c+d)/2

  #1  [0,4,8,12,16,…]       10     [10]          [12,16,20,24,…] / [10,14,18,22,…]
  #2  [10,12,14,16,18,…]    15     [10,15]       [16,18,20,22,…] / [15,19,23,27,…]
  #3  [15,16,18,19,20,…]    18

stop here, because c equals (c+d)/2

add 0 to the output list: [0,10,15]
take all elements modulo 2^N: [0,2,3]
print X at position 0, 2 and 3 

1

Mathematica, 110 102 112 108

a=Array["."&,n=2^Input[]];a[[Mod[Round@{n/2,n}//.{x_,y_,z___}/;y-x>1:>{z,x+n,(x+y)/2+n,y+n},n]+1]]="X";""<>a
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.