Punti di frattale su una linea


12

A volte, quando sono davvero annoiato ( davvero annoiato), mi piace disegnare un segmento di linea e disegnare punti su di esso.

Innanzitutto, disegno un segmento di una certa dimensione, che è 2 ^ N per un valore di N. La linea sarà rappresentata da una serie di .caratteri.

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

Quindi, tracciamo un punto all'estremità sinistra. I punti saranno rappresentati da Xpersonaggi.

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

Quindi, seguo un modello. A partire dal punto tracciato più di recente (che chiamerò A), avanzerò al punto tracciato successivo (B) sulla linea (avvolgendo se necessario). Quindi, passo al prossimo punto tracciato sulla linea (C). Quindi, tracciamo un nuovo punto a metà tra questo terzo punto (C) e il successivo punto già tracciato (D).

Ogni volta che avvolgi la linea, il "mezzo" viene determinato in modo avvolgente. Il punto appena tracciato è sempre alla destra di C.

Diciamo che la seguente riga era la mia linea corrente. Ecco come vorrei tracciare i prossimi due punti. Per questo esempio, etichetterò ogni punto importante con una lettera.

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.
  ^

Tornando all'esempio precedente, il punto successivo verrà tracciato nel mezzo della linea.

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

Questo è forse un po 'un caso speciale: passare al punto successivo ti lascia semplicemente dove hai iniziato. L'unico punto a metà utile è il punto a metà "ciclico" (il punto a metà sulla linea), invece di tracciare un punto sopra se stesso.

Di seguito è riportata la serie di punti che vorrei tracciare sulla linea da qui alla fine.

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

Non c'è più spazio per tracciare il punto successivo, poiché dovrebbe essere incuneato tra due punti adiacenti, quindi ho raggiunto la profondità massima per il valore dato di N = 4. L'ultima riga dell'elenco sopra è "completa ".

La sfida

L'obiettivo è scrivere il programma più breve / la funzione con nome che stamperà / restituirà la riga completata per un dato valore di N. Quanto sopra mostra N = 4.

Ingresso

L'input sarà un singolo intero non negativo N. La lunghezza della linea generata sarà quindi 2 ^ N.

Produzione

L'output sarà la riga completata di lunghezza 2 ^ N, formata da .e Xcaratteri. Una nuova riga finale non ha importanza.

Esempio di I / O

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

Risposte:


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

Abbastanza semplice.

Pyth, 49

Più o meno una traduzione. La differenza principale è che non uso un elenco che rappresenta la linea, uso una stringa.

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

Provalo 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

Clip , 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 byte)

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

Il numero di iterazioni di loop richieste sembra essere A061419 , ma il do-loop è più breve del calcolo. Un divmod salverebbe un carattere all'interno del ciclo do. La parte che sembra più dispendiosa è la conversione dell'output, ma non vedo come migliorarla.



2

Java, 209 207 195 191 byte

Sono sorpreso di essere riuscito a farlo così in fretta. Probabilmente c'è ancora spazio per miglioramenti. Come al solito, i suggerimenti saranno apprezzati :)

Questo restituisce a char[]. Chiama 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;}

rientrato:

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 byte grazie a Peter :)
4 byte grazie a TNT;)


(c%b+b)%b? Ti aspetti cdi essere negativo?
Peter Taylor,

c=0e d=0può essere abbreviato in solo ce d. inti tipi definiti a livello di classe vengono automaticamente inizializzati su 0.
TNT

1

Haskell, 182 byte

(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. Uscita: X.X.X...X...X...X.XXX.XXX........

Sfortunatamente Haskell non ha una funzione di unione nelle librerie standard, quindi devo fornire la mia (-> %). Fortunatamente devo unire solo elenchi infiniti, quindi non devo coprire i casi di base, ovvero elenchi vuoti. Costa ancora 40 byte.

Come funziona: invece di impostare le Xs direttamente in un array, tengo un elenco delle posizioni in cui si trovano. Inoltre non mi giro a, 2^Nma continuo ad aumentare le posizioni verso l'infinito (ad es. Per N = 2 con una Xin primo piano, l'elenco delle posizioni appare come [0,4,8,12,16,20,…]). Prendo il 3o e 4o elemento ( ce d), calcolo la nuova posizione (c+d)/2, la conservo per la lista di output, unisco la vecchia lista di posizioni dalla posizione 4 (la d) in poi con una nuova a partire da (c+d)/2e ricomincio . Mi fermo quando è (c+d)/2uguale c. Infine aggiungo 0a alla lista di output e stampo Xs nelle posizioni indicate e .altrove.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.