Najwyższa peregrynacja parzystości


44

Celem tego wyzwania jest graficzne przedstawienie chodzenia po płaszczyźnie, gdzie kierunek każdego kroku k jest określony przez pierwotność k i parzystość jego binarnej ekspansji. Konkretnie,

  • Początkowy kierunek jest ustalony, powiedzmy na północ.
  • Wszystkie kroki mają tę samą długość .
  • Kierunek z etapu k może być Północna, Zachodnia, Południowa i Wschodnia, a określa się następująco:
    • Jeśli k nie jest liczbą pierwszą, kierunek się nie zmienia.
    • Jeśli k jest liczbą pierwszą, a binarne rozszerzenie k ma parzystą liczbę, skręć w prawo.
    • Jeśli k jest liczbą pierwszą, a binarne rozszerzenie k ma nieparzystą liczbę, skręć w lewo.

Jako działający przykład , załóżmy, że początkowy kierunek to Północ. Pierwsze kroki to:

  • k=1 nie jest liczbą pierwszą. Przesuwamy się więc o jeden krok w obecnym kierunku, czyli na północ.
  • k=2 jest liczbą pierwszą, a jej rozwinięcie binarne10ma liczbę nieparzystą. Skręcamy więc w lewo i jesteśmy teraz zwróceni na Zachód. Przesuwamy się o jeden krok w tym kierunku.
  • k=3 jest liczbą pierwszą, a jej binarne rozszerzenie11ma, a nawet liczbę. Skręcamy więc w prawo i jesteśmy teraz skierowani na północ. Przesuwamy się o jeden krok w tym kierunku.
  • k=4 nie jest liczbą pierwszą. Przesuwamy się więc o jeden krok w obecnym kierunku, czyli na północ.

Wyzwanie

Wejście : dodatnia N .

Wyjście : wykres przejścia N krokowego, jak zdefiniowano powyżej.

Dodatkowe zasady

  • Początkowy kierunek może być dowolnie wybrana (niekoniecznie Północna), lecz powinna być taka sama dla wszystkich N .
  • Reguła toczenia może być odwrotny do opisanego powyżej, to znaczy, skręcić w prawo na nieparzystości i pozostawiona na jeszcze; ale to musi być taka sama dla wszystkich N .
  • Wyjściem musi być graficzne przedstawienie marszu. Na przykład:
    • Spacer można narysować za pomocą segmentów linii.
    • Odwiedzone punkty mogą być oznaczone markerem, takim jak kropka; z segmentami linii łączącej lub bez.
    • Można dostarczyć dwukolorowy obraz rastrowy, z jednym kolorem odpowiadającym odwiedzanym punktom, a drugim dla osób nieodwiedzanych.
  • Skale osi poziomej i pionowej nie muszą być takie same. Również etykiety osi i podobne elementy są opcjonalne. Tak długo, jak spacer można wyraźnie zobaczyć, fabuła jest ważna.
  • Pamiętaj, że niektóre punkty są odwiedzane więcej niż raz. Fabuła nie jest na to wrażliwa. Na przykład, jeśli na wykresie są pokazane segmenty linii, każdy segment jednostki jest wyświetlany tak samo bez względu na to, ile razy został przemierzony.
  • Kod powinien działać dla dowolnych Nnieograniczonych zasobów. Dopuszczalne jest, jeśli w praktyce zawodzi przez długi Nczas z powodu ograniczeń czasowych, pamięciowych lub typu danych.
  • Wejścia i wyjścia są elastyczne jak zwykle. W szczególności można zastosować dowolny ze standardowych sposobów przesyłania obrazów.
  • Najkrótszy kod w bajtach wygrywa.

Przypadki testowe

Poniższe wykresy wykorzystują północ jako kierunek początkowy; nawet parzystość skręca w prawo; i spacer jest przedstawiony za pomocą segmentów linii.

N = 7:

wprowadź opis zdjęcia tutaj

N = 3000:

wprowadź opis zdjęcia tutaj

N = 20000:

