ASCII-Kunst des Tages # 2 - Flow Snakes

32

Eine Flow Snake, auch Gosper-Kurve genannt , ist eine fraktale Kurve, deren Größe mit jeder Ordnung / Iteration eines einfachen Prozesses exponentiell zunimmt. Nachfolgend finden Sie Details zum Aufbau und einige Beispiele für verschiedene Bestellungen:

Bestellung 1 Flow Snake :

____
\__ \
__/

Bestellung 2 Flow Snake :

      ____
 ____ \__ \
 \__ \__/ / __
 __/ ____ \ \ \
/ __ \__ \ \/
\ \ \__/ / __
 \/ ____ \/ /
    \__ \__/
    __/

Bestellung 3 Flow Snake :

                 ____
            ____ \__ \
            \__ \__/ / __
            __/ ____ \ \ \    ____
           / __ \__ \ \/ / __ \__ \
      ____ \ \ \__/ / __ \/ / __/ / __
 ____ \__ \ \/ ____ \/ / __/ / __ \ \ \
 \__ \__/ / __ \__ \__/ / __ \ \ \ \/
 __/ ____ \ \ \__/ ____ \ \ \ \/ / __
/ __ \__ \ \/ ____ \__ \ \/ / __ \/ /
\ \ \__/ / __ \__ \__/ / __ \ \ \__/
 \/ ____ \/ / __/ ____ \ \ \ \/ ____
    \__ \__/ / __ \__ \ \/ / __ \__ \
    __/ ____ \ \ \__/ / __ \/ / __/ / __
   / __ \__ \ \/ ____ \/ / __/ / __ \/ /
   \/ / __/ / __ \__ \__/ / __ \/ / __/
   __/ / __ \ \ \__/ ____ \ \ \__/ / __
  / __ \ \ \ \/ ____ \__ \ \/ ____ \/ /
  \ \ \ \/ / __ \__ \__/ / __ \__ \__/
   \/ / __ \/ / __/ ____ \ \ \__/
      \ \ \__/ / __ \__ \ \/
       \/      \ \ \__/ / __
                \/ ____ \/ /
                   \__ \__/
                   __/

Konstruktion

Betrachten Sie die Reihenfolge, in der 1 Flow Snake aus einem Pfad mit 7 Kanten und 8 Scheitelpunkten aufgebaut wird (unten beschriftet. Aus Gründen der Durchführbarkeit vergrößert):

4____5____6
 \         \
 3\____2   7\
       /
0____1/

Jetzt ersetzen Sie bei jeder nächsten Bestellung einfach die Kanten durch eine gedrehte Version dieses Musters der ursprünglichen Bestellung 1. Verwenden Sie die folgenden 3 Regeln, um die Kanten zu ersetzen:

1 Ersetzen Sie eine horizontale Kante durch die ursprüngliche Form wie folgt:

________
\       \
 \____   \
     /
____/

2 Ersetzen Sie eine /Kante ( 12in der obigen Konstruktion) durch die folgende gedrehte Version:

 /
/   ____
\  /   /
 \/   /
     /
____/

3 Ersetzen Sie eine \Kante ( 34und 67höher) durch die folgende gedrehte Version:

 /
/   ____ 
\   \   \
 \   \   \
  \  /
   \/

So sieht beispielsweise die Reihenfolge 2 mit den Eckpunkten aus der Reihenfolge 1 wie folgt aus

            ________
            \       \
  ________   \____   \6
  \       \      /   /
   \____   \5___/   /   ____
       /            \   \   \
  4___/   ________   \   \   \7
 /        \       \   \  /
/   ____   \____   \2  \/
\   \   \      /   /
 \   \   \3___/   /   ____
  \  /            \  /   /
   \/   ________   \/   /
        \       \      /
         \____   \1___/
             /
        0___/

Für eine höhere Ordnung zerlegen Sie jetzt einfach den aktuellen Pegel in Kanten der Längen 1 /, 1 \oder 2 _und wiederholen den Vorgang. Beachten Sie, dass auch nach dem Ersetzen die gemeinsamen Eckpunkte zwischen zwei aufeinanderfolgenden Kanten immer noch übereinstimmen.

