Перегринація паритету


44

Мета цього виклику - графічно зобразити прогулянку по площині, де напрямок кожного кроку визначається первинністю та паритетом її двійкового розширення. Зокрема,kk

  • Початковий напрямок фіксований, скажімо, на північ.
  • Усі щаблі мають однакову довжину .
  • Напрямок етапу може бути Північ, Захід, Південь і Схід, і визначається наступним чином : k
    • Якщо не є простим, напрямок не змінюється.k
    • Якщо є простим, а двійкове розширення має парне число одиниць, поверніть праворуч.kk
    • Якщо є простим, а двійкове розширення має непарну кількість одиниць, поверніть ліворуч.kk

Як відпрацьований приклад , припустимо, що початковий напрямок - північ. Перші кроки:

  • k=1 не є простим. Тож ми рухаємося на один крок у поточному напрямку, а саме на північ.
  • k=2 є простим, а його двійкове розширення 10має, непарне число одиниць. Тож ми повертаємо ліворуч і зараз звернені на Захід. Ми рухаємось одним кроком у цьому напрямку.
  • k=3 є простим, а його двійкове розширення 11, має і парне число одиниць. Тож ми повертаємо праворуч і зараз звернені на Північ. Ми рухаємось одним кроком у цьому напрямку.
  • k=4 не є простим. Тож ми рухаємося на один крок у поточному напрямку, а саме на північ.

Змагання

Вхідні дані : ціле позитивне число .N

Вихід : графік крокової прогулянки, як визначено вище.N

Додаткові правила

  • Початковий напрямок може бути вільно вибрано (не обов'язково Північ), але повинна бути однаковою для всіх .N
  • Повороту правило може бути протилежне тому , що було описано вище, тобто, повернути праворуч на непарність і вліво для парних; але він повинен бути однаковим для всіх .N
  • На виході має бути графічне зображення ходи. Наприклад:
    • Прогулянку можна намалювати відрізками ліній.
    • Відвідані точки можуть бути показані маркером, наприклад крапкою; з відрізками сполучних ліній або без них.
    • Можна надати двоколірне растрове зображення з одним кольором, що відповідає відвідуваним точкам, а іншим для не відвідуваних.
  • Масштаби горизонтальної та вертикальної осей не повинні бути однаковими. Крім того, мітки осі та подібні елементи необов’язкові. Поки прогулянку добре видно, сюжет дійсний.
  • Зауважте, що деякі пункти відвідуються не раз. Сюжет до цього не чутливий. Наприклад, якщо на графіку показані сегменти рядків, кожен сегмент одиниці відображається однаково, незалежно від того, скільки разів він був пройдений.
  • Код повинен працювати для будь-яких Nнеобмежених ресурсів. Це прийнятно, якщо на практиці це не вдається Nзважаючи на обмеження часу, пам'яті чи типу даних.
  • Введення та вихід гнучкі, як завжди. Зокрема, можна використовувати будь-який із стандартних засобів для виведення зображень.
  • Виграє найкоротший код у байтах.

Тестові справи

Наступні сюжети використовують північ як вихідний напрямок; навіть паритет повертає праворуч; і хода зображена лінійними відрізками.

N = 7:

введіть тут опис зображення

N = 3000:

введіть тут опис зображення

N = 20000:

введіть тут опис зображення

N = 159000:

введіть тут опис зображення

N = 1200000:

введіть тут опис зображення

N = 11000000:

введіть тут опис зображення


1
Чи [graphical-output]дозволена лише причина ? Будь-яка причина, зокрема, заборонити вихід ASCII, як-от моя відповідь на тепер видалену деревне вугілля?
Кевін Кройсейсен

2
@Kevin Мені порадили один раз не змішувати обох в одному виклику ... Що думають інші?
Луїс Мендо

1
Ну, я можу зрозуміти міркування, що стоять за цією порадою, оскільки вихід у вигляді зображень / графіків проти мистецтва ASCII у деяких мовах зовсім інший. Знову ж таки, я бачив, як графічні виходи отримують навантаження в обсягах ASCII art, і навпаки, тому, мабуть, не всі згодні. Особисто я думаю, що це дійсно залежить від виклику. У цьому випадку я особисто не бачу ніякої шкоди в тому, щоб дозволити обом в одному і тому ж виклику, але, можливо, я упереджений через свою видалену відповідь. Тож я запитаю те саме питання, що і ви: « Що думають інші? » @Arnauld Можливо, ви все-таки повинні опублікувати свого водія таксі ASCII;)
Кевін Круїйсен

