Art ASCII du jour # 2 - Flow Snakes

32

Un Flow Snake, également connu sous le nom de courbe de Gosper , est une courbe fractale dont la taille augmente de façon exponentielle à chaque ordre / itération d'un processus simple. Voici les détails de la construction et quelques exemples pour diverses commandes:

Commandez 1 Flow Snake :

____
\__ \
__/

Ordre 2 Flow Snake :

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

Ordre 3 Flow Snake :

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

Construction

Considérez l'ordre 1 Flow Snake à construire d'un chemin contenant 7 arêtes et 8 sommets (étiqueté ci-dessous. Agrandi pour la faisabilité):

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

Maintenant, pour chaque prochaine commande, il vous suffit de remplacer les bords par une version pivotée de ce modèle de commande d'origine 1. Utilisez les 3 règles suivantes pour remplacer les bords:

1 Pour un bord horizontal, remplacez-le par sa forme d'origine tel quel:

________
\       \
 \____   \
     /
____/

2 Pour un /bord ( 12dans la construction ci-dessus), remplacez-le par la version pivotée suivante:

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

3 Pour un \bord ( 34et 67au - dessus), remplacez-le par la version pivotée suivante:

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

Ainsi, par exemple, l'ordre 2 avec des sommets de l'ordre 1 étiqueté ressemblera à

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

Maintenant, pour tout ordre supérieur, vous divisez simplement le niveau actuel en bords de longueurs 1 /, 1 \ou 2 _et répétez le processus. Notez que même après le remplacement, les sommets communs entre deux arêtes consécutives coïncident toujours.

Défi

  • Vous devez écrire une fonction d'un programme complet qui reçoit un seul entier Nvia l'argument STDIN / ARGV / fonction ou l'équivalent le plus proche et imprime l'ordre NFlow Snake sur STDOUT.
  • L'entier d'entrée est toujours supérieur à 0.
  • Il ne doit pas y avoir d'espaces de tête qui ne font pas partie du motif.
  • Il ne doit y avoir aucun espace de fin ou suffisamment d'espaces de fin pour remplir le motif afin de remplir complètement le rectangle de délimitation minimum.
  • Le retour à la ligne est facultatif.

Faits amusants

  • Flow Snakes est un jeu de mots de Snow Flakes, auquel ce modèle ressemble pour l'ordre 2 et au-dessus
  • Le Flow et les serpents jouent en fait un rôle dans le motif car le motif est composé d'un seul chemin qui coule partout.
  • Si vous le remarquez attentivement, le motif d'ordre 2 (et supérieur également) comprend des rotations de motif d'ordre 1 pivotant sur le sommet commun du bord actuel et du bord précédent.
  • Il existe une variante non ASCII de Flow Snakes qui peut être trouvée ici et à plusieurs autres endroits.

C'est le donc le code le plus court en octets gagne!


Classement

Le premier post de la série génère un classement.

Pour vous assurer que vos réponses s'affichent, veuillez commencer chaque réponse par un titre, en utilisant le modèle Markdown suivant:

# Language Name, N bytes

Nest la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores en les effaçant. Par exemple:

# Ruby, <s>104</s> <s>101</s> 96 bytes
Optimiseur
la source
Si je comprends bien, les formes 1, 2, 3 sont agrandies 2x, donc la rangée du bas en 2 devrait être composée de 4 undescores, pas 3.
edc65
@ edc65 Les formes des exemples sont parfaitement dimensionnées. Si vous parlez de la partie Construction, oui, elle est agrandie et il y a 3 traits de soulignement pour que le numéro de bord prenne la place du 4e
Optimizer
Mais il n'y a pas de numéro d'arête dans la forme 2 (dans la partie construction, oui). Le bas de la forme 2 doit être égal au bas de la forme 1.
edc65
@ edc65 Oh, là!. Fixé!
Optimizer
3
J'ai lu le titre "Snow Flakes" et je n'ai même pas remarqué le vrai titre jusqu'à ce que vous attiriez l'attention sur la différence.
mbomb007

Réponses:

4

CJam, 144 octets

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*

Ajout d'une nouvelle ligne pour éviter le défilement. Essayez-le en ligne

