We need a way to memorize positions already visited such that they will not be counted twice.
A coordinate system with (0,0) as the first (starting) position would be the natural choice.
From (0,0), we can move in all 4 directions:
Diagonals are just juxtapositions of 2 orthogonal moves:
The distance and angle between head and tail determines how the tail will follow to remain in close proximity:
By applying move
to the head on each step of the procedure and letting the tail follow
it, their coordinates can then be determined:
Finally, counting all distinct coordinates from the tail results is trivial:
I extended run-simulation
and process-instruction
to work with tails of multiple knots, which just means that each preceeding knot in the list is the lead/head that the next one will follow:
To visualize the results in a grid, it is important to recognize that the values can be negative and that the y-axis is flipped from top-down coordinates used by SVG. I made use of the view-box and SVG transform to translate the values to the correct coordinates.
The results of the first example with only the head-knot (white dot):
And its characteristic pattern left behind by the tail-knot (red):
For 10 knots, we can show the traces as a gradient from red→blue with a blue dot emphasizing the last tail-knot:
The second example looks somewhat more interesting.
First, only the movement of the head:
Let’s see how the tail follows:
While the head moves in a rectangular fashion, the tail tries to catch it with diagonal shortcuts, which of course reflects the encoded movement pattern.
The actual input looks a lot like a random walk; uncomment the following lines if you are curios (takes a few seconds to render):
(def results4 (run-simulation 2 (parse input)))
(count (distinct (map (comp last :tail) results4)))
(make-chart results4)
Can’t render this with 10 knots, because of stack overflow. D: Would have to recreate this in canvas.