wprowadź opis zdjęcia tutaj

N = 159000:

wprowadź opis zdjęcia tutaj

N = 1200000:

wprowadź opis zdjęcia tutaj

N = 11000000:

wprowadź opis zdjęcia tutaj


1
Czy [graphical-output]dozwolony jest tylko powód ? Czy jest jakikolwiek powód, aby odrzucić niedozwolone dane wyjściowe ASCII, takie jak moja teraz usunięta odpowiedź na węgiel drzewny?
Kevin Cruijssen

2
@Kevin Poradzono mi kiedyś, aby nie mieszać obu w tym samym wyzwaniu ... Co myślą inni?
Luis Mendo

1
Cóż, rozumiem uzasadnienie tej rady, ponieważ wynik w postaci obrazu / wykresu w porównaniu z grafiką ASCII jest zupełnie inny w niektórych językach. Z drugiej strony widziałem, że wyniki wykresów są ładowane w głosowaniu w wyzwaniach ASCII i odwrotnie, więc chyba nie wszyscy się z tym zgadzają. Osobiście uważam, że to naprawdę zależy od wyzwania. W tym przypadku osobiście nie widzę żadnej szkody w dopuszczeniu obu w tym samym wyzwaniu, ale być może jestem stronniczy z powodu mojej teraz usuniętej odpowiedzi. Zadam więc to samo pytanie: „ Co myślą inni? ” @Arnauld Może jednak powinieneś opublikować ASCII Taxi Driver;)
Kevin Cruijssen

1
Byłoby interesujące zobaczyć ten przebieg w różnych sekwencjach OEIS (to prawda, niektóre po prostu chodzą po linii prostej lub biegają w kółko, ale niektóre mogą być czymś zupełnie innym).
Draco18s

16
Przy N = 11000000 wydaje się zbliżać do mapy Europy.
Digital Trauma

Odpowiedzi:


12

Młot 0.4 , 22 20 bajtów

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

Dekompresuje się do tej funkcji języka Wolfram:

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

Nie golfił

Najpierw definiujemy funkcję, która zwraca kąt obrotu na każdym kroku:

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

ThueMorsejest parzystością sumy cyfr binarnych. Używamy -1^(...)raczej niż 2*...-1z nieco skomplikowanego powodu: Język Wolfram automatycznie konwertuje wyrażenia arytmetyczne ze źródła na postać kanoniczną, więc wyrażenia podobne 2/xsą przechowywane jako Times[2, Power[x, -1]]. To sprawia, że ​​częstotliwość jest Powerbardzo wysoka, a zatem kompresja jest bardzo tania.

(Mnożenie przez Boole@PrimeQ@jest nieco dłuższe, a niejawne Boolerzucanie booleanów nie było zaimplementowane w momencie wyzwania).

Odtąd matematyka AnglePathi ListPlotrób dokładnie to, czego potrzebujemy:

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

W aplikacji interaktywnej dane wyjściowe to skalowalny obiekt wektorowy.

wprowadź opis zdjęcia tutaj


Chłodny! Połączyłem nasze rozwiązania z 77 bajtami. Twoje zdrowie!
Roman

14

MATL , 25 24 21 bajtów

Q:qJyZpbB!sEq*^YpYsXG

Wypróbuj w MATL online

Dzięki @LuisMendo za fajną sesję golfa na czacie, która ostatecznie doprowadziła do tej 21-bajtowej wersji, sugerując Eq*^

Wyjaśnienie

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=12345wprowadź opis zdjęcia tutaj


8

C (gcc) , 179 bajtów

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

Wypróbuj online!

4n2+4n+101

C (gcc) , 219 bajtów

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

Wypróbuj online!

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

Przycięta moc wyjściowa dla 20000:

przycięte wyjście dla 20000

Obie wersje zaczynają się od zachodu i skręcają w prawo na kursie nieparzystym, w lewo na parzystym.