Le programme fonctionne en plusieurs étapes:

  1. La fractale initiale (ordre 1) est codée comme une séquence de 7 angles (conceptuellement, multiples de 60 °) représentant la direction du mouvement
  2. La fractale est "appliquée" à un segment horizontal (fractale d'ordre 0) N fois pour générer tous les "mouvements" dans l'ordre fractal N
  3. À partir de [0 0], les mouvements sont traduits en une séquence de points avec des coordonnées [xy]
  4. Chaque segment (paire de points) est converti en 1 ou 2 triplets [xyc], représentant le caractère c aux coordonnées x, y
  5. Le rectangle de délimitation est déterminé, les coordonnées sont ajustées et une matrice d'espaces est générée
  6. Pour chaque triplet, le caractère c est placé à la position x, y dans la matrice et la matrice finale est ajustée pour la sortie
Aditsu
la source
Cette réponse est suffisamment longue pour bénéficier du codage d'octets: goo.gl/D1tMoc
Dennis
@ Dennis Je ne suis pas sûr d'avoir fini de jouer au golf ... et pourquoi l'avez-vous mis dans un bloc?
aditsu
Je ne suis pas vraiment sûr ... Votre réponse est assez impressionnante. J'ai passé une journée entière à essayer de bien faire les choses.
Dennis
@Dennis Thanks; btw, pensez-vous qu'il est généralement correct d'utiliser des caractères non imprimables / de contrôle? J'essaie généralement de les éviter
aditsu
Si je peux les éviter sans augmenter le nombre d'octets, je le fais. Mais plus court est plus court. : P Dans des cas comme celui-ci où je compresse le code lui-même plutôt qu'une chaîne ou un tableau, j'inclus généralement les deux versions dans la réponse.
Dennis
16

Python 2, 428 411 388 octets

Celui-ci était assez délicat. Les motifs ne conservent pas leurs rapports après chaque étape, ce qui signifie qu'il est très difficile de produire une image procédurale à partir de son prédécesseur. Ce que ce code fait, bien qu'il soit assez illisible après un golf mathématique intense, est en fait de tracer la ligne du début à la fin en utilisant la Dfonction définie de manière récursive .

La taille était également un problème, et j'ai fini par commencer au milieu d'un 5*3**ncarré latéral et recadrer les choses par la suite, mais si je peux penser à une meilleure façon de calculer la taille, je pourrais la changer.

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
la source
Wow, c'est génial. Vous voulez donner un coup de feu à AAoD # 1?
Optimizer
r=[s*[" "]for i in range(s)]-> r=[[" "]*s]*s]va raser quelques octets
sirpercival
1
@sirpercival malheureusement, cela ne fonctionnera pas à cause de la *répétition des objets mutables .
grc
oh, c'est vrai, j'ai oublié
sirpercival
Vous pouvez enregistrer certains octets en les insérant l, en basculant print'\n'.join()vers l'impression dans une boucle for, en utilisant return[...][t]+x,et en supprimant les parenthèses (t%2). Vous pouvez également l'utiliser min(c.find('\\')%s for c in S)si vous modifiez le nom de la liste Safin qu'elle n'écrase pas la valeur initiale de s.
grc
12

JavaScript ( ES6 ), 356 362 370

C'est difficile ...

Chaque forme est stockée sous forme de chemin. Il y a 6 blocs de construction de base (3 + 3 en arrière)

  • 0diagonale de gauche à droite en bas ( 4arrière)
  • 1diagonale en bas de gauche à haut à droite (en 5arrière)
  • 2horizontal gauche à droite ( 6arrière)

Pour chacun, il y a une étape de remplacement à appliquer lors de l'augmentation de l'ordre:

  • 0-> 0645001(arrière 4-> 5441024)
  • 1-> 2116501(arrière 5-> 5412556)
  • 2-> 2160224(arrière 6-> 0664256)

valeurs préremplies dans le htableau, même si les éléments 4..6 peuvent être obtenus à partir de 0..2 en utilisant

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

Pour obtenir la forme pour l'ordre donné, le chemin est construit dans la variable p en appliquant les substitutions à plusieurs reprises. Ensuite, la boucle principale itère sur la variable p et trace la forme à l'intérieur du tableau g [], où chaque élément est une ligne.
À partir de la position (0,0), chaque indice peut devenir négatif (indice y à des ordres élevés). J'évite que les indices y négatifs déplacent tout le tableau g chaque fois que je trouve une valeur y négative. Je me fiche que l'indice x devienne négatif, car dans JS, les indices négatifs sont autorisés, juste un peu plus difficiles à gérer.
Dans la dernière étape, j'analyse le tableau principal à l'aide de .map, mais pour chaque ligne, je dois utiliser une boucle explicite pour (;;) en utilisant la bvariable qui contient le moins d'index x atteint (qui sera <0).
dans leconsole.log la version il y a un retour à la ligne de début pratique, qui peut être facilement fait un retour à la ligne de fin en échangeant 2 lignes, comme dans la version d'extrait.

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

Extrait pratique à tester (dans 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
la source
6

Haskell, 265 octets

(?)=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]]

(Remarque: sur GHC avant 7.10, vous devrez ajouter import Control.Applicativeou remplacer abs<$>par map abs$.)

Exécutez en ligne sur Ideone.com