Herausforderung

  • Sie müssen eine Funktion eines vollständigen Programms schreiben, das eine einzelne Ganzzahl Nüber das Argument STDIN / ARGV / function oder das nächste Äquivalent empfängt und die Reihenfolge NFlow Snake auf STDOUT ausgibt.
  • Die eingegebene Ganzzahl ist immer größer als 0.
  • Es sollten keine führenden Leerzeichen vorhanden sein, die nicht Teil des Musters sind.
  • Es sollten entweder keine nachgestellten Leerzeichen oder genügend nachgestellte Leerzeichen vorhanden sein, um das Muster aufzufüllen und das minimale Begrenzungsrechteck vollständig auszufüllen.
  • Der Zeilenumbruch ist optional.

Wissenswertes

  • Flow Snakes ist ein Wortspiel von Schneeflocken, das in diesem Muster der Ordnung 2 und höher ähnelt
  • Der Fluss und die Schlangen spielen tatsächlich eine Rolle im Muster, da das Muster aus einem einzelnen Pfad besteht, der durch das Muster fließt.
  • Wenn Sie genau hinschauen, besteht das Muster der Ordnung 2 (und höher) aus Rotationen des Musters der Ordnung 1, die auf dem gemeinsamen Scheitelpunkt der aktuellen und der vorherigen Kante gedreht sind.
  • Es gibt eine Nicht-ASCII-Variante von Flow Snakes, die hier und an mehreren anderen Stellen zu finden ist.

Dies ist also gewinnen Sie den kürzesten Code in Bytes!


Bestenliste

Der erste Beitrag der Serie generiert eine Rangliste.

Um sicherzustellen, dass Ihre Antworten angezeigt werden, beginnen Sie jede Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

# Language Name, N bytes

Wo Nist die Größe Ihres Beitrags? Wenn Sie Ihren Score zu verbessern, Sie können alte Rechnungen in der Überschrift halten, indem man sich durch das Anschlagen. Zum Beispiel:

# Ruby, <s>104</s> <s>101</s> 96 bytes
Optimierer
quelle
Wenn ich das richtig verstehe, werden die Formen 1,2,3 2x vergrößert, sodass die unterste Reihe in 2 aus 4 Unterstrichen bestehen sollte, nicht aus 3.
edc65
@ edc65 Die Formen in den Beispielen haben die perfekte Größe. Wenn Sie über den Konstruktionsteil sprechen, ja, das ist vergrößert und es gibt 3 Unterstriche, so dass die Kantennummer den 4. Platz einnimmt
Optimierer
Es gibt jedoch keine Kantennummern in Form 2 (im Konstruktionsteil ja). Die Unterseite von Form 2 sollte der Unterseite von Form 1 entsprechen.
edc65
@ edc65 Oh, da !. Fest!
Optimierer
3
Ich las den Titel als "Snow Flakes" und bemerkte den eigentlichen Titel erst, als Sie auf den Unterschied aufmerksam machten.
mbomb007

Antworten:

4

CJam, 144 Bytes