Wypróbowałem większe przypadki testowe z żadnym z nich, ponieważ dane wyjściowe z 20000 wyniosły ~ 1,5 GB, a 150000 to ~ 90 GB. Wszystko to jest przechowywane w pamięci podczas wykonywania programu.

Wyjaśnienie górnej:

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 */
}

1
Nie sądzę, aby wymaganie podania przydzielonego bufora było dozwolone jako argument - dla każdej meta polityki wszelkie dodatkowe dane wejściowe muszą być puste (co interpretowałbym jako 0wskaźnik zerowy w przypadku C).
Klamka

3
Interpretuję to jako powiedzenie, że mogę oczekiwać, że zostanie przydzielone. Jest to również wzorzec używany w wielu standardowych funkcjach biblioteki, takich jak sprintf.
wastl

Ach, dobrze, masz rację, to ma sens.
Klamka


8

Wolfram Language (Mathematica) , 98 96 91 77 76 63 bajtów

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

-14 bajtów: Dzięki @lirtosiast za pokazanie mi, jak używaćAnglePath ...

-13 bajtów: ... i ThueMorse!

przykład użycia:

%[20000]

wprowadź opis zdjęcia tutaj

Wyjaśnienie krok po kroku:

  • If[PrimeQ@#, 2 ThueMorse@# - 1, 0] &jest funkcją, która pobiera indeks kroku i zwraca 0 dla liczb niepierwszych, -1 dla liczb parzystych binarnych i +1 dla liczb nieparzystych. ThueMorse@#zastępuje poprzednie rozwiązanie Total[#~IntegerDigits~2](które jest takie samo, modulo 2).

  • Array[Pi/2*%,#]tworzy listę tej funkcji z indeksem od 1 do argumentu funkcji (20000 w przykładzie) i mnoży każdy element przez π / 2, aby uzyskać kąt zmiany kierunku (w radianach). Mamy teraz 0 dla liczb pierwszych nieparzystych, -π / 2 dla liczb parzystych binarnych i + π / 2 dla liczb nieparzystych binarnych.

  • AnglePath[%]konwertuje tę listę kątów zmiany kierunku na ścieżkę. Ta instrukcja zastępuje podwójne użycie poprzedniego rozwiązania Accumulate.

  • ListPlot[%]konwertuje listę pozycji na wykres kropkowy XY. Jeśli preferowana jest linia, użyj ListLinePlotzamiast niej. Te funkcje drukowania mają wiele opcji, dzięki którym wykresy wyglądają lepiej.


1
Dzięki @lirtosiast! To jak nauka języka obcego: nowe słownictwo każdego dnia.
Roman

7

MATL, 31 30 28 26 bajtów

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

3 bajty zapisane dzięki @LuisMendo

2 bajty zapisane dzięki @Sanchises

Wypróbuj w MATL Online

Wyjaśnienie

W tym rozwiązaniu liczby zespolone reprezentują składowe X i Y płaszczyzny 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]

W tym momencie mamy cztery punkty ( (0, 1), (-1, 0), (0, -1), (1, 0)) w tablicy reprezentowanej przez liczby zespolone. Są to cztery główne kierunki. Teraz chcemy ich użyć do „chodzenia”.

Zasadniczo działa to w ten sposób, że zaczynamy zmierzać w kierunku zerowym (0-ty element tablicy, który jest (-1, 0)). Na każdym etapie musimy określić zmianę w tym nagłówku. Użyjemy liczb całkowitych do śledzenia tej zmiany. Jeśli chcemy skręcić w prawo, zwiększamy tę liczbę całkowitą o 1 (odwołując się do następnego elementu w tablicy 4-punktowej), a jeśli chcemy przejść w lewo, zmniejszamy tę liczbę całkowitą o 1 (odwołując się do poprzedniego elementu w Tablica 4-punktowa). Jeśli chcemy kontynuować naszą ścieżkę, utrzymujemy stałą wartość całkowitą (odwołując się do tego samego elementu w tablicy 4-punktowej).

Ta część kodu tworzy tablicę wszystkich tych 0, -1i 1wartości.

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

Teraz mamy tablicę różnic między kolejnymi liczbami całkowitymi, dzięki czemu możemy obliczyć skumulowaną sumę tych wartości, aby uzyskać wskaźniki, których możemy użyć do sprawdzenia kierunku na każdym kroku w oryginalnej 4-elementowej tablicy.

Dogodnie, MATL ma indeksowanie z zawijaniem, tak że indeks 5zawija się do początku 4-elementowej tablicy. Możemy to wykorzystać na naszą korzyść, dzięki czemu możemy zwiększać i zmniejszać tę liczbę całkowitą, nie martwiąc się o to, że tablica kierunków odniesienia zawiera tylko 4 elementy.

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

Teraz mamy tablicę kierunków kroków, dzięki czemu możemy obliczyć skumulowaną sumę tych kierunków, aby wyznaczyć ścieżkę, którą obierzono.

Ys     % Compute the cumulative sum
XG     % Plot as a 2D plot

5

Perl 6 , 213 182 bajtów

{my @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)}

