Pérégrination de premier rang

44

Le but de ce défi est de représenter graphiquement une marche sur le plan, où la direction de chaque étape k est déterminée par la primalité de k et la parité de son développement binaire. Plus précisément,

  • La direction initiale est fixe, disons le nord.
  • Toutes les étapes ont la même longueur .
  • La direction de l’étape k peut être Nord, Ouest, Sud ou Est, et est déterminée comme suit:
    • Si k n'est pas premier, la direction ne change pas.
    • Si k est premier et que l'expansion binaire de k a un nombre pair, tournez à droite.
    • Si k est premier et que l'expansion binaire de k a un nombre impair de 1, tournez à gauche.

En tant qu'exemple travaillé , supposons que la direction initiale est le nord. Les premières étapes sont:

  • k=1 n'est pas premier. Nous faisons donc un pas dans la direction actuelle, qui est le nord.
  • k=2 est premier et son développement binaire10, a et un nombre impair de uns. Alors on tourne à gauche et on fait maintenant face à l'ouest. Nous faisons un pas dans cette direction.
  • k=3 est premier et son développement binaire11, a et même nombre d'unités. Nous tournons donc à droite et faisons maintenant face au nord. Nous faisons un pas dans cette direction.
  • k=4 n'est pas premier. Nous faisons donc un pas dans la direction actuelle, qui est le nord.

Le défi

Entrée : nombre entier positif N .

Sortie : tracé de la marche en N étapes telle que définie ci-dessus.

Règles supplémentaires

  • La direction initiale peut être choisie librement (pas nécessairement du Nord), mais devrait être le même pour tous N .
  • La règle de retournement peut être l'inverse de celle décrite ci-dessus, c'est-à-dire tourner à droite pour une parité impair et à gauche pour un niveau pair; mais il doit être le même pour tous N .
  • La sortie doit être une représentation graphique de la promenade. Par exemple:
    • La promenade peut être dessinée avec des segments de ligne.
    • Les points visités peuvent être affichés avec un marqueur, tel qu'un point; avec ou sans connexion de segments de ligne.
    • Une image matricielle à deux couleurs peut être fournie, une couleur correspondant aux points visités et une autre aux non visités.
  • Les échelles des axes horizontal et vertical ne doivent pas nécessairement être identiques. Les étiquettes d'axe et les éléments similaires sont également facultatifs. Tant que la promenade est clairement visible, l'intrigue est valable.
  • Notez que certains points sont visités plus d'une fois. L'intrigue n'est pas sensible à cela. Par exemple, si des segments de ligne sont affichés dans le tracé, chaque segment d'unité est affiché de la même manière quel que soit le nombre de passages parcourus.
  • Le code devrait fonctionner pour toutes les Nressources illimitées. Il est acceptable que, dans la pratique, il échoue pour de grandesN raison de contraintes de temps, de mémoire ou de types de données.
  • L'entrée et la sortie sont flexibles comme d'habitude. En particulier, l’un quelconque des moyens standard de sortie d'images peut être utilisé.
  • Le code le plus court en octets gagne.

Cas de test

Les placettes suivantes utilisent le nord comme direction initiale; même la parité tourne à droite; et la promenade est représentée avec des segments de ligne.

N = 7:

entrez la description de l'image ici

N = 3000:

entrez la description de l'image ici

N = 20000:

entrez la description de l'image ici

N = 159000:

entrez la description de l'image ici

N = 1200000:

entrez la description de l'image ici

N = 11000000:

entrez la description de l'image ici

Luis Mendo
la source
1
Y at-il une raison seulement [graphical-output]est autorisée? Une raison en particulier de rejeter la sortie ASCII, comme ma réponse Charcoal maintenant supprimée?
Kevin Cruijssen le
2
@ Kevin on m'a conseillé une fois de ne pas mélanger les deux dans le même défi ... Qu'en pensent les autres?
Luis Mendo le
1
Eh bien, je peux comprendre le raisonnement qui sous-tend ce conseil, car la sortie sous forme d'image / graphique ou d'art ASCII est complètement différente dans certaines langues. Encore une fois, j’ai vu les sorties de graphiques obtenir de nombreuses votes positifs dans les défis de l’art ASCII et vice-versa, donc je suppose que tout le monde n’est pas d’accord. Personnellement, je pense que cela dépend vraiment du défi. Dans ce cas, personnellement, je ne vois pas de mal à autoriser les deux dans le même défi, mais je suis peut-être partial en raison de ma réponse maintenant supprimée. Je vais donc poser la même question que vous: " Que pensent les autres? " @Arnauld Peut-être devriez-vous poster votre chauffeur de taxi ASCII après tout;)
Kevin Cruijssen le
1
Il serait intéressant de voir cette séquence s'exécuter sur différentes séquences OEIS (en réalité, certains marcheraient en ligne droite ou tourneraient en rond, mais d'autres pourraient être vraiment quelque chose).
Draco18s le
16
À N = 11000000, il semble se rapprocher de la carte de l’Europe.
Digital Trauma

