Prime parity peregrination

MATL, 25 24 21 bytes

Q:qJyZpbB!sEq*^YpYsXG

Try it at MATL online

Thanks @LuisMendo for a nice golfing session in chat that ultimately led to this 21 byte version, by suggesting Eq*^

Explanation

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

Example for \$k=12345\$: enter image description here


Sledgehammer 0.4, 22 20 bytes

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

Decompresses into this Wolfram Language function:

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

Ungolfed

First we define a function that returns the angle to turn at each step:

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

ThueMorse is the parity of the sum of binary digits. We use -1^(...) rather than 2*...-1 for a slightly complicated reason: Wolfram Language automatically converts arithmetic expressions in source to a canonical form, so expressions like 2/x are stored as Times[2, Power[x, -1]]. This makes the frequency of Power very high, and thus compressing it very cheap.

(Multiplying by Boole@PrimeQ@ is slightly longer, and implicit Boole casting of Booleans had not been implemented at the time of the challenge.)

From here, Mathematica's AnglePath and ListPlot do exactly what we need:

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

In the interactive app, output is a rescalable vector Graphics object.

enter image description here


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

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

-14 bytes: Thanks to @lirtosiast for showing me how to use AnglePath...

-13 bytes: ...and ThueMorse!

usage example:

%[20000]

enter image description here

Step-by-step explanation:

  • If[PrimeQ@#, 2 ThueMorse@# - 1, 0] & is a function that takes the step index and returns 0 for non-primes, -1 for even-binary primes, and +1 for odd-binary primes. ThueMorse@# replaces the previous solution's Total[#~IntegerDigits~2] (which is the same, modulo 2).

  • Array[Pi/2*%,#] makes a list of this function with the index going from 1 to the function argument (20000 in the example), and multiplies every element by π/2 to make it into a direction-change angle (radians). We now have 0 for non-primes, -π/2 for even-binary primes, and +π/2 for odd-binary primes.

  • AnglePath[%] converts this list of direction-change angles into a path. This instruction replaces the previous solution's double-use of Accumulate.

  • ListPlot[%] converts the list of positions into a XY dot plot. If a line is preferred, use ListLinePlot instead. These plotting functions have lots of options to make the plots look better.