# [seqfan] Re: Anyone have a 3-D "Ulam" spiral?

M. F. Hasler oeis at hasler.fr
Wed Apr 28 00:08:52 CEST 2021

```On Tue, Apr 27, 2021 at 2:25 PM Hugo Pfoertner <yae9911 at gmail.com> wrote:

> A simpler 2-dimensional analogue of Maxmilian's idea is implemented in
> oeis.org/A305575 and oeis.org/A305576.

I have expanded this to 3 dimensions by adding a sorting by the
> z-coordinate between the sorting by distance from the coordinate origin and
> the sorting by the circumferential angle. (... https://oeis.org/A342561
> ff ...)

Yes, that's a much nicer idea: instead of searching for complicated
shortest paths,
fill the shells by circles defined by "slicing" the shell according to the
z-values.
(taking intersection with Z-planes, like a "scan" of shell/sphere).

> If you want to avoid the relatively large distances when jumping to the
> next shell with R = const,

then a reversal of a modified mapping, i.e. the determination of the index
> position in this
> "spiral" at given coordinates (x, y, z), is quite complicated.
>

I don't know whether you refer to that, but there's a simple modification
to stay (IMHO) closer to the Ulam spiral idea;
in the sense of having a more continuous (and shorter) path by avoiding the
large jump from +R to -(R+1) when going to the next shell:

instead of moving the "scanning planes" always from lowest to highest
z-coordinate,
switch the z-scan direction every other shell:
e.g., scan from z=1 to z=-1 for the first shell (R=1), then scan from z =
-R to z = +R for the next shell R² = 2,
then scan from z = R to z = -R for the next shell R² = 3, etc.
I don't think that would make the inverse function (much) more complicated.

(Vaguely related: "stripe enumeration" of N x N in A319571,
didn't search to see whether this idea has been extended to enumerate Z x N
and/or N x Z in a "windshield wiper" way.)

Anyway, that's still much easier to code than my original idea:
I include a very primitive "brute force" implementation in PARI below,
which gives:

Shell R^2=0: [0,0,0],
Shell R^2=1: [0,0,1], [0,1,0], [1,0,0], [-1,0,0], [0,-1,0], [0,0,-1],
Shell R^2=2: [0,1,-1], [1,0,-1], [-1,0,-1], [0,-1,-1],
[1,1,0], [-1,1,0], [-1,-1,0], [1,-1,0],
[0,1,1], [1,0,1], [-1,0,1], [0,-1,1],
Shell R^2=3: [1,1,1], [-1,1,1], [-1,-1,1], [1,-1,1], [1,1,-1], [-1,1,-1],
[-1,-1,-1], [1,-1,-1],
Shell R^2=4: [0,0,-2], [0,2,0], [2,0,0], [-2,0,0], [0,-2,0], [0,0,2],
Shell R^2=5: [0,1,2], [1,0,2], [-1,0,2], [0,-1,2],
[0,2,1], [2,0,1], [-2,0,1], [0,-2,1],
[2,1,0], [1,2,0], [-1,2,0], [-2,1,0], [-2,-1,0], [-1,-2,0],
[1,-2,0], [2,-1,0],
[0,2,-1], [2,0,-1], [-2,0,-1], [0,-2,-1],
[0,1,-2], [1,0,-2], [-1,0,-2], [0,-1,-2],

- Maximilian

(PARI)
/* make shell n: create coordinates of decreasing value, then consider
permutations and sign flips; finally sort by z [decreasing when dir != 0]
then polar angle */
shell(n, dir=(-1)^n, Q=Qfb(1,0,1), L=List() )={n||return([[0,0,0]]); for(
z=sqrtint((n-1)\3)+1, sqrtint(n), my( S= if( n>z^2, Set( apply( vecsort,
abs( qfbsolve( Q,n-z^2,3 )))) , [[0,0]]));
foreach(S, s, forperm(concat(s,z), p, listput( L, p )))); /*print1(L);*/
for(i=1,3, for(j=1,#L, xyz=L[j]; (xyz[i]*=-1) && listput(L,xyz)));
vecsort(L, (p,q)-> if( p[3] != q[3],  dir*(p[3] - q[3]), p[1]==q[1], /* if
x-coord is same, return <0 if y-coord of p is bigger */ q[2]-p[2],
/* else, if they're in different half planes, return <0 if p is in the
upper half, q in the lower half */ p[2]*q[2]<=0, q[2] - p[2],
/* in the same half plane: return the y-coords (eg. >0) iff p is to the
left, ie, smaller x-coord */ (q[1]-p[1])*(p[2]+q[2]) )/*endif*/ ); }

d=1; for(n=0,5, #(L=shell(n,d))|| next; d=-d; print1("\nShell R^2="n":
");foreach(L, x, printf("%d, ",Vec(x))))

=> the above output.

```