44
5
Drawing the Sierpinski triangle has been done to death. There's other interesting things we can do with it though. If we squint hard enough at the triangle, we can view upside-down triangles as nodes of a fractal graph. Let's find our way around that graph!
First, let's assign a number to each node. The largest upside-down triangle will be node zero, and then we just go down layer by layer (breadth-first), assigning consecutive numbers in the order top-left-right:
Click for larger version where the small numbers are a bit less blurry.
(Of course, this pattern continues ad infinitum inside the blue triangles.) Another way to define the numbering is that the centre node has index 0
, and the children of node i
(adjacent triangles of the next-smaller scale) have indices 3i+1
, 3i+2
, and 3i+3
.
How do we move around this graph? There are up to six natural steps one can take from any given triangle:
- One can always move through the midpoint of one of the edges to one of the three children of the current node. We'll designate these moves as
N
,SW
andSE
. E.g. if we're currently on node2
, these would lead to nodes7
,8
,9
, respectively. Other moves through the edges (to indirect descendants) are disallowed. - One can also move through one of the three corners, provided it doesn't touch the edge of the triangle, to either the direct parent or one of two indirect ancestors. We'll designate these moves as
S
,NE
andNW
. E.g. if we're currently on node31
,S
would lead to10
,NE
would be invalid andNW
would lead to0
.
The Challenge
Given two non-negative integers x
and y
, find the shortest path from x
to y
, using only the six moves described above. If there are several shortest paths, output any one of them.
Note that your code should work for more than just the 5 levels depicted in the above diagram. You may assume that x, y < 1743392200
. This ensures that they fit inside a 32-bit signed integer. Note that this corresponds to 20 levels of the tree.
Your code must process any valid input in less than 5 seconds. While this rules out a brute force breadth-first search, it should be a fairly loose constraint — my reference implementation handles arbitrary input for depth 1000 in half a second (that's ~480-digit numbers for the nodes).
You may write a program or function, taking input via STDIN (or closest alternative), command-line argument or function argument and outputting the result via STDOUT (or closest alternative), function return value or function (out) parameter.
The output should be a flat, unambiguous list of the strings N
, S
, NE
, NW
, SE
, SW
, using any reasonable separator (spaces, linefeeds, commas, ","
...).
Standard code-golf rules apply.
Test Cases
The first few test cases can be worked out by hand using the diagram above. The others ensure that answers are sufficiently efficient. For those, there may be other solutions of the same length that are not listed.
0 40 => N N N N
66 67 => S SW N N N
30 2 => NW NW -or- NE SW
93 2 => NE SW
120 61 => NW NW NW NW N SE SW N
1493682877 0 => S S NW NW
0 368460408 => SW SW N N SW SW SE SW SW N SE N N SW SW N SE SE
1371432130 1242824 => NW NW NE NW N SE SW SW SW SE SE SW N N N N SW
520174 1675046339 => NE NW NE NE SE SE SW SW N SE N SW N SW SE N N N N SE SE SW SW
312602548 940907702 => NE NW S SW N N SW SE SE SE SW SE N N SW SE SE SE SW
1238153746 1371016873 => NE NE NE SE N N SW N N SW N SE SE SW N SW N N SE N SE N
547211529 1386725128 => S S S NE NW N N SE N SW N SE SW SE SW N SE SE N SE SW SW N
1162261466 1743392199 => NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE
6Damn that was fast. I can't tell you how happy it makes me every time I get you to answer one of my challenges. :) – Martin Ender – 2015-12-17T15:14:07.963
2@MartinBüttner Thanks, that's a huge compliment! FWIW, I hugely enjoy solving your challenges. I might, or might not, have started working on this one while it was still in the sandbox... :) – Ell – 2015-12-17T15:18:54.213
2The addressing scheme is brilliant. This is awesome. – BrainSteel – 2015-12-17T15:20:59.490
Excellent answer. But how did you type all this up in less than an hour? ;-) – AdmBorkBork – 2015-12-17T15:26:19.400
1@BrainSteel the first thing that occured to me was to try that addressing scheme, but to see the whole thing conceptualized, implemented and written up in under an hour is awesome. +1 – Level River St – 2015-12-17T17:25:40.040
I believe this may be slightly off, as the largest center triangle does not have a value of 0, nor match the case in the OP where
i
is the value in the center node, and going counter-clockwise, the values are3i+1
,3i+2
, and3i+3
– None – 2015-12-17T21:06:11.5771@Zymus I'm not sure I follow, but if you're referring to the picture, it's not supposed to match the OP—this is a different addressing scheme, as described in the post., – Ell – 2015-12-17T21:28:18.180
@Ell, got it, I misunderstood. – None – 2015-12-17T22:22:04.180
1
The addressing system described here is a base-3 bijective numeration (using digits 0-2 rather than the more conventional 1-3).
– Blckknght – 2015-12-18T02:28:40.210