0_]0a{{_[0X3Y0_5]f+W@#%~}%}ri*{_[YXW0WW]3/If=WI6%2>#f*.+}fI]2ew{$_0=\1f=~-
"__1a /L \2,"S/=(@\+\~.+}%_2f<_:.e>\:.e<:M.-:)~S*a*\{M.-~3$3$=\tt}/zN*

Neue Zeile hinzugefügt, um das Scrollen zu vermeiden. Probieren Sie es online aus

Das Programm arbeitet in mehreren Schritten:

  1. Das anfängliche Fraktal (Reihenfolge 1) wird als Folge von 7 Winkeln (konzeptionell ein Vielfaches von 60 °) codiert, die die Bewegungsrichtung darstellen
  2. Das Fraktal wird N-mal auf ein horizontales Segment (Fraktal der Ordnung 0) "angewendet", um alle "Bewegungen" in dem Fraktal der Ordnung N zu erzeugen
  3. Ausgehend von [0 0] werden die Bewegungen in eine Folge von Punkten mit [xy] -Koordinaten übersetzt
  4. Jedes Segment (Punktepaar) wird in 1 oder 2 [xyc] -Tripletts umgewandelt, die das Zeichen c bei den Koordinaten x, y darstellen
  5. Das Begrenzungsrechteck wird bestimmt, die Koordinaten werden angepasst und eine Matrix von Räumen wird erzeugt
  6. Für jedes Triplett wird das Zeichen c in der Matrix an die Positionen x, y gesetzt und die endgültige Matrix für die Ausgabe angepasst
aditsu
quelle
Diese Antwort ist lang genug, um von der Bytecodierung
Dennis
@Dennis Ich bin mir nicht sicher, ob ich mit dem Golfen fertig bin ... und warum hast du es in einen Block gesteckt?
Aditsu
Ich bin mir nicht sicher ... Ihre Antwort ist ziemlich beeindruckend. Ich habe einen ganzen Tag damit verbracht, dies richtig zu machen.
Dennis
@ Tennis Danke; Übrigens, denken Sie, dass es im Allgemeinen in Ordnung ist, nicht druckbare Zeichen / Steuerzeichen zu verwenden? Normalerweise versuche ich, sie zu meiden
am
Wenn ich sie vermeiden kann, ohne die Byteanzahl zu erhöhen, tue ich. Aber kürzer ist kürzer. : P In Fällen wie diesem, in denen ich den Code selbst anstelle eines Strings oder Arrays komprimiere, beziehe ich normalerweise beide Versionen in die Antwort ein.
Dennis
16

Python 2, 428 411 388 Bytes

Dieser war ziemlich knifflig. Die Muster behalten ihre Verhältnisse nach jedem Schritt nicht bei, was bedeutet, dass es sehr schwierig ist, ein Bild von ihrem Vorgänger prozedural zu erzeugen. Was dieser Code macht, obwohl er nach einigem intensiven Mathe-Golfen ziemlich unlesbar ist, ist die rekursiv definierte DFunktion , um die Grenze von Anfang bis Ende zu ziehen .

Die Größe war auch ein Problem, und ich habe gerade erst in der Mitte eines 5*3**nseitlichen Quadrats angefangen und die Dinge danach beschnitten. Wenn ich mir jedoch eine bessere Möglichkeit überlege, die Größe zu berechnen, kann ich sie möglicherweise ändern.

n=input();s=5*3**n
r=[s*[" "]for i in[0]*s]
def D(n,x,y,t=0):
 if n<1:
    x-=t%2<1;y+=t%3>1;r[y][x]='_/\\'[t/2]
    if t<2:r[y][x+2*t-1]='_'
    return[-1,2,0,1,0,1][t]+x,y-(2<t<5)
 for c in[int(i)^t%2for i in"424050035512124224003"[t/2::3]][::(t^1)-t]:x,y=D(n-1,x,y,c)
 return x,y
D(n,s/2,s/2)
S=[''.join(c).rstrip()for c in r]
for l in[c[min(c.find('\\')%s for c in S):]for c in S if c]:print l
KSab
quelle
Wow, das ist großartig. Willst du eine Chance auf AAoD # 1 geben?
Optimierer
r=[s*[" "]for i in range(s)]-> r=[[" "]*s]*s]wird ein paar Bytes rasieren
Sirpercival
1
@sirpercival leider das wird nicht funktionieren , weil , wie *wiederholt veränderbare Objekte .
grc
oh, richtig, ich habe vergessen
Sirpercival
Sie können einige Bytes einsparen, indem Sie ein Inlining einfügen l, print'\n'.join()zum Drucken in einer for-Schleife wechseln , return[...][t]+x,Klammern verwenden und entfernen (t%2). Sie können auch verwenden, min(c.find('\\')%s for c in S)wenn Sie den Namen der Liste ändern, Sdamit der ursprüngliche Wert von nicht überschrieben wird s.
grc
12

JavaScript ( ES6 ), 356 362 370

Das ist eine schwierige Frage ...

Jede Form wird als Pfad gespeichert. Es gibt 6 Grundbausteine ​​(3 + 3 rückwärts)

  • 0diagonal von links oben nach rechts unten ( 4rückwärts)
  • 1diagonal von links unten nach rechts oben ( 5rückwärts)
  • 2horizontal von links nach rechts ( 6rückwärts)

Für jedes gibt es einen Ersetzungsschritt, der angewendet werden muss, wenn die Reihenfolge erhöht wird:

  • 0-> 0645001(rückwärts 4-> 5441024)
  • 1-> 2116501(rückwärts 5-> 5412556)
  • 2-> 2160224(rückwärts 6-> 0664256)

Werte im hArray vorbelegt , auch wenn die Elemente 4..6 mit 0..2 erhalten werden können

