Part 1


In [1]:
function steps(n)
    root = ceil(sqrt(n))
    curR = root % 2 != 0 ? root : root + 1
    numR = (curR - 1) / 2
    cycle = n - ((curR - 2) ^ 2) 
    innerOffset = cycle % (curR - 1)    
    numR + abs(innerOffset - numR)
end


Out[1]:
steps (generic function with 1 method)

In [2]:
steps(23)


Out[2]:
2.0

In [3]:
steps(12)


Out[3]:
3.0

In [4]:
@time steps(347991)


  0.000009 seconds (84 allocations: 6.107 KiB)
Out[4]:
480.0

Part 2

Code taken from Ferran solution and translated to Julia :-P


In [5]:
function number_to_coordinates(n)
    
    q = floor(sqrt(n))
    r = n - q ^ 2
    if q % 2 != 0
        x = div(q - 1, 2) + min(1, r) + min(q - r + 1, 0)
        y = - div(q - 1, 2) + min(max(r - 1, 0), q)
    else
        x = 1 - div(q, 2) - min(1, r) - min(q - r + 1, 0)
        y = div(q, 2) - min(max(r - 1, 0), q)
    end
    
    [x, y]
end

function spiral_manhattan(n)
    x, y = number_to_coordinates(n)
    abs(x) + abs(y)
end


Out[5]:
spiral_manhattan (generic function with 1 method)

In [6]:
function spiral_coordinates(c::Channel)
    n = 0
    while n >= 0
        n += 1
        put!(c, number_to_coordinates(n))
    end  
end


Out[6]:
spiral_coordinates (generic function with 1 method)

In [7]:
using DataStructures

function first_larger(bound)
    values = DefaultDict(0)
    g = Channel(spiral_coordinates)
    pos = take!(g)
    values[pos] = 1
    while values[pos] <= bound
        pos = take!(g)
        values[pos] = sum( values[pos + [i, j]] for i=-1:1 for j=-1:1 if i!=0||j!=0 )
    end    
    values[pos]
end


Out[7]:
first_larger (generic function with 1 method)

In [8]:
first_larger(22)


Out[8]:
23

In [9]:
@time first_larger(347991)


  0.003836 seconds (7.68 k allocations: 312.172 KiB)
Out[9]:
349975