Wypróbuj online!

(Naprawdę udało mi się to obniżyć!)

Ta funkcja wyświetla dane w formacie SVG.

  • { -{ .is-prime * .base(2).comb(~1) R** -1 || i }(++$)i } ... *jest nieskończoną sekwencją zmian kierunku dla każdego kroku, w postaci liczb zespolonych, gdzie 1oznacza „kontynuuj w tym samym kierunku” ioznacza „skręć w lewo” i -i„skręć w prawo”.
  • [^$_] ogranicza tę sekwencję do liczby kroków podanych jako argument funkcji.
  • [\*] skanuje tę sekwencję z (złożonym) mnożeniem, zamieniając listę względnych zmian kierunku w listę bezwzględnych kierunków.
  • [\+]skanuje sekwencję z (złożonym) dodatkiem, tworząc listę odwiedzanych współrzędnych.
  • ».reals konwertuje tę listę liczb zespolonych na dwuelementowe listy jej rzeczywistych i urojonych części.

Obraz SVG to tylko jeden pathelement.

Wyjście (przeliczone na PNG) dla N = 20000:

ścieżka dla N = 20000


4

C, 321 bajtów

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

Wypróbuj online!

Zacząłem nad tym pracować, zanim opublikowano drugą odpowiedź C, ale pomyślałem, że równie dobrze mogę napisać moją. Ten jest znacznie dłuższy, ale automatycznie przycina obraz wyjściowy do wymiarów wyniku.

Funkcja jest wywoływana jako f(n), a wyjściem jest wyjście standardowe w formacie netpbm.

Przykładowe dane wyjściowe dla 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

Test podstawowy jest zasadniczo testem zastosowanym w odpowiedzi Lynn na inne wyzwanie , które opiera się na twierdzeniu Wilsona .

Test parzystości wykorzystuje adaptację metody zliczania bitów Kernighana .

Ponieważ główny test jest bardzo wolny, a algorytm ponownie uruchamia całą funkcję generowania ścieżki dla każdego narysowanego piksela, każde wejście znacznie wyższe niż 1000 razy w TIO.



4

LOGO, 177 171 bajtów

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

Do użytku, coś takiego zrobić to :

reset
pu
fw 100
pd
g 3000

Przepraszam, ale nie byłem w stanie uchwycić próbki wyjściowej. Wyjaśnienie:

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

Jest to procedura rekurencyjna, która obraca się o 180 ° dla każdego ustawionego bitu w swoim parametrze, co skutecznie oblicza parzystość jego binarnej ekspansji.

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 jest bardzo podstawowy test pierwotności. Po specjalnej obudowie 1 procedura wcześnie powraca, jeśli zostanie znaleziony czynnik. Jeśli jednak bieżąca wartość okaże się liczbą pierwszą, skręca w prawo, a następnie stosuje powyższą procedurę, aby zmienić ją odpowiednio na skręt w lewo.

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

Jest to po prostu prosta pętla do przetestowania wszystkich liczb aż do npierwotności i do przesunięcia o dwa piksele po każdym.