f n :: Int -> IO ()dessine le ncouloir de niveau . Le dessin est calculé dans l'ordre du bitmap plutôt que le long de la courbe, ce qui permet à l'algorithme de s'exécuter dans l'espace O (n) (c'est-à-dire logarithmique dans la taille du dessin). Près de la moitié de mes octets sont consacrés au calcul du rectangle à dessiner!

Anders Kaseorg
la source
Je me suis connecté et cela fonctionne maintenant! Agréable!
Optimizer
Il s'avère que cela ne fonctionnait pas auparavant sur Ideone.com car je supposais que l'Int 64 bits. Corrigé maintenant (sacrifiant 2 octets).
Anders Kaseorg
Ce n'est pas grave car la chose de connexion n'avait besoin que de mon identifiant de messagerie pour confirmation ..
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

Paramètre pris sur l'entrée standard. Testez- moi .

nutki
la source
5

Haskell, 469 419 390 385 365 octets

la fonction f :: Int-> IO () prend un entier en entrée et imprime le serpent de flux

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
la source
Cela produit 2 chiffres agrandis. Je pense que la question consiste à demander des chiffres plus petits en haut et à n'utiliser que des chiffres agrandis 2 × pour expliquer comment le couleuvre est construit.
Anders Kaseorg
Vous avez raison. Je l'ai corrigé
Damien
Vous pouvez utiliser $dans la définition de ket remplacer (!!)apar (a!!)ce qui peut éliminer certaines parenthèses. En dehors de cela, vous semblez connaître beaucoup de trucs par vous-même. Nice
fier haskeller
4

C, 479 474 468 427 octets

Il n'y a pas lieu de battre les gars de Perl et Haskell, je suppose, mais puisqu'il n'y a pas encore de soumission C ici:

#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));}

Pour économiser de l'espace sur un appel atoi (), le nombre d'arguments transmis au programme est utilisé pour le niveau.

Le programme s'exécute en O (n ^ 3) ou pire; le chemin est d'abord calculé une fois pour trouver les coordonnées min / max, puis pour chaque paire (x, y), il est calculé une fois pour trouver le caractère à cet emplacement spécifique. Terriblement lent, mais économise sur l'administration de la mémoire.

Exemple exécuté sur http://codepad.org/ZGc648Xi

Zevv
la source
Utiliser à la X,Y,K,L,M,N,i,j,c;place de int X,Y,K,L,M,N,i,j,c;et main(l)au lieu devoid main(int l)
Spikatrix
Oui, merci, je les ai déjà rasés et un peu plus, je vais mettre en place une nouvelle version.
Zevv
La sortie dans la dernière version semble être coupée et un peu décalée aux extrémités.
Optimizer
J'ai téléchargé le mauvais blob, celui-ci devrait être bien.
Zevv
4

Python 2, 523 502 475 473 467 450 437 octets

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, m'a coûté environ 3 heures, mais c'était amusant à faire!

L'idée est de diviser la tâche en plusieurs étapes:

  1. Calculez tous les bords (codés 0-5) par ordre d'apparition (donc du début du serpent à la fin)
  2. Calculez la position de chacun des bords (et enregistrez les valeurs min et max pour x et y)
  3. Construisez les chaînes qui le composent (et utilisez les valeurs min pour compenser, afin que nous n'obtenions pas d'indices négatifs)
  4. Imprimer les cordes

Voici le code sous forme non golfée:

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

Edit: j'ai changé la langue en python 2, pour être compatible avec ma réponse pour # 3 (et cela économise également 6 octets de plus)

Matty
la source
Bon travail; une simple amélioration que vous pourriez faire serait en train de changer l.extend(x)à l+=x. Vous pouvez aussi probablement utiliser codegolf.stackexchange.com/questions/54/… au lieu de celui que .split()vous utilisez (j'ai fait quelque chose de similaire dans ma réponse)
KSab
@KSab Merci, je me sens vraiment stupide maintenant pour l'utilisationextend
Matty
0

Pari / GP, 395

Faire une boucle sur les positions des caractères x, y et calculer le caractère à imprimer. Tentatives modérées de minimisation, marquées avec des espaces et des commentaires supprimés.

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())
}

Chaque char est le premier ou le second d'une cellule hexagonale. Un emplacement de cellule est un nombre complexe z divisé en base b = 2 + w avec les chiffres 0, 1, w ^ 2, ..., w ^ 5, où w = e ^ (2pi / 6) sixième racine de l'unité. Ces chiffres sont conservés comme un 1 à 7 distinctif, puis pris de haut en bas dans une table d'états pour une rotation nette. C'est dans le style du code flowsnake d'Ed Shouten (xytoi) mais uniquement pour la rotation nette, sans faire des chiffres dans un index "N" le long du chemin. Les étendues sont relatives à une origine 0 au centre de la forme. Tant que la limite n'est pas un point de terminaison, ils sont au milieu d'un hexagone à 2 caractères et un seul de ces caractères est nécessaire. Mais lorsque le début et / ou la fin du serpent sont la limite X, 2 caractères sont nécessaires, qui est k = 0 début et k <3 fin. Pari a des "quads" comme sqrt (-3) intégré mais la même chose peut être faite avec des parties réelles et imaginaires séparément.

Kevin Ryde
la source
1
Cela ne satisfait pas tout à fait les règles concernant les espaces de début et de fin.
Anders Kaseorg
Merci, j'ai modifié. Votre haskell m'a battu d'une heure à une boucle x, y l'a fait. J'aurais dû poster avant d'attendre pour voir si une inspiration supplémentaire viendrait :-).
Kevin Ryde
Maintenant, une fin du serpent est coupée pour k = 0, 1, 2. (Le calcul est irritant de cette façon — je devais aussi y faire face.)
Anders Kaseorg
Ah cher, quand le point final est le maximum x. Hmm.
Kevin Ryde