1
Було б цікаво побачити цей пробіг у різних послідовностях OEIS (правда, деякі просто ходитимуть по прямій чи бігатимуть по колах, а деякі можуть бути зовсім чимось).
Draco18s

16
В N = 11000000, здається, це наближається до карти Європи.
Цифрова травма

Відповіді:


12

Кувалда 0,4 , 22 20 байт

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

Декомпресується у цю функцію мови Wolfram:

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

Безумовно

Спочатку ми визначаємо функцію, яка повертає кут повороту на кожному кроці:

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

ThueMorse- це парність суми двійкових цифр. Ми використовуємо, -1^(...)а не 2*...-1злегка складну причину: мова Wolfram автоматично перетворює арифметичні вирази в джерелі в канонічну форму, тому вирази на зразок 2/xзберігаються як Times[2, Power[x, -1]]. Це робить частоту Powerдуже високою, а отже, стискаючи її дуже дешево.

(Помноження на Boole@PrimeQ@дещо довше, і неявна Booleзаливка булевих не була здійснена на момент виклику.)

Звідси, Mathematica AnglePathі ListPlotробимо саме те, що нам потрібно:

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

У інтерактивному додатку висновок - це об'єкт векторної графіки, який можна змінити.

введіть тут опис зображення


Класно! Я зійшов до 77 байт, поєднавши наші рішення. Ура!
Роман

14

MATL , 25 24 21 байт

Q:qJyZpbB!sEq*^YpYsXG

Спробуйте це у мережі MATL

Дякуємо @LuisMendo за приємну гольф-сесію в чаті, яка в кінцевому підсумку призвела до цієї 21-байтної версії, запропонувавши Eq*^

Пояснення

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=12345введіть тут опис зображення


8

C (gcc) , 179 байт

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

Спробуйте в Інтернеті!

Функція. Перший аргумент N, другий аргумент - виділений буфер розміром принаймні байт. У цей буфер записується квадратне зображення, повертається його бічна довжина. На зображенні - білий піксель, - чорний піксель.4n2+4n+101

C (gcc) , 219 байт

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

Спробуйте в Інтернеті!

Функція. Перший аргумент N, другий аргумент - це виділений буфер розміром не менше байт. Квадратне зображення у форматі PBM записується в буфер.4n2+4n+2×log10(2n+1)+9

Обрізаний вихід на 20000:

обрізний вихід на 20000

Обидві версії починаються із заходу і повертають праворуч на непарні, ліві на парні.

Я спробував більші тестові корпуси з жодною з них, оскільки вихід з 20000 становив ~ 1,5 ГБ, а 150000 склав би ~ 90 ГБ. Це все зберігається в пам'яті під час виконання програми.

Пояснення верхнього:

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
Я не думаю, що вимагати надання виділеного буфера в якості аргументу дозволено - за метаполітикою будь-який додатковий вхід повинен бути порожнім (що я трактував би як значення 0або нульовий покажчик у випадку C).
Дверна ручка

3
Я інтерпретую це як кажу, що можу очікувати, що він буде виділений. Це також шаблон, який використовується у багатьох стандартних функціях бібліотеки, таких як sprintf.
wastl

Ну добре, ти маєш рацію, це має сенс.
Дверна ручка


8

Мова Вольфрама (Mathematica) , 98 96 91 77 76 63 байт

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

-14 байт: Дякую @lirtosiast за те, що він показав мені, як користуватисяAnglePath ...

-13 байт: ... і ThueMorse!

приклад використання:

%[20000]

введіть тут опис зображення