4

Galaretka , 41 bajtów

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

Wypróbuj online!

N

N=3000

Wyjście dla 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

4

JavaScript - 675 668 660 632 556 534 bajtów

Po raz pierwszy na CodeGolf, początkowo zaczął od ~ 1500 Bajtów. Grał w golfa do mniej niż połowy prawie więcej niż jednej trzeciej. Kontynuuj grę w golfa. Bajty liczone za pomocą: tego narzędzia

Zasada:
Rysuje na płótno o stałym rozmiarze z N i zmienną długością skoku jako wejściem.

Edycje:

-07 Bytes - usunięcie pominiętego if
-08 Bytes - zmiana przełącznika na if / else
-28 Bytes - zmiana na tenary if / else
-76 Bytes - krótszy test główny (runtime / 3)
-22 Bytes - użyj tej funkcji prime (runtime * 4)

Kod do gry w golfa:

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}

Nieskluczony kod z białymi spacjami:

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
}

Przykłady:

N = 7 - Długość = 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 - Długość = 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 - Długość = 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 - Długość = 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"/> 


Kolor zależy od ilości nakładających się linii? Chłodny!
val

Nie zmieniłem stylu obrysu, powinien to być domyślny czarny kolor bez wzoru lub przezroczystości. Znaleziono tutaj . Dlaczego może się zdarzyć, zmiana koloru może być związana z szerokością obrysu ustawioną w drugim parametrze, który moja funkcja przyjmuje @val. Przepraszam, że cię rozczarowuję.
pixma140

3

Czerwony , 515 480 471 bajtów

-1 bajt dzięki 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]]]]]

Znaczna część kodu (~ 160 bajtów) dotyczy normalizacji współrzędnych, tak aby grafika mieściła się całkowicie w obszarze roboczym, niezależnie od wielkości danych wejściowych.

Początkowy kierunek: południe.

Oto wynik dla n = 3000

3000 iteracji

n = 20000

20000


1
Z ciekawości, dlaczego nie istnieją przestrzenie wymagane dla modulos na if j%(k + 1)a if j% 2 = 1, ale istnieją przestrzenie wymagane dla większości pozostałych operatorów ( +, /, itd.). Czy przestrzeń można również usunąć w module pick[-90 90]s% 2? Właściwie, dlaczego również nie są wymagane jakieś obowiązuje w as-pair k/1 - t * c k/2 - v * cdla /?
Kevin Cruijssen

1
@KevinCruijssen Tak, miejsce można usunąć s% 2, dzięki! Nie wiem dlaczego, ale modulo %jest jedynym operatorem, dla którego spacja przed nim może zostać usunięta, jeśli poprzedza ją słowo (zmienna). W as-pair k/1 - t * c k/2 - v * cukośnikach /służą zupełnie inne cele - są path. kjest a pairi k/1jest pierwszym elementem (można go również wybrać k/x, lub pick k 1). Przestrzenie są potrzebne prawie wszędzie, wyjątki są wokół ()[]{}, ponieważ nie ma dwuznaczności.
Galen Iwanow

@KevinCruijssen Większość symboli może być używanych w wordnazwach ( Rednie ma variables, wszystko jest albo a, wordalbo wartością (lub jakimś blokiem składni, takim jak [...]lub (...)). Więc: a*4: 45-> słowu a*4przypisuje się wartość 45. %jest używane jako znacznik dla file!typu danych i może dlatego nie można go używać w wordnazwach, ale może łamać reguły dla innych operatorów arytmetycznych
Galen Iwanow

1
Ach, ok, to ma sens, że /mają one inny cel, a symbole mogą być używane bez spacji w zmiennych (lub wordsjak się je nazywa na czerwono). Dziękuję za wyjaśnienie. :) I cieszę się, że mogłem (głównie przypadkowo) zapisać bajt dla s% 2. :)
Kevin Cruijssen

1

Przetwarzanie, ponad 140 bajtów

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

Może nie spełnić wyraźnie widoczne

spacerować

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.