;[...h[n]].reverse().map(x=>x^4).join('')

Um die Form für die angegebene Reihenfolge zu erhalten, wird der Pfad in der Variablen p erstellt, wobei die Ersetzungen wiederholt angewendet werden. Dann durchläuft die Hauptschleife die Variable p und zeichnet die Form innerhalb des Arrays g [], wobei jedes Element eine Zeile ist.
Ab Position (0,0) kann jeder Index negativ werden (y-Index bei hohen Ordnungen). Ich vermeide negative y-Indizes, die das gesamte g-Array verschieben, wenn ich einen negativen y-Wert finde. Es ist mir egal, ob der x-Index negativ wird, da in JS negative Indizes zulässig sind, die nur etwas schwieriger zu verwalten sind.
Im letzten Schritt scanne ich das Hauptarray mit .map, aber für jede Zeile muss ich eine explizite for (;;) -Schleife mit der bVariablen verwenden, die den am wenigsten erreichten x-Index enthält (der <0 sein wird).
In demconsole.log Version gibt es eine handliche führende Newline, die leicht zu einer abschließenden Newline gemacht werden kann, die 2 Zeilen vertauscht, wie in der Snippet-Version.

f=o=>{
  g=[],x=y=b=0,
  h='064500192116501921602249954410249541255690664256'.split(9);
  for(p=h[2];--o;)p=p.replace(/./g,c=>h[c]);
  for(t of p)
    z='\\/_'[s=t&3],
    d=s-(s<1),
    t>3&&(x-=d,y+=s<2),
    y<0&&(y++,g=[,...g]),r=g[y]=g[y]||[],
    s?s>1?r[x]=r[x+1]=z:r[x]=z:r[x-1]=z,
    t<3&&(x+=d,y-=s<2),
    x<b?b=x:0;
  g.map(r=>
  {
    o+='\n';
    for(x=b;x<r.length;)o+=r[x++]||' '
  },o='');
  console.log(o)
}

Handliches Snippet zum Testen (in Firefox):

f=o=>{
  g=[],x=y=b=0,
  h='064500192116501921602249954410249541255690664256'.split(9);
  for(p=h[2];--o;)p=p.replace(/./g,c=>h[c]);
  for(t of p)
    z='\\/_'[s=t&3],
    d=s-(s<1),
    t>3&&(x-=d,y+=s<2),
    y<0&&(y++,g=[,...g]),r=g[y]=g[y]||[],
    s?s>1?r[x]=r[x+1]=z:r[x]=z:r[x-1]=z,
    t<3&&(x+=d,y-=s<2),
    x<b?b=x:0;
  g.map(r=>
  {
    for(x=b;x<r.length;)o+=r[x++]||' ';
    o+='\n'
  },o='');
  return o
}

// TEST

fs=9;
O.style.fontSize=fs+'px'

function zoom(d) { 
  d += fs;
  if (d > 1 && d < 40)
    fs=d, O.style.fontSize=d+'px'
}
#O {
  font-size: 9px;
  line-height: 1em;
}
<input id=I value=3><button onclick='O.innerHTML=f(I.value)'>-></button>
<button onclick="zoom(2)">Zoom +</button><button onclick="zoom(-2)">Zoom -</button>
<br>
<pre id=O></pre>

edc65
quelle
6

Haskell, 265 Bytes