Покрокове пояснення:

  • If[PrimeQ@#, 2 ThueMorse@# - 1, 0] &- це функція, яка приймає індекс кроків і повертає 0 для непримірів, -1 для парних бімерів і +1 для непарних бій. ThueMorse@#замінює попереднє рішення Total[#~IntegerDigits~2](те саме, модуль 2).

  • Array[Pi/2*%,#]складає список цієї функції з індексом, що йде від 1 до аргументу функції (20000 у прикладі), і множує кожен елемент на π / 2, щоб перетворити його на кут зміни напрямку (радіани). Тепер у нас є 0 для непримірів, -π / 2 для парних бімерів і + π / 2 для непарних праймерів.

  • AnglePath[%]перетворює цей список кутів зміни напряму в шлях. Ця інструкція замінює подвійне використання попереднього рішення Accumulate.

  • ListPlot[%]перетворює список позицій у крапковий графік XY. Якщо лінія краща, скористайтеся ListLinePlotзамість неї. Ці функції побудови графіків мають безліч варіантів, щоб покращити вигляд сюжетів.


1
Дякую @lirtosiast! Це як вивчати іноземну мову: новий словник щодня.
Роман

7

MATL, 31 30 28 26 байт

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

3 байти збережено завдяки @LuisMendo

2 байти збережено завдяки @Sanchises

Спробуйте в MATL Online

Пояснення

Це рішення використовує складні числа для представлення X і Y компонентів 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]

На даний момент у нас є чотири точки ( (0, 1), (-1, 0), (0, -1), (1, 0)) у масиві, представленому складними числами. Це чотири кардинальні напрямки. Тепер ми хочемо використовувати їх для «прогулянки».

По суті, так це працює в тому, що ми починаємо прямувати в нульовому напрямку (0-й елемент масиву, який є (-1, 0)). Для кожного кроку нам потрібно визначити зміну цього заголовка. Ми будемо використовувати цілі числа для відстеження цієї зміни. Якщо ми хочемо повернути «вправо», ми збільшуємо це ціле число на 1 (посилаючись на наступний елемент у 4-точковому масиві), і якщо ми хочемо перейти «вліво», ми декрементуємо це ціле число на 1 (посилаючись на попередній елемент у 4-бальний масив). Якщо ми хочемо продовжити наш шлях, ми будемо зберігати ціле значення постійним (посилаючись на той самий елемент у 4-точковому масиві).

Ця частина коду створює масив всіх тих 0, -1і 1цінностей.

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

Тепер у нас є масив різниць між послідовними цілими числами, тому ми можемо обчислити сукупну суму цих вгору, щоб отримати індекси, які потім ми можемо використовувати для пошуку напряму на кожному кроці в початковому масиві 4 елементів.

Зручно, що MATL має індексацію обертання таким чином, що індекс 5обертається до початку 4-елементного масиву. Ми можемо використовувати це на нашу користь, щоб ми могли збільшити та зменшити це ціле число, не турбуючись про те, що масив опорного напрямку становить лише 4 елементи.

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

Тепер у нас є масив напрямів кроків, тому ми можемо обчислити сукупну суму цих напрямків, щоб простежити шлях, який було зроблено.

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

5

Perl 6 , 213 182 байт

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

Спробуйте в Інтернеті!

(Дійсно вдалося збити це!)

Ця функція виводиться у форматі SVG.

  • { -{ .is-prime * .base(2).comb(~1) R** -1 || i }(++$)i } ... *являє собою нескінченну послідовність зміни напрямків для кожного кроку у вигляді складних чисел, де 1означає «продовжувати в тому ж напрямку», iозначає «повернути ліворуч» і -iозначає «повернути праворуч».
  • [^$_] обмежує цю послідовність числом кроків, поданих як аргумент функції.
  • [\*] сканує цю послідовність із (складним) множенням, перетворюючи список відносних напрямків змін у список абсолютних напрямків.
  • [\+]сканує цю послідовність за допомогою (складного) додавання, створюючи список відвіданих координат.
  • ».reals перетворює цей список складних чисел у двоелементні списки його реальних та уявних частин.

Образ SVG - це лише один єдиний pathелемент.

Вихід (перетворений в PNG) для N = 20000:

шлях для N = 20000


4

C, 321 байт

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

Спробуйте в Інтернеті!

Я почав працювати над цим ще до того, як був опублікований інший відповідь С, але я зрозумів, що так само, як і раніше, міг би розмістити свій. Це набагато довше, але воно також автоматично обробляє вихідне зображення до розмірів результату.

Функція називається як f(n), а вихід - stdout у форматі netpbm.

Приклад виводу для 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

Простий тест - це, по суті, те, що використовується у відповіді Лінни на інший виклик , що спирається на теорему Вілсона .

Тест на паритет використовує адаптацію методу підрахунку бітів Керніган .

Оскільки простий тест дуже повільний, і алгоритм запускає всю функцію генерації контуру для кожного намальованого пікселя, будь-який вхід набагато перевищує 1000 разів у TIO.



4

LOGO, 177 171 байт

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

Для використання, зробити що - щось на зразок цього :

reset
pu
fw 100
pd
g 3000

Вибачте, але я не зміг захопити вихідний зразок. Пояснення:

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

Це рекурсивна процедура, яка обертається на 180 ° для кожного набору бітів у своєму параметрі, що ефективно обчислює паритет його бінарного розширення.

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

Це дуже базовий тест на первинність. Після спеціального кожуха 1 процедура достроково повертається, якщо виявлено фактор. Якщо, однак, поточне значення вважається простим, воно повертається праворуч, а потім використовує описану вище процедуру, щоб змінити його на лівий поворот у відповідних випадках.

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

Це просто простий цикл для тестування всіх чисел до nпервинності та переміщення двох пікселів після кожного.


4

Желе , 41 байт

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

Спробуйте в Інтернеті!

N

N=3000

Вихід для 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 байт

Перший раз тут, на CodeGolf, спочатку розпочався з ~ 1500 байт-коду. Полювали його на менше половини майже більше третини. Не соромтеся продовжувати гольф. Байти, що враховуються: цей інструмент

Принцип:
малює полотно фіксованого розміру з N та змінною довжиною ходу як вхід.

Зміни:

-07 байт - видалити пропущене, якщо
-08 байт - змінити перемикач на if / else
-28 байтів - перехід на tenary якщо / else
-76 байт - коротший простий тест (час виконання / 3)
-22 байтів - використовуйте цю основну функцію (час виконання * 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}

Невикористаний код з пробілами:

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
}