Réponses:

12

Sledgehammer 0.4 , 22 20 octets

⢂⡐⠥⡄⠡⢒⣩⣀⣼⡝⢄⡎⣛⠅⡉⣱⡆⢀⡠⣽

Décompresse dans cette fonction Wolfram Language:

ListPlot[AnglePath[Array[If[PrimeQ@#, ArcSin[(-1)^ThueMorse@#], 0] &, #]]]

Ungolfed

Nous définissons d’abord une fonction qui renvoie l’angle de rotation à chaque étape:

If[PrimeQ[#],
    ArcSin[(-1)^ThueMorse@#],
    0
]&

ThueMorseest la parité de la somme des chiffres binaires. Nous utilisons -1^(...)plutôt que 2*...-1pour une raison un peu compliquée: Wolfram Language convertit automatiquement les expressions arithmétiques de la source en une forme canonique; les expressions comme celles-ci 2/xsont donc stockées sous Times[2, Power[x, -1]]. Cela rend la fréquence Powertrès élevée, et donc la compression très bon marché.

(La multiplication par Boole@PrimeQ@est légèrement plus longue et la Booleconversion implicite des booléens n'avait pas encore été implémentée au moment du challenge.)

À partir de là, Mathematica AnglePathet ListPlotfaisons exactement ce dont nous avons besoin:

ListPlot[AnglePath[Array[%, #]]]&

Dans l'application interactive, la sortie est un objet graphique vectoriel redimensionnable.

entrez la description de l'image ici

lirtosiast
la source
Cool! Je suis descendu à 77 octets en combinant nos solutions. À votre santé!
Roman le
14

MATL , 25 24 21 octets

Q:qJyZpbB!sEq*^YpYsXG

Essayez-le sur MATL en ligne

Merci @LuisMendo pour une belle session de golf en chat qui a finalement conduit à cette version de 21 octets, en suggérant Eq*^

Explication

Q:q % Push 0:n
J   % Push 1i for later use.
y   % Duplicate 0:n from below
Zp  % Vector result of isprime()
b   % Bubble 0:n from bottom of stack
B!s % Sum of bits in binary representation
Eq  % Double minus one to get an odd number
*   % Multiply by isprime result to get either zero or aforementioned odd number
^   % Exponentiate 1i by an odd number or zero to get -i, 1 or i (corresponding to left turn, straight ahead, right turn).
Yp  % Cumulative product to get a vector of directions
Ys  % Cumulative sum to get vector of positions
XG  % Plot

k=12345entrez la description de l'image ici

Sanchises
la source
8

C (gcc) , 179 octets

o;i;d;k;h;f(n,p)char*p;{h=2*n+1;memset(p,0,h*h);p+=h--*n+n;*p=1;for(d=k=0;k++<n;){for(i=1;k%++i%k;);for(o=k;o/2;o=o/2^o&1);i==k?d+=o*2+3:0;p+=(d%2*h+1)*((d&2)-1);*p=1;}return++h;}

Essayez-le en ligne!

4n2+4n+101

C (gcc) , 219 octets

o;i;d;k;h;f(n,p)char*p;{h=2*n+1;p+=sprintf(p,"P1 %d %d ",h,h);memset(p,48,h*h);k=h--*n+n;*(p+2*k+1)=0;p+=k;*p=49;for(d=k=0;k++<n;){for(i=1;k%++i%k;);for(o=k;o/2;o=o/2^o&1);i==k?d+=o*2+3:0;p+=(d%2*h+1)*((d&2)-1);*p=49;}}

Essayez-le en ligne!

4n2+4n+2×log10(2n+1)+9

Production recadrée pour 20000:

recadré pour 20000

Les deux versions commencent par l'ouest et tournent à droite sur impair, gauche sur pair.

J'ai essayé les tests plus grands sans aucun d'entre eux, car la sortie avec 20000 était d'environ 1,5 Go, et 150000 aurait été d'environ 90 Go. Tout cela est stocké en mémoire pendant l'exécution du programme.

Explication de la supérieure:

o;         /* Temporary variable for calculating parity */
i;         /* Temporary variable for primality test */
d;         /* d % 4 = direction */
k;         /* Step */
h;         /* height/width of image */
f(n,p)char*p;{ /* Function taking int and char pointer */
  h=2*n+1;     /* Image sidelength = 2 * N + 1, so N in each direction */
  memset(p,0,h*h); /* Reset buffer */
  p+=h--*n+n;  /* Position p at image center; decrement h */
  *p=1;        /* Put a dot at center */
  for(d=k=0;   /* Set direction and step to 0 */
    k++<n;){   /* Loop over [1..N] */
    for(i=1;k%++i%k;); /* Primality test */
    for(o=k;o/2;o=o/2^o&1); /* Parity test */
    i==k?d+=o*2+3:0; /* Change direction if necessary */
    p+=(d%2*h+1)*((d&2)-1); /* Move according to direction */
    *p=1; /* Set pixel to black */
  }
  return++h; /* Add 1 back to h and return */
}
wastl
la source
1
Je ne pense pas qu’il soit permis d’exiger qu’un tampon alloué soit fourni sous forme d’argument - pour chaque méta-règle , toute entrée supplémentaire doit être vide (ce que j’interpréterais comme signifiant 0ou comme pointeur nul dans le cas de C).
Bouton de porte
3
J'interprète cela comme une affirmation que je peux m'attendre à ce qu'il soit attribué. C'est également un modèle utilisé dans de nombreuses fonctions de bibliothèque standard, telles que sprintf.
wastl
Ah ok, tu as raison, ça a du sens.
Poignée de porte
162 octets
ceilingcat le
8

Wolfram Language (Mathematica) , 98 96 91 77 76 63 octets

ListPlot@AnglePath@Array[Pi/2If[PrimeQ@#,2ThueMorse@#-1,0]&,#]&

-14 octets: Merci à @lirtosiast de m'avoir montré comment utiliserAnglePath ...

-13 octets: ... et ThueMorse!

exemple d'utilisation:

%[20000]

entrez la description de l'image ici

Explication pas à pas:

  • If[PrimeQ@#, 2 ThueMorse@# - 1, 0] &est une fonction qui prend l'index de pas et renvoie 0 pour les nombres non premiers, -1 pour les nombres pairs-binaires et +1 pour les nombres premiers impairs-binaires. ThueMorse@#remplace la solution précédente Total[#~IntegerDigits~2](qui est la même, modulo 2).

  • Array[Pi/2*%,#]dresse une liste de cette fonction avec l'index allant de 1 à l'argument de la fonction (20000 dans l'exemple), et multiplie chaque élément par π / 2 pour en faire un angle de changement de direction (radians). Nous avons maintenant 0 pour les nombres non premiers, -π / 2 pour les nombres premiers pairs, et + π / 2 pour les nombres premiers impairs.

  • AnglePath[%]convertit cette liste d'angles de changement de direction en une trajectoire. Cette instruction remplace la double utilisation de la solution précédente Accumulate.

  • ListPlot[%]convertit la liste des positions en un tracé de points XY. Si vous préférez une ligne, utilisez ListLinePlotplutôt. Ces fonctions de tracé offrent de nombreuses options pour améliorer l'apparence des parcelles.

romain
la source
1
Merci @lirtosiast! C'est comme apprendre une langue étrangère: du nouveau vocabulaire chaque jour.
Romain
7

MATL, 31 30 28 26 octets

J4:^0i:Zpl_G:B!s^*hYs)YsXG

3 octets sauvés grâce à @LuisMendo

2 octets sauvés grâce à @Sanchises

Essayez-le sur MATL Online

Explication

Cette solution utilise des nombres complexes pour représenter les composantes X et Y du plan 2D.

J      % Push the literal complex number 0 + 1j to the stack
4:     % Create the array [1, 2, 3, 4]
^      % Raise 0 + 1j to each power in the array, [1, 2, 3, 4]

À ce stade, nous avons quatre points ( (0, 1), (-1, 0), (0, -1), (1, 0)) dans un tableau représenté par des nombres complexes. Ce sont les quatre directions cardinales. Maintenant, nous voulons utiliser ceux-ci pour "marcher".

La façon dont cela fonctionne est que nous commençons par aller dans la zéroième direction (le 0ème élément du tableau qui est (-1, 0)). Pour chaque étape, nous devons déterminer le changement dans cette rubrique. Nous allons utiliser des entiers pour suivre ce changement. Si nous voulons tourner "à droite", nous incrémentons cet entier de 1 (référençant l' élément suivant dans le tableau à 4 points) et si nous voulons "gauche", nous décrémentons cet entier de 1 (référençant l' élément précédent dans la Tableau à 4 points). Si nous voulons continuer sur notre chemin, nous gardons la valeur entière constante (référençant le même élément dans le tableau à 4 points).

Cette partie du code crée un tableau de tous ceux 0, -1et les 1valeurs.

0      % Push a literal 0 to the stack (the starting point)
i      % Explicitly grab the input (N)
:      % Create an array from 1...N
Zp     % Determine if each element is a prime (1) or not (0)
l_     % Push the literal -1 to the stack
G      % Explicitly grab the input again (N)
:      % Create an array from 1...N
B      % Convert to binary representation (each row is the binary representation of
       % each element in the vector)
!      % Transpose
s      % Sum down the columns to count number of 1's
^      % Raise the -1 to each element. For odd number of 1's in the
       % binary expansion this yields -1, and even yields 1

*      % Multiply this -1 or 1 by the result of the prime check (element-wise). 
       % For non-primes this yields a 0, for primes with an even number of 1's in 
       % the binary representation this is a 1, and for primes 
       % with an odd number of 1's in

h      % Horizontally concatenate with the initial 0

Nous avons maintenant un tableau des différences entre les entiers successifs afin que nous puissions calculer la somme cumulative de ceux-ci pour obtenir les indices que nous pouvons ensuite utiliser pour rechercher la direction à chaque étape dans le tableau à 4 éléments d'origine.

De manière pratique, MATL a une indexation en 5boucle qui permet d’indexer au début d’un tableau à 4 éléments. Nous pouvons utiliser ceci à notre avantage pour pouvoir incrémenter et décrémenter cet entier sans nous soucier du fait que le tableau de direction de référence ne comporte que 4 éléments.

Ys     % Compute the cumulative sum
)      % Use this to modularly index into the original array of four points

Nous avons maintenant un tableau de directions des étapes à suivre, nous pouvons donc calculer la somme cumulée de ces directions pour tracer le chemin qui a été emprunté.

Ys     % Compute the cumulative sum
XG     % Plot as a 2D plot
Suever
la source
5

Perl 6 , 213 182 octets

{mon @p = [\ +] [\ *] ({{. is-prime ??. base (2) .comb (~ 1)% 2 ?? i !! - i !! 1 + 0i} (+ + $)} ... *) [^ $ _]; {"<svg viewBox = '{. min xx 2, .elems xx 2}' >>. & {" L {.re} {.im} " }} 'fill =' none 'stroke =' black '/> "} (minmax | @p» .reals)}

{{"<svg viewBox='{{.min,.min,+$_,+$_}(.minmax)}'><path d='{"L"X~$_}' fill='none' stroke='red'/></svg>"}(([\+] [\*]({-{.is-prime*.base(2).comb(~1)R**-1||i}(++$)i}...*)[^$_])».reals)}

Essayez-le en ligne!

(Vraiment réussi à réduire celui-ci!)

Cette fonction est générée au format SVG.

  • { -{ .is-prime * .base(2).comb(~1) R** -1 || i }(++$)i } ... *est une suite infinie de changements de direction pour chaque étape, sous la forme de nombres complexes, où 1signifie «continue dans la même direction», isignifie «tourne à gauche» et -isignifie «tourne à droite».
  • [^$_] limite cette séquence au nombre d'étapes fourni comme argument de la fonction.
  • [\*] analyse cette séquence avec une multiplication (complexe) en transformant la liste des changements de direction relatifs en une liste de directions absolues.
  • [\+]scanne cette séquence avec addition (complexe), produisant une liste des coordonnées visitées.
  • ».reals convertit cette liste de nombres complexes en listes à deux éléments de ses parties réelle et imaginaire.

L'image SVG n'est qu'un pathélément.

Sortie (convertie en PNG) pour N = 20000:

chemin pour N = 20000

Sean
la source
4

C, 321 octets

a,b,A,B,k,p,e,i,t,r;g(n,c,d,x,y,X,Y){x=y=Y=r=0;X=1;for(k=0;k++<=n;){r|=x==c&y==d;a=x<a?x:a;A=x>A?x:A;b=y<b?y:b;B=y>B?y:B;for(p=1,i=k;--i;p=p*i*i%k);for(e=1,i=k;i;e=-e)i&=i-1;if(p)t=X,X=-e*Y,Y=e*t;x+=X;y+=Y;}}f(n,x,y){A=a=B=b=0;g(n);printf("P1%d %d ",A-a+1,B-b+1);for(y=b;y<=B;++y)for(x=a;x<=A;++x)g(n,x,y),putchar(48+r);}

Essayez-le en ligne!

J'ai commencé à travailler dessus avant que l'autre réponse C ne soit publiée, mais je me suis dit que je pourrais aussi bien poster la mienne de toute façon. Celui-ci est beaucoup plus long, mais il recadre automatiquement l'image de sortie aux dimensions du résultat.

La fonction est appelée en tant que f(n)et la sortie est stdout au format netpbm.

Exemple de sortie pour n = 1000:

a,b,A,B,          // used to store x range [a,A] and y range [b,B]
k,p,e,i,t,        // temp variables used in g
r;g(n,c,d,        // takes n + coordinates, sets r to whether (c,d) is visited
x,y,X,Y){         // temp variables - position (x,y) and velocity (X,Y)
x=y=Y=r=0;X=1;    // initialization
for(k=0;k++<=n;){ // loops k over the step number
r|=x==c&y==d;     // set r to 1 if current coordinate is the requested one
a=x<a?x:a;A=x>A?x:A;b=y<b?y:b;B=y>B?y:B;    // update bounds
for(p=1,i=k;--i;p=p*i*i%k);                 // prime test
for(e=1,i=k;i;e=-e)i&=i-1;                  // parity test
if(p)t=X,X=-e*Y,Y=e*t;                      // if prime, turn accordingly
x+=X;y+=Y;}}      // move position in direction of velocity
f(n,x,y){         // main function; x and y are temp variables
A=a=B=b=0;g(n);   // obtain accurate bounds
printf("P1 %d %d\n",A-a+1,B-b+1);           // output netpbm header
for(y=b;y<=B;++y)for(x=a;x<=A;++x)          // loop through all coordinates
g(n,x,y),putchar(48+r);}                    // output 1 if visited, 0 otherwise

Le test principal est essentiellement celui utilisé dans la réponse de Lynn à un défi différent , qui repose sur le théorème de Wilson .

Le test de parité utilise une adaptation de la méthode de comptage de bits de Kernighan .

Étant donné que le test principal est très lent et que l'algorithme ré-exécute la fonction de génération de chemin d'accès complète pour chaque pixel dessiné, toute entrée est supérieure à 1 000 fois sur TIO.

Poignée de porte
la source
308 octets
ceilingcat
4

LOGO, 177 171 octets

to d:c
if :c%2[rt 180
make"c:c-1]if:c<1[stop]d:c/2
end
to p
if:c>1[make"f 2
repeat:c-2[if:c%:f<1[stop]make"f:f+1]rt 90
d:c]end
to g:n
make"c 1
repeat:n[p
fw 2
make"c:c+1]end

Pour utiliser, faire quelque chose comme ça :

reset
pu
fw 100
pd
g 3000

Désolé, je n'ai pas pu capturer un exemple de sortie. Explication:

to d:c
if :c%2[rt 180
make"c:c-1]if:c<1[stop]d:c/2
end

Il s'agit d'une procédure récursive qui fait pivoter de 180 ° pour chaque bit défini dans son paramètre, ce qui calcule efficacement la parité de son développement binaire.

to p
if:c>1[make"f 2
repeat:c-2[if:c%:f<1[stop]make"f:f+1]rt 90
d:c]end

C'est un test de primalité très basique. Après la casse spéciale 1, la procédure est rétablie si un facteur est trouvé. Si, toutefois, la valeur actuelle est jugée supérieure, il tourne à droite et utilise ensuite la procédure ci-dessus pour la changer en virage à gauche, selon le cas.

to g:n
make"c 1
repeat:n[p
fw 2
make"c:c+1]end

Il ne s’agit que d’une simple boucle permettant de tester tous les nombres jusqu’à la nprimalité et de déplacer deux pixels après chacun.

Neil
la source
4

Gelée , 41 octets

B§ḂḤ’×ıµ1Ẓ?€×\ÄŻÆiZ_Ṃ$€Z‘ḞŒṬµẈḢ⁾P1,;Lṭ@FK

Essayez-le en ligne!

N

N=3000

Sortie pour N = 3000

N=300

0000000000000000000000111110000000000
0000000000000000000000100010000000000
0000001110000000000000100010000000000
0000001010000000000000100010000000000
0000001010000000000000100010000000000
0000001010000000000000100010000000000
0000001010000000111111111010000000000
0000001010000000100000101010000000000
0000001111111110100000101010000000000
0000000000100010100000101010000000000
0000000000111111100000101010001111111
0000000000000010000000101010001000001
0000000000000011100010101010001000001
0000000000000000100010101010001000001
0000111111100000100011111111111111111
0100100000100000100010001010001000001
0110100000111111100011111111111000111
0010100000000000000010101010000000101
1111100000000000000010101110000000101
1010000000000000000010100000000000101
1010000000000000000011111111111011101
1010000000000000000000100000001010101
1110000000000000000000111111101111101
0000000000000000000000000000100010101
0000000000000000000000000000100010101
0000000000000000000000000000100010101
0000000000000000000000000000111111111
0000000000000000000000000000000010100
0000000000000000000000000000000010100
0000000000000000000000000000000010100
0000000000000000000000000000000011100
Nick Kennedy
la source
4

JavaScript - 675 668 660 632 556 534 octets

Première fois ici sur CodeGolf, a commencé avec ~ 1500 octets de code. Il a golfé à moins de la moitié, presque plus du tiers. N'hésitez pas à continuer à jouer au golf. Octets comptés avec: cet outil

Principe:
Dessine un canevas de taille fixe avec N et une longueur de trait variable en entrée.

Modifications:

-07 octets - suppression des manquants si
-08 octets - remplace le commutateur par if / else
-28 octets - remplace par tenary si / else
-76 octets - test principal plus court (runtime / 3)
-22 octets - utilise cette fonction principale (runtime * 4)

Code de golf:

function f(e,r){for(var t=0,n=0,i=950,f=450,o=document.getElementById("d").getContext("2d"),a=1;a<=e;a++){n=iP(a)?iO(a)?1:2:0;var u=i,c=f;t==0?(t=0==n?(c=f-r,0):1==n?(u=i-r,1):(u=i+r,3)):t==1?(t=0==n?(u=i-r,1):1==n?(c=f+r,2):(c=f-r,0)):t==2?(t=0==n?(c=f+r,2):1==n?(u=i+r,3):(u=i-r,1)):(t=0==n?(u=i+r,3):1==n?(c=f-r,0):(c=f+r,2));o.beginPath(),o.moveTo(i,f),o.lineTo(u,c),o.stroke(),i=u,f=c}}function iP(h){for(i=n=h;n%--i;);return(1==i)}function iO(e){for(var r=(e>>>0).toString(2),t=0,n=0;n<r.length;n++)"1"==r[n]&&t++;return t%2!=0}

Code non golfé avec des espaces blancs:

function f(e,r){
    for(var t=0,n=0,i=950,f=450,o=document.getElementById("d").getContext("2d"),a=1;a<=e;a++){

        // prime and odd/even check
        n=iP(a)?iO(a)?1:2:0;

        var u=i,c=f;

        t==0?(t=0==n?(c=f-r,0):1==n?(u=i-r,1):(u=i+r,3)):t==1?(t=0==n?(u=i-r,1):1==n?(c=f+r,2):(c=f-r,0)):t==2?(t=0==n?(c=f+r,2):1==n?(u=i+r,3):(u=i-r,1)):(t=0==n?(u=i+r,3):1==n?(c=f-r,0):(c=f+r,2));

        o.beginPath(),o.moveTo(i,f),o.lineTo(u,c),o.stroke(),
        i=u,f=c // renew old cords
    }
}

// check prime
function iP(h){
    for(i=n=h;n%--i;);
    return(1==i)
}

// check binary expression even/odd
function iO(e){
    for(var r=(e>>>0).toString(2),t=0,n=0;n<r.length;n++)
        "1"==r[n]&&t++;
    return t%2!=0
}

Exemples:

N = 7 - Longueur = 60

f(7, 60);
function f(e,r){for(var t=0,n=0,i=950,f=450,o=document.getElementById("d").getContext("2d"),a=1;a<=e;a++){n=iP(a)?iO(a)?1:2:0;var u=i,c=f;t==0?(t=0==n?(c=f-r,0):1==n?(u=i-r,1):(u=i+r,3)):t==1?(t=0==n?(u=i-r,1):1==n?(c=f+r,2):(c=f-r,0)):t==2?(t=0==n?(c=f+r,2):1==n?(u=i+r,3):(u=i-r,1)):(t=0==n?(u=i+r,3):1==n?(c=f-r,0):(c=f+r,2));o.beginPath(),o.moveTo(i,f),o.lineTo(u,c),o.stroke(),i=u,f=c}}function iP(h){for(i=n=h;n%--i;);return(1==i)}function iO(e){for(var r=(e>>>0).toString(2),t=0,n=0;n<r.length;n++)"1"==r[n]&&t++;return t%2!=0}
<canvas id="d" width="1900" height="900"/> 

N = 3000 - Longueur = 4

f(3000, 4);
function f(e,r){for(var t=0,n=0,i=950,f=450,o=document.getElementById("d").getContext("2d"),a=1;a<=e;a++){n=iP(a)?iO(a)?1:2:0;var u=i,c=f;t==0?(t=0==n?(c=f-r,0):1==n?(u=i-r,1):(u=i+r,3)):t==1?(t=0==n?(u=i-r,1):1==n?(c=f+r,2):(c=f-r,0)):t==2?(t=0==n?(c=f+r,2):1==n?(u=i+r,3):(u=i-r,1)):(t=0==n?(u=i+r,3):1==n?(c=f-r,0):(c=f+r,2));o.beginPath(),o.moveTo(i,f),o.lineTo(u,c),o.stroke(),i=u,f=c}}function iP(h){for(i=n=h;n%--i;);return(1==i)}function iO(e){for(var r=(e>>>0).toString(2),t=0,n=0;n<r.length;n++)"1"==r[n]&&t++;return t%2!=0}
<canvas id="d" width="1900" height="900"/> 

N = 20000 - Longueur = 2

f(20000, 2);
function f(e,r){for(var t=0,n=0,i=950,f=450,o=document.getElementById("d").getContext("2d"),a=1;a<=e;a++){n=iP(a)?iO(a)?1:2:0;var u=i,c=f;t==0?(t=0==n?(c=f-r,0):1==n?(u=i-r,1):(u=i+r,3)):t==1?(t=0==n?(u=i-r,1):1==n?(c=f+r,2):(c=f-r,0)):t==2?(t=0==n?(c=f+r,2):1==n?(u=i+r,3):(u=i-r,1)):(t=0==n?(u=i+r,3):1==n?(c=f-r,0):(c=f+r,2));o.beginPath(),o.moveTo(i,f),o.lineTo(u,c),o.stroke(),i=u,f=c}}function iP(h){for(i=n=h;n%--i;);return(1==i)}function iO(e){for(var r=(e>>>0).toString(2),t=0,n=0;n<r.length;n++)"1"==r[n]&&t++;return t%2!=0}
<canvas id="d" width="1900" height="900"/> 

N = 159000 - Longueur = 1

f(159000, 1);
function f(e,r){for(var t=0,n=0,i=950,f=450,o=document.getElementById("d").getContext("2d"),a=1;a<=e;a++){n=iP(a)?iO(a)?1:2:0;var u=i,c=f;t==0?(t=0==n?(c=f-r,0):1==n?(u=i-r,1):(u=i+r,3)):t==1?(t=0==n?(u=i-r,1):1==n?(c=f+r,2):(c=f-r,0)):t==2?(t=0==n?(c=f+r,2):1==n?(u=i+r,3):(u=i-r,1)):(t=0==n?(u=i+r,3):1==n?(c=f-r,0):(c=f+r,2));o.beginPath(),o.moveTo(i,f),o.lineTo(u,c),o.stroke(),i=u,f=c}}function iP(h){for(i=n=h;n%--i;);return(1==i)}function iO(e){for(var r=(e>>>0).toString(2),t=0,n=0;n<r.length;n++)"1"==r[n]&&t++;return t%2!=0}
<canvas id="d" width="1900" height="900"/> 

pixma140
la source
La couleur dépend de la quantité de lignes qui se chevauchent? Cool!
val
Je n'ai pas changé le style de trait, il devrait s'agir d'un noir par défaut, sans motif ni transparence. Trouvé ici . La raison pour laquelle un changement de couleur est susceptible de se produire peut être liée à la largeur de trait définie dans le deuxième paramètre de ma fonction prenant @val. Désolé de te décevoir peut-être.
pixma140
3

Rouge , 515 480 471 octets

-1 octet grâce à Kevin Cruijssen!

func[n][a: 270 x: t: u: v: w: 0 y: 1
b: copy[line 0x0 0x1]repeat i n - 1[p: on
j: i + 1 repeat k i / 2[if j%(k + 1)= 0[p: off]]if p[s: 0
until[if j% 2 = 1[s: s + 1](j: j / 2)< 1]a: a + pick[-90 90]s% 2 + 1]append b 'line 
append b as-pair x y x: x + cosine a y: y - sine a append b as-pair x y t: min x t
u: max x u v: min y v w: max y w]c: 500 /(max u - t w - v)view[base white 502x500
draw collect[foreach k b[keep either pair? k[as-pair k/1 - t * c k/2 - v * c][k]]]]]

Une partie importante du code (~ 160 octets) traite de la normalisation des coordonnées de sorte que les graphiques s’intègrent entièrement dans la grille, quelle que soit la taille de l’entrée.

Direction initiale: sud.

Voici le résultat pour n = 3000

3000 itérations

n = 20000

20000

Galen Ivanov
la source
1
Par curiosité, pourquoi ne sont pas là des espaces requis pour les modulos à if j%(k + 1)et if j% 2 = 1, mais il y a des espaces nécessaires à la plupart des autres opérateurs ( +, /, etc.). Peut-on également supprimer l’espace au modulo de pick[-90 90]s% 2? En fait, pourquoi n’y at-il pas d’espace requis as-pair k/1 - t * c k/2 - v * cpour le /?
Kevin Cruijssen le
1
@KevinCruijssen Oui, l'espace peut être supprimé pour s% 2, merci! Je ne sais pas pourquoi, mais modulo %est le seul opérateur pour lequel l'espace qui le précède peut être supprimé, s'il est précédé d'un mot (variable). Dans as-pair k/1 - t * c k/2 - v * cles barres obliques /servent un but complètement différent - ils sont paths. kest un pairet k/1est le premier élément (il peut être sélectionné aussi par k/x, ou pick k 1). Les espaces sont nécessaires presque partout, à l'exception des exceptions ()[]{}, car il n'y a pas d'ambiguïté.
Galen Ivanov
@KevinCruijssen La plupart des symboles peuvent être utilisés dans les wordnoms ( Redn'a pas variables, tout est soit une wordvaleur, soit un bloc de syntaxe tel que [...]ou (...)). Ainsi: a*4: 45-> un mot a*4reçoit une valeur 45. %est utilisé comme marqueur du file!type de données et c'est peut-être pourquoi il ne peut pas être utilisé dans les wordnoms mais peut enfreindre les règles pour les autres opérateurs arithmétiques
Galen Ivanov
1
Ah ok, cela a du sens qu’ils /aient un but différent et que les symboles puissent être utilisés sans espaces dans les variables (ou wordsalors qu’ils sont apparemment appelés Red). Merci pour l'explication. :) Et content que je puisse (la plupart du temps accidentellement) enregistrer un octet pour le s% 2. :)
Kevin Cruijssen le
1

Traitement, plus de 140 octets

void f(int N){for(int x,y,i,l,d,k=d=y=x=0;k++<N;d+=i<l?0:Integer.bitCount(k)%2*2-1,d&=3,point(x-=~-d%2,y+=(d-2)%2))for(i=1,l=k;0<l%++i%l;);}

Pourrait ne pas remplir clairement vu

marcher

PrincePolka
la source