(?)=div
(%)=mod
t[a,b]=[3*a+b,2*b-a]
_#[0,0]=0
0#_=3
n#p=[352,6497,2466,-1]!!((n-1)#t[(s+3)?7|s<-p])?(4^p!!0%7)%4
0&_=0
n&p=(n-1)&t p+maximum(abs<$>sum p:p)
n!b=n&[1,-b]
f n=putStr$unlines[["__ \\/   "!!(2*n#t[a?2,-b]+a%2)|a<-[b-n!2+1..b+n!2+0^n?3]]|b<-[-n!0..n!0]]

(Anmerkung: auf GHC vor 7.10, müssen Sie hinzufügen import Control.Applicativeoder ersetzen abs<$>mit map abs$.)

Laufen Sie online auf Ideone.com

f n :: Int -> IO ()nZeichnet den Level- Flowsnake. Die Zeichnung wird nicht entlang der Kurve, sondern in Bitmap-Reihenfolge berechnet, sodass der Algorithmus im O (n) -Raum ausgeführt werden kann (dh logarithmisch in der Zeichnungsgröße). Fast die Hälfte meiner Bytes wird für die Berechnung des zu zeichnenden Rechtecks ​​aufgewendet!

Anders Kaseorg
quelle
Ich habe mich eingeloggt und es funktioniert jetzt! Nett!
Optimierer
Es stellte sich heraus, dass dies zuvor auf Ideone.com nicht funktioniert hat, da ich von 64-Bit Int ausgegangen bin. Behoben (2 Bytes opfern).
Anders Kaseorg
Es ist in Ordnung, da das Login-Ding nur meine E-Mail-ID zur Bestätigung benötigte.
Optimizer
5

Perl, 334 316 309

$_=2;eval's/./(map{($_,"\1"x7^reverse)}2003140,2034225,4351440)[$&]/ge;'x($s=<>);
s/2|3/$&$&/g;$x=$y=3**$s-1;s!.!'$r{'.qw($y--,$x++ ++$y,--$x $y,$x++ $y,--$x
$y--,--$x ++$y,$x++)[$&]."}=$&+1"!eeg;y!1-6!//__\\!,s/^$x//,s/ *$/
/,print for
grep{/^ */;$x&=$&;$'}map{/^/;$x=join'',map$r{$',$_}||$",@f}@f=0..3**$s*2

Parameter der Standardeingabe. Teste mich .

nutki
quelle
5

Haskell, 469 419 390 385 365 Bytes

Die Funktion f :: Int-> IO () nimmt eine ganze Zahl als Eingabe und gibt die Flussschlange aus

e 0=[0,0];e 5=[5,5];e x=[x]
f n=putStr.t$e=<<g n[0]
k=map$(53-).fromEnum
g 0=id
g n=g(n-1).(=<<)(k.(words"5402553 5440124 1334253 2031224 1345110 2003510"!!))
x=s$k"444666555666"
y=s$k"564645554545"
r l=[minimum l..maximum l]
s _[]=[];s w(x:y)=w!!(x+6):map(+w!!x)(s w y)
t w=unlines[["_/\\\\/_ "!!(last$6:[z|(c,d,z)<-zip3(x w)(y w)w,c==i&&d==j])|i<-r.x$w]|j<-r.y$w]
Damien
quelle
Dies ergibt 2 × vergrößerte Figuren. Ich denke, die Frage bezieht sich auf die kleineren Zahlen oben und verwendete nur 2 × vergrößerte Zahlen, um zu erklären, wie die Flussschlange aufgebaut ist.
Anders Kaseorg
Du hast recht. Ich habe es korrigiert
Damien
Sie könnten $bei der Definition von kund zu ersetzen(!!)a mit (a!!)der von einigen Klammern loswerden. Davon abgesehen scheinen Sie viele Tricks selbst zu kennen. Nizza
stolzer Haskeller
4

C, 479 474 468 427 Bytes

Ich schätze, es gibt keinen Sieg gegen die Perl- und Haskell-Typen, aber da hier noch kein C-Ergebnis vorliegt:

#define C char
C *q="053400121154012150223433102343124450553245";X,Y,K,L,M,N,i,c,x,y,o;F(C*p,
int l,C d){if(d){l*=7;C s[l];for(i=0;i<l;i++)s[i]=q[(p[i/7]%8)*7+i%7];return F
(s,l,d-1);}x=0;y=0;o=32;while(l--){c=*p++%8;for(i=!(c%3)+1;i--;) {K=x<K?x:K;L=
y<L?y:L;M=x>M?x:M;N=y>N?y:N;y+=c&&c<3;x-=c%5>1;if(x==X&y==Y)o="_\\/"[c%3];y-=c
>3;x+=c%5<2;}}return X<M?o:10;}main(l){F(q,7,l);for(Y=L;Y<N;Y++)for(X=K;X<=M;X
++)putchar(F(q,7,l));}

Um bei einem atoi () -Aufruf Platz zu sparen, wird die Anzahl der an das Programm übergebenen Argumente für die Ebene verwendet.

Das Programm läuft in O (n ^ 3) oder schlechter; Zuerst wird der Pfad einmal berechnet, um die Min / Max-Koordinaten zu finden, dann wird für jedes (x, y) Paar einmal berechnet, um das Zeichen an diesem bestimmten Ort zu finden. Schrecklich langsam, spart aber Speicherplatz.

Beispiel unter http://codepad.org/ZGc648Xi

Zevv
quelle
Verwenden Sie X,Y,K,L,M,N,i,j,c;anstelle von int X,Y,K,L,M,N,i,j,c;und main(l)anstelle vonvoid main(int l)
Spikatrix
Yeah, danke, ich habe diese bereits rasiert und ein bisschen mehr, ich werde eine neue Version erstellen.
Zevv
Die Ausgabe in der neuesten Version scheint getrimmt zu sein und an den Enden etwas abzulaufen.
Optimierer
Ich habe den falschen Blob hochgeladen, dieser sollte in Ordnung sein.
Zevv,
4

Python 2, 523 502 475 473 467 450 437 Bytes

l=[0]
for _ in l*input():l=sum([map(int,'004545112323312312531204045045050445212331'[t::6])for t in l],[])
p=[]
x=y=q=w=Q=W=0
for t in l:T=t|4==5;c=t in{2,4};C=t<3;q=min(q,x);Q=max(Q,x+C);w=min(w,y);W=max(W,y);a=C*2-1;a*=2-(t%3!=0);b=(1-T&c,-1)[T&1-c];x+=(a,0)[C];y+=(0,b)[c];p+=[(x,y)];x+=(0,a)[C];y+=(b,0)[c]
s=[[' ']*(Q-q)for _ in[0]*(W-w+1)]
for t,(x,y)in zip(l,p):x-=q;s[y-w][x:x+1+(t%3<1)]='_/\_'[t%3::3]
for S in s:print''.join(S)

Pffft hat mich ungefähr 3 Stunden gekostet, aber es hat Spaß gemacht!

Die Idee ist, die Aufgabe in mehrere Schritte aufzuteilen:

  1. Berechnen Sie alle Kanten (als 0-5 codiert) in der Reihenfolge ihres Auftretens (also vom Anfang der Schlange bis zum Ende).
  2. Berechnen Sie die Position für jede der Kanten (und speichern Sie die Min- und Max-Werte für x und y)
  3. Erstellen Sie die Zeichenfolgen, aus denen es besteht (und verwenden Sie die min-Werte zum Versetzen, damit wir keine negativen Indizes erhalten).
  4. Drucken Sie die Zeichenfolgen

Hier ist der Code in ungolfed Form:

# The input
n = int(input())

# The idea:
# Use a series of types (_, /, \, %), and positions (x, y)
# Forwards:   0: __  1: /  2: \
# Backwards:  3: __  4: /  5: \

# The parts
pieces = [
    "0135002",
    "0113451",
    "4221502",
    "5332043",
    "4210443",
    "5324551"
]
# The final types list
types = [0]
for _ in range(n):
    old = types
    types = []
    for t in old:
        types.extend(map(int,pieces[t]))

# Calculate the list of positions (and store the mins and max')
pos = []
top = False
x = 0
y = 0
minX = 0
minY = 0
maxX = 0
maxY = 0
for t in types:
    # Calculate dx
    dx = 1 if t < 3 else -1
    if t%3==0:
        dx *= 2         # If it's an underscore, double the horizontal size
    # Calculate dy
    top = t in {1, 5}
    dy = 0
    if top and t in {0, 3, 1, 5}:
        dy = -1
    if not top and t in {2, 4}:
        dy = 1
    # If backwards, add dx before adding the position to the list
    if t>2:
        x += dx
    # If top to bottom, add dy before adding the position to the list
    if t in {2,4}:
        y += dy
    # Add the current position to the list
    pos += [(x, y)]
    # In the normal cases (going forward and up) modify the x and y after changing the position
    if t<3:
        x += dx
    if t not in {2, 4}:
        y += dy
    # Store the max and min vars
    minX = min(minX, x)
    maxX = max(maxX, x + (t<3)) # For forward chars, add one to the length (we never end with __'s)
    minY = min(minY, y)
    maxY = max(maxY, y)

# Create the string (a grid of charachters)
s = [[' '] * (maxX - minX) for _ in range(maxY - minY + 1)]
for k, (x, y) in enumerate(pos):
    x -= minX
    y -= minY
    t = types[k]
    char = '/'
    if t % 3 == 0:
        char = '__'
    if t % 3 == 2:
        char = '\\'
    s[y][x : x + len(char)] = char

# Print the string
for printString in s:
    print("".join(printString))

Bearbeiten: Ich habe die Sprache in Python 2 geändert, um mit meiner Antwort für # 3 kompatibel zu sein (und es werden auch 6 weitere Bytes gespart).

Matty
quelle
Gute Arbeit; Eine einfache Verbesserung, die Sie vornehmen könnten, wäre die Änderung l.extend(x)zu l+=x. Sie können wahrscheinlich auch codegolf.stackexchange.com/questions/54/… anstelle der von .split()Ihnen verwendeten verwenden (ich habe in meiner Antwort etwas Ähnliches getan)
KSab
@KSab Danke, ich fühle mich jetzt wirklich dumm für die Verwendungextend
Matty
0

Pari / GP, 395

Durchlaufen von x, y Zeichenpositionen und Berechnen des zu druckenden Zeichens. Mäßige Minimierungsversuche, Punkte mit Leerzeichen und Kommentare entfernt.

k=3;
{
  S = quadgen(-12);  \\ sqrt(-3)
  w = (1 + S)/2;     \\ sixth root of unity
  b = 2 + w;         \\ base

  \\ base b low digit position under 2*Re+4*Im mod 7 index
  P = [0, w^2, 1, w, w^4, w^3, w^5];
  \\ rotation state table
  T = 7*[0,0,1,0,0,1,2, 1,2,1,0,1,1,2, 2,2,2,0,0,1,2];
  C = ["_","_",  " ","\\",  "/"," "];

  \\ extents
  X = 2*sum(i=0,k-1, vecmax(real(b^i*P)));
  Y = 2*sum(i=0,k-1, vecmax(imag(b^i*P)));

  for(y = -Y, Y,
     for(x = -X+!!k, X+(k<3),  \\ adjusted when endpoint is X limit
        z = (x- (o = (x+y)%2) - y*S)/2;
        v = vector(k,i,
                   z = (z - P[ d = (2*real(z) + 4*imag(z)) % 7 + 1 ])/b;
                   d);
        print1( C[if(z,3,
                     r = 0;
                     forstep(i=#v,1, -1, r = T[r+v[i]];);
                     r%5 + o + 1)]) );  \\ r=0,7,14 mod 5 is 0,2,4
     print())
}

Jedes Zeichen ist das erste oder zweite einer Sechseckzelle. Ein Zellenort ist eine komplexe Zahl z, die in die Basis b = 2 + w mit den Ziffern 0, 1, w ^ 2, ..., w ^ 5 aufgeteilt ist, wobei w = e ^ (2pi / 6) die sechste Wurzel der Einheit ist. Diese Ziffern werden nur als Unterscheidungsmerkmal 1 bis 7 gespeichert und dann durch eine Zustandstabelle für die Nettorotation von hoch nach niedrig geführt. Dies ist im Stil von Flowsnake-Code von Ed Shouten (xytoi), aber nur für die Nettorotation, keine Ziffern in einen "N" -Index entlang des Pfades setzen. Die Ausdehnungen beziehen sich auf einen Ursprung 0 in der Mitte der Form. Solange das Limit kein Endpunkt ist, handelt es sich um die Mitte eines 2-stelligen Sechsecks und es wird nur 1 dieser Zeichen benötigt. Wenn der Schlangenstart und / oder das Schlangenende die X-Grenze sind, werden 2 Zeichen benötigt, was k = 0 Start und k <3 Ende ist. Pari hat "Quads" wie sqrt (-3) eingebaut, aber das gleiche kann mit Real- und Imaginärteilen getrennt gemacht werden.

Kevin Ryde
quelle
1
Dies entspricht nicht ganz den Regeln für führende und nachfolgende Leerzeichen.
Anders Kaseorg
Danke, habe ich geändert. Dein Hasch hat mich um eine Stunde geschlagen, bis eine XY-Schleife es geschafft hat. Hätte gepostet, bevor ich abwarte, ob weitere Inspiration kommen würde :-).
Kevin Ryde
Jetzt wird ein Ende der Schlange für k = 0, 1, 2 abgeschnitten. (Die Mathematik ist auf diese Weise irritierend - ich musste mich auch damit befassen.)
Anders Kaseorg
Ah mein Lieber, wenn der Endpunkt das x-Maximum ist. Hmm.
Kevin Ryde