Well, I came up with a pretty dumb solution that goes through the Cartesian coordinates and finds the coordinates and their distance in a rather brain-dead way. At least it seems to give the correct output:
Code:
//hive.cpp
#include <iostream>
#include <cmath>
struct Coord
{
int x, y;
};
Coord coord_from_num(unsigned n)
{
const unsigned turn_count = 6;
Coord turns[turn_count] = {{-1, 0}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1, 1}};
unsigned level = 0;
unsigned level_start = 1;
unsigned level_end = 1;
//determine level on the spiral
while (n > level_end) {
level_start = level_end;
++level;
level_end += level * 6;
}
//find coordinates by moving along the spiral
Coord result = {0, level};
for (unsigned i = 0; i != turn_count; ++i) {
for (unsigned j = 0; j != level; ++j) {
if (level_start == n)
return result;
result.x += turns[i].x;
result.y += turns[i].y;
++level_start;
}
}
return result; // 1
}
int get_move(int a, int b)
{
//what should be added to a, to advance the value towards b
if (a < b) return 1;
else if (a > b) return -1;
return 0;
}
int get_distance(Coord start, const Coord& target)
{
//start advancing towards the target and count steps
//move both in x and y direction, unless increments are (1, 1) or (-1, -1)
int distance = 0;
while (!(start.x == target.x && start.y == target.y)) {
++distance;
int xInc = get_move(start.x, target.x);
int yInc = get_move(start.y, target.y);
start.x += xInc;
if (abs(xInc + yInc) != 2)
start.y += yInc;
}
return distance;
}
int main()
{
int a = 0, b = 0;
while (std::cin >> a >> b && a && b) {
Coord ac = coord_from_num(a);
Coord bc = coord_from_num(b);
std::cout << "The distance between cells " << a << " and " << b << " is "
<< get_distance(ac, bc) << '\n';
}
}