# [ACCEPTED]-Generating triangular/hexagonal coordinates (xyz)-hexagonal-tiles

Score: 21

Not only is `x + y + z = 0`, but the absolute values of 4 x, y and z are equal to twice the radius 3 of the ring. This should be sufficient 2 to identify every hexagon on each successive 1 ring:

``````var radius = 4;
for(var i = 0; i < radius; i++)
{
for(var j = -i; j <= i; j++)
for(var k = -i; k <= i; k++)
for(var l = -i; l <= i; l++)
if(Math.abs(j) + Math.abs(k) + Math.abs(l) == i*2 && j + k + l == 0)
console.log(j + "," + k + "," + l);
console.log("");
}``````
Score: 13

Another possible solution, that runs in 8 O(radius2), unlike the O(radius4) of tehMick's solution (at the expense of a lot 7 of style) is this:

``````radius = 4
x = 0
y = -r
z = +r
print x,y,z
for i in range(r):
x = x+1
z = z-1
print x,y,z
for i in range(r):
y = y+1
z = z-1
print x,y,z
for i in range(r):
x = x-1
y = y+1
print x,y,z
for i in range(r):
x = x-1
z = z+1
print x,y,z
for i in range(r):
y = y-1
z = z+1
print x,y,z
for i in range(r-1):
x = x+1
y = y-1
print x,y,z
``````

or written a little more 6 concisely:

``````radius = 4
deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]]
x = 0
y = -r
z = +r
print x,y,z
for j in range(6):
if j==5:
num_of_hexas_in_edge = r-1
else:
num_of_hexas_in_edge = r
for i in range(num_of_hexas_in_edge):
x = x+deltas[j]
y = y+deltas[j]
z = z+deltas[j]
print x,y,z
``````

It's inspired by the fact the 5 hexagons are actually on the exterior of 4 a hexagon themselves, so you can find the 3 coordinates of 1 of its points, and then 2 calculate the others by moving on its 6 1 edges.

Score: 6

This was a fun puzzle.

O(radius2) but with (hopefully) a 11 bit more style than Ofri's solution. It occurred to me 10 that coordinates could be generated as though 9 you were "walking" around the 8 ring using a direction (move) vector, and 7 that a turn was equivalent to shifting the 6 zero around the move vector.

This version 5 also has the advantage over Eric's solution in that it 4 never touches on invalid coordinates (Eric's 3 rejects them, but this one never even has 2 to test them).

``````# enumerate coords in rings 1..n-1; this doesn't work for the origin
for ring in range(1,4):
# start in the upper right corner ...
(x,y,z) = (0,-ring,ring)
# ... moving clockwise (south-east, or +x,-z)
move = [1,0,-1]

# each ring has six more coordinates than the last
for i in range(6*ring):
# print first to get the starting hex for this ring
print "%d/%d: (%d,%d,%d) " % (ring,i,x,y,z)
# then move to the next hex
(x,y,z) = map(sum, zip((x,y,z), move))

# when a coordinate has a zero in it, we're in a corner of
# the ring, so we need to turn right
if 0 in (x,y,z):
# left shift the zero through the move vector for a
# right turn
i = move.index(0)
(move[i-1],move[i]) = (move[i],move[i-1])

print # blank line between rings
``````

Three cheers for python's 1 sequence slicing.

Score: 2

``````const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.textAlign = "center";

const altitude = Math.sqrt(3) * radius;
const total = 3;
for (let x = -total; x <= total; x++) {
let y1 = Math.max(-total, -x-total);
let y2 = Math.min(total, -x+total);
for (let y = y1; y <= y2; y++) {
let xx = x * altitude + Math.cos(1/3*Math.PI) * y * altitude;
let yy = y * radius * 1.5;
xx += canvas.width/2;
yy += canvas.height/2;
ctx.fillText(x+","+y, xx, yy);
}
}

ctx.beginPath();
for(let a = 0; a < Math.PI*2; a+=Math.PI/3){
let xx = Math.sin(a) * radius + x;
let yy = Math.cos(a) * radius + y;
if(a == 0) ctx.moveTo(xx, yy);
else ctx.lineTo(xx, yy);
}
ctx.stroke();
}``````
``<canvas id="canvas" width=250 height=250>``

0

Score: 1

Ok, after trying both the options I've settled 8 on Ofri's solution as it is a tiny bit faster 7 and made it easy to provide an initial offset 6 value. My code now looks like this:

``````var xyz = [-2,2,0];
var deltas = [[1,0,-1],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0]];
for(var i = 0; i < radius; i++) {
var x = xyz;
var y = xyz-i;
var z = xyz+i;
for(var j = 0; j < 6; j++) {
for(var k = 0; k < i; k++) {
x = x+deltas[j]
y = y+deltas[j]
z = z+deltas[j]
placeTile([x,y,z]);
}
}
}
``````

The 5 "placeTile" method uses cloneNode to copy 4 a predefined svg element and it takes approx 3 0.5ms per tile to execute which is more 2 than good enough. A big thanks to tehMick 1 and Ofri for your help!

JS

More Related questions