Final kata of the series (highly recommended to compute [layers](https://www.codewars.com/kata/progressive-spiral-number-position/) and [branch](https://www.codewars.com/kata/progressive-spiral-number-branch/) first to get a good idea), this is a blatant ripoff of [the one offered on AoC](http://adventofcode.com/2017/day/3).

Given a number, return the Manhattan distance considering the core of the spiral (the `1` cell) as 0 and counting each step up, right, down or left to reach a given cell.

For example, using our beloved 5x5 square:

```
17 16 15 14 13    4 3 2 3 4
18 05 04 03 12    3 2 1 2 3
19 06 01 02 11 => 2 1 0 1 2
20 07 08 09 10    3 2 1 2 3
21 22 23 24 25    4 3 2 3 4
```

And thus your code should behave like this:

```python
distance(1) == 0
distance(5) == 2
distance(25) == 4
distance(30) == 5
distance(50) == 7
```

Just be ready for larger numbers, as usual always positive.

*[Dedicated to [swiftest learner I met in a long while](https://www.codewars.com/users/irbekrm/)]*

Source: codewars | Difficulty: EASY
Tags: Number theory

Fundamentals

Mathematics

Starter code: def distance(n):
	

Solutions:
def distance(n):
	if n == 1:
		return 0
	r = 0 - (1 - n ** 0.5) // 2
	(d, m) = divmod(n - (2 * r - 1) ** 2 - 1, 2 * r)
	z = (r * (1 + 1j) - m - 1) * 1j ** d
	return abs(z.real) + abs(z.imag)


from itertools import count

def pos(n):
	for i in count(1, 2):
		if i * i >= n:
			break
	n -= (i - 2) ** 2
	step = i - 1
	p = (1 + 1j) * (step // 2)
	for d in [-1, -1j, +1, +1j]:
		x = min(step, n)
		p += x * d
		n -= x
	return p

def distance(n):
	p = pos(n)
	return abs(int(p.real)) + abs(int(p.imag))


import math

def distance(n):
	if n == 1:
		return 0
	level = math.ceil(n ** 0.5) // 2
	l_start = (level * 2 - 1) ** 2 + 1
	quad = (n - l_start) // (2 * level)
	l_span = 2 * level + 1
	direct = l_start - 1 + l_span // 2 + (l_span - 1) * quad
	dist = level + abs(direct - n)
	return dist


distance = lambda n: (lambda s: 0 if n == 1 else s + abs(s - (n - 4 * s * s + 4 * s - 1) % (2 * s)))(int((n - 1) ** 0.5 + 1) >> 1)


import math

def distance(n):
	if n == 1:
		return 0
	if n <= 9:
		return 2 if n % 2 else 1
	lower = math.ceil(n ** 0.5) - 2 if math.ceil(n ** 0.5) % 2 else math.ceil(n ** 0.5) - 1
	cycle = list(range(lower, (lower + 1) // 2 - 1, -1)) + list(range((lower + 1) // 2 + 1, lower + 2))
	return cycle[(n - lower ** 2 - 1) % len(cycle)]


def distance(n):
	if n == 1:
		return 0
	i = 1
	while True:
		if n <= (2 * i - 1) ** 2:
			break
		i += 1
	x = (n - (2 * i - 3) ** 2 - 1) % (2 * i - 2)
	h = (2 * i - 2) // 2
	if x < h:
		return i + h - x - 2
	else:
		return i + x - h


from math import *

def distance(n):
	k = ceil((sqrt(n) - 1) / 2)
	t = 2 * k + 1
	m = t ** 2
	t = t - 1
	if n >= m - t:
		x = (k - (m - n), -k)
		return sum(map(abs, x))
	m -= t
	if n >= m - t:
		x = (-k, -k + (m - n))
		return sum(map(abs, x))
	m -= t
	if n >= m - t:
		x = (-k + (m - n), k)
		return sum(map(abs, x))
	x = (k, k - (m - n - t))
	return sum(map(abs, x))


from math import sqrt, floor

def distance(n):
	if n == 1:
		return 0
	x = floor(sqrt(n - 1) + 1) // 2
	return x + abs(x - (n - 4 * x * (x + 1) - 1) % (2 * x))


from math import ceil

def distance(n):
	border = ceil(int(n ** 0.5) / 2) + int(not (n ** 0.5).is_integer())
	k = border * 2 - 1
	a = k ** 2
	for i in range(4):
		if a - k < n <= a:
			return border - 1 + abs(n - (a - k + 1 + a) // 2)
		a -= k - 1


from math import ceil

def distance(n):
	m = ceil((n ** 0.5 - 1) / 2)
	x = y = m
	t = 1 + 4 * m * (m + 1)
	for (dx, dy) in [(0, -1), (-1, 0), (0, 1), (1, 0)]:
		if n == t:
			break
		d = min(t - n, 2 * m)
		x += dx * d
		y += dy * d
		t -= d
	return abs(x) + abs(y)