Fraktale Punkte auf einer Linie

12

Manchmal, wenn ich wirklich gelangweilt bin ( wirklich gebohrt), ich mag ein Liniensegment zeichnen und darauf verweisen zu ziehen.

Zuerst zeichne ich ein Liniensegment einer bestimmten Größe, die 2 ^ N für einen Wert von N ist. Die Linie wird durch eine Reihe von .Zeichen dargestellt.

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

Dann zeichne ich einen Punkt am linken Ende. Punkte werden durch XZeichen dargestellt.

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

Dann folge ich einem Muster. Beginnend mit dem zuletzt gezeichneten Punkt (den ich als A bezeichne) gehe ich zum nächsten gezeichneten Punkt (B) auf der Linie (nach Bedarf umlaufend). Dann gehe ich zum nächsten eingezeichneten Punkt auf der Linie (C). Dann zeichne ich einen neuen Punkt auf halbem Weg zwischen diesem dritten Punkt (C) und dem nächsten bereits gezeichneten Punkt (D).

Immer wenn Sie die Linie umbrechen, wird die "Mitte" in umbrechender Weise bestimmt. Der neu gezeichnete Punkt befindet sich immer rechts von C.

Angenommen, die folgende Zeile war meine aktuelle Zeile. Hier ist, wie ich die nächsten zwei Punkte aufzeichnen würde. In diesem Beispiel beschrifte ich jeden wichtigen Punkt mit einem Buchstaben.

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

Zurück zum vorherigen Beispiel, der nächste Punkt wird in der Mitte der Linie gezeichnet.

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

Dies ist vielleicht ein kleiner Sonderfall: Wenn Sie zum nächsten Punkt voranschreiten, bleiben Sie einfach dort, wo Sie begonnen haben. Der einzig nützliche halbe Punkt ist der "zyklische" halbe Punkt (der halbe Punkt auf der Linie), im Gegensatz dazu, einen Punkt auf sich selbst zu zeichnen.

Unten ist die Reihe von Punkten, die ich von hier bis zum Ende auf der Linie zeichnen würde.

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

Es gibt keinen Platz mehr, um den nächsten Punkt zu zeichnen, da er zwischen zwei benachbarten Punkten eingeklemmt werden müsste, sodass ich die maximale Tiefe für den angegebenen Wert von N = 4 erreicht habe. Die letzte Zeile in der obigen Liste ist "vollständig" . "

Die Herausforderung

Das Ziel ist es, das kürzeste Programm / die kürzeste benannte Funktion zu schreiben, das / die die abgeschlossene Zeile für einen gegebenen Wert von N ausgibt / zurückgibt. Das Obige zeigt N = 4.

Eingang

Die Eingabe ist eine einzelne nicht negative Ganzzahl N. Die Länge der erzeugten Zeile beträgt dann 2 ^ N.

Ausgabe

Die Ausgabe erfolgt in der vollständigen Zeile der Länge 2 ^ N, die aus den Zeichen .und besteht X. Ein abschließender Zeilenumbruch spielt keine Rolle.

Beispiel 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.......
PhiNotPi
quelle

Antworten:

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

Recht einfach.

Pyth, 49

Mehr oder weniger eine Übersetzung. Der Hauptunterschied besteht darin, dass ich keine Liste verwende, die die Linie darstellt, sondern eine Zeichenfolge.

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

Probieren Sie es online aus .

                         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
Jakube
quelle
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}
Ypnypn
quelle
3

GolfScript (61 Bytes)

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

Die Anzahl der erforderlichen Schleifeniterationen scheint A061419 zu sein , aber die do-Schleife ist kürzer als die Berechnung. Ein divmod würde ein Zeichen in der do-Schleife speichern. Der Teil, der sich am verschwenderischsten anfühlt, ist die Ausgabeumwandlung, aber ich sehe keinen Weg, sie zu verbessern.

Peter Taylor
quelle
3

CJam, 55 53 51 50 Bytes

2ri#:N'.*0aN{):U+__Nf++$_U#))>2<1bNe|2/N%|}*{'Xt}/

Zunächst einmal etwas.

Probieren Sie es hier online aus

Optimierer
quelle
2

Java, 209 207 195 191 Bytes

Ich bin überrascht, dass ich es so kurz kriegen konnte. Es gibt wahrscheinlich noch Raum für Verbesserungen. Wie immer sind Vorschläge erwünscht :)

Dies gibt a zurück char[]. Mit anrufen 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;}

Eingerückt:

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 dank Peter :)
4 Bytes dank TNT;)

Die Nummer eins
quelle
(c%b+b)%b? Erwarten Sie c, negativ zu sein?
Peter Taylor
c=0und d=0kann verkürzt werden , um einfach cund d. intAuf Klassenebene definierte Typen werden automatisch auf 0 initialisiert.
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

Verbrauch: f 5. Ausgang: X.X.X...X...X...X.XXX.XXX........

Leider hat Haskell in den Standardbibliotheken keine Merge-Funktion, daher muss ich meine eigene bereitstellen (-> %). Glücklicherweise muss ich nur unendliche Listen zusammenführen, damit ich die Basisfälle, dh leere Listen, nicht abdecken muss. Es kostet immer noch 40 Bytes.

So funktioniert es: Anstatt die Xs direkt in einem Array festzulegen, behalte ich eine Liste der Positionen, an denen sie sich befinden. Außerdem mache ich keinen Umlauf um, 2^Nsondern erhöhe die Positionen immer weiter in Richtung unendlich (z. B. Xsieht die Positionsliste für N = 2 mit einem vorne aus [0,4,8,12,16,20,…]). Ich nehme das 3. und 4. Element ( cund d), berechne die neue Position (c+d)/2, behalte sie für die Ausgabeliste, füge die alte Positionsliste ab Position 4 (die d) mit einer neuen zusammen, beginnend mit (c+d)/2und wiederhole sie. Ich höre auf, wenn es (c+d)/2gleich ist c. Schließlich füge ich 0der Ausgabeliste ein hinzu und drucke Xs an den angegebenen Stellen und an .anderer Stelle.

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 
nimi
quelle
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
Alephalpha
quelle