Приклади:

N = 7 - довжина = 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 - довжина = 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 - довжина = 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 - довжина = 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"/> 


Колір залежить від кількості ліній, що перекриваються? Класно!
val

Я не змінив стиль обведення, це має бути чорний колір за замовчуванням без малюнка та прозорості. Знайдено тут . Чому може статися зміна кольору, може бути пов’язано з шириною обведення, яку я встановив у другому параметрі, моя функція приймає @val. Вибачте, що можливо вас розчарував.
pixma140

3

Червоний , 515 480 471 байт

-1 байт завдяки 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]]]]]

Значна частина коду (~ 160 байт) стосується нормалізації координат, щоб графіка повністю вміщувалася в полотно незалежно від розміру вводу.

Початковий напрямок: Південь.

Ось результат для n = 3000

3000 ітерацій

n = 20000

20000


1
З цікавості, чому не існує будь - яких пробілу , необхідні для модулі на if j%(k + 1)і if j% 2 = 1, але є пробілу , необхідні для більшості інших операторів ( +, /і т.д.). Чи можна також видалити простір за модулем pick[-90 90]s% 2? Насправді, чому також не потрібні пробіли as-pair k/1 - t * c k/2 - v * cдля /?
Кевін Круїссен

1
@KevinCruijssen Так, простір можна видалити для s% 2, дякую! Я не знаю чому, але модуль %- єдиний оператор, для якого може бути відпущений простір перед ним, якщо йому передує слово (змінна). У as-pair k/1 - t * c k/2 - v * cкосої частини /служать зовсім інші цілі - вони paths. kє a pairі k/1є першим елементом (його можна вибрати також і k/xабо pick k 1). Простіри потрібні майже скрізь, винятки є навколо ()[]{}, тому що двозначності немає.
Гален Іванов,

@KevinCruijssen Більшість символів можуть використовуватися в wordіменах ( Redне має variables, все є wordабо значення (або якийсь синтаксичний блок, як [...]або (...)). Отже: a*4: 45-> слову a*4присвоюється значення 45. %використовується як маркер для file!типу даних і, можливо, тому його не можна використовувати в wordіменах, але може порушити правила для інших арифметичних операторів.
Гален Іванов,

1
Ну добре, це має сенс, що /там інше призначення є, і символи можуть використовуватися без пробілів у змінних (або wordsяк їх, очевидно, називають Червоним). Дякую за пояснення. :) І радий, що міг (в основному випадково) зберегти байт для s% 2. :)
Кевін Круїссен

1

Обробка, 140+ байт

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

Може не виконати чітко побачене

ходити

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.