44 KiB
44 KiB
In [1]:
k = 4In [2]:
for n in range(2 * k):
print abs(n - k),4 3 2 1 0 1 2 3
In [3]:
for n in range(2 * k):
print abs(n - (k - 1)),3 2 1 0 1 2 3 4
In [4]:
for n in range(2 * k):
print abs(n - (k - 1)) + k,7 6 5 4 5 6 7 8
In [5]:
def row_value(k, i):
i %= (2 * k) # wrap the index at the row boundary.
return abs(i - (k - 1)) + kIn [6]:
k = 5
for i in range(2 * k):
print row_value(k, i),9 8 7 6 5 6 7 8 9 10
In [7]:
def rank_and_offset(n):
assert n >= 2 # Guard the domain.
n -= 2 # Subtract two,
# one for the initial square,
# and one because we are counting from 1 instead of 0.
k = 1
while True:
m = 8 * k # The number of places total in this rank, 4(2k).
if n < m:
return k, n % (2 * k)
n -= m # Remove this rank's worth.
k += 1In [8]:
for n in range(2, 51):
print n, rank_and_offset(n)2 (1, 0) 3 (1, 1) 4 (1, 0) 5 (1, 1) 6 (1, 0) 7 (1, 1) 8 (1, 0) 9 (1, 1) 10 (2, 0) 11 (2, 1) 12 (2, 2) 13 (2, 3) 14 (2, 0) 15 (2, 1) 16 (2, 2) 17 (2, 3) 18 (2, 0) 19 (2, 1) 20 (2, 2) 21 (2, 3) 22 (2, 0) 23 (2, 1) 24 (2, 2) 25 (2, 3) 26 (3, 0) 27 (3, 1) 28 (3, 2) 29 (3, 3) 30 (3, 4) 31 (3, 5) 32 (3, 0) 33 (3, 1) 34 (3, 2) 35 (3, 3) 36 (3, 4) 37 (3, 5) 38 (3, 0) 39 (3, 1) 40 (3, 2) 41 (3, 3) 42 (3, 4) 43 (3, 5) 44 (3, 0) 45 (3, 1) 46 (3, 2) 47 (3, 3) 48 (3, 4) 49 (3, 5) 50 (4, 0)
In [9]:
for n in range(2, 51):
k, i = rank_and_offset(n)
print n, row_value(k, i)2 1 3 2 4 1 5 2 6 1 7 2 8 1 9 2 10 3 11 2 12 3 13 4 14 3 15 2 16 3 17 4 18 3 19 2 20 3 21 4 22 3 23 2 24 3 25 4 26 5 27 4 28 3 29 4 30 5 31 6 32 5 33 4 34 3 35 4 36 5 37 6 38 5 39 4 40 3 41 4 42 5 43 6 44 5 45 4 46 3 47 4 48 5 49 6 50 7
In [10]:
def row_value(k, i):
return abs(i - (k - 1)) + k
def rank_and_offset(n):
n -= 2 # Subtract two,
# one for the initial square,
# and one because we are counting from 1 instead of 0.
k = 1
while True:
m = 8 * k # The number of places total in this rank, 4(2k).
if n < m:
return k, n % (2 * k)
n -= m # Remove this rank's worth.
k += 1
def aoc20173(n):
if n <= 1:
return 0
k, i = rank_and_offset(n)
return row_value(k, i)In [11]:
aoc20173(23)Out [11]:
2
In [12]:
aoc20173(23000)Out [12]:
105
In [13]:
aoc20173(23000000000000)Out [13]:
4572225
In [14]:
from sympy import floor, lambdify, solve, symbols
from sympy import init_printing
init_printing() In [15]:
k = symbols('k')In [16]:
E = 2 + 8 * k * (k + 1) / 2 # For the reason for adding 2 see above.
EOut [16]:
In [17]:
def rank_of(n):
return floor(max(solve(E - n, k))) + 1In [18]:
for n in (9, 10, 25, 26, 49, 50):
print n, rank_of(n)9 1 10 2 25 2 26 3 49 3 50 4
In [19]:
%time rank_of(23000000000000) # Compare runtime with rank_and_offset()!Out [19]:
CPU times: user 68 ms, sys: 8 ms, total: 76 ms Wall time: 73.8 ms
In [20]:
%time rank_and_offset(23000000000000)Out [20]:
CPU times: user 308 ms, sys: 0 ns, total: 308 ms Wall time: 306 ms
In [21]:
y = symbols('y')In [22]:
g, f = solve(E - y, k)In [23]:
gOut [23]:
In [24]:
fOut [24]:
In [25]:
floor(f) + 1Out [25]:
In [26]:
F = lambdify(y, floor(f) + 1)In [27]:
for n in (9, 10, 25, 26, 49, 50):
print n, int(F(n))9 1 10 2 25 2 26 3 49 3 50 4
In [28]:
%time int(F(23000000000000)) # The clear winner.Out [28]:
CPU times: user 0 ns, sys: 0 ns, total: 0 ns Wall time: 11.9 µs
In [29]:
from math import floor as mfloor, sqrt
def mrank_of(n):
return int(mfloor(sqrt(23000000000000 - 1) / 2 - 0.5) + 1)In [30]:
%time mrank_of(23000000000000)Out [30]:
CPU times: user 0 ns, sys: 0 ns, total: 0 ns Wall time: 12.9 µs
In [31]:
def offset_of(n, k):
return (n - 2 + 4 * k * (k - 1)) % (2 * k)In [32]:
offset_of(23000000000000, 2397916)Out [32]:
In [33]:
def rank_of(n):
return int(mfloor(sqrt(n - 1) / 2 - 0.5) + 1)
def offset_of(n, k):
return (n - 2 + 4 * k * (k - 1)) % (2 * k)
def row_value(k, i):
return abs(i - (k - 1)) + k
def aoc20173(n):
k = rank_of(n)
i = offset_of(n, k)
return row_value(k, i)In [34]:
aoc20173(23)Out [34]:
In [35]:
aoc20173(23000)Out [35]:
In [36]:
aoc20173(23000000000000)Out [36]:
In [37]:
%time aoc20173(23000000000000000000000000) # Fast for large values.Out [37]:
CPU times: user 0 ns, sys: 0 ns, total: 0 ns Wall time: 20 µs
In [38]:
from notebook_preamble import J, V, defineIn [39]:
define('rank_of == -- sqrt 2 / 0.5 - floor ++')In [40]:
define('offset_of == dup 2 * [dup -- 4 * * 2 + -] dip %')In [41]:
define('row_value == over -- - abs +')In [42]:
define('aoc2017.3 == dup rank_of [offset_of] dupdip swap row_value')In [43]:
J('23 aoc2017.3')2
In [44]:
J('23000 aoc2017.3')105
In [45]:
V('23000000000000 aoc2017.3') . 23000000000000 aoc2017.3
23000000000000 . aoc2017.3
23000000000000 . dup rank_of [offset_of] dupdip swap row_value
23000000000000 23000000000000 . rank_of [offset_of] dupdip swap row_value
23000000000000 23000000000000 . -- sqrt 2 / 0.5 - floor ++ [offset_of] dupdip swap row_value
23000000000000 22999999999999 . sqrt 2 / 0.5 - floor ++ [offset_of] dupdip swap row_value
23000000000000 4795831.523312615 . 2 / 0.5 - floor ++ [offset_of] dupdip swap row_value
23000000000000 4795831.523312615 2 . / 0.5 - floor ++ [offset_of] dupdip swap row_value
23000000000000 2397915.7616563076 . 0.5 - floor ++ [offset_of] dupdip swap row_value
23000000000000 2397915.7616563076 0.5 . - floor ++ [offset_of] dupdip swap row_value
23000000000000 2397915.2616563076 . floor ++ [offset_of] dupdip swap row_value
23000000000000 2397915 . ++ [offset_of] dupdip swap row_value
23000000000000 2397916 . [offset_of] dupdip swap row_value
23000000000000 2397916 [offset_of] . dupdip swap row_value
23000000000000 2397916 . offset_of 2397916 swap row_value
23000000000000 2397916 . dup 2 * [dup -- 4 * * 2 + -] dip % 2397916 swap row_value
23000000000000 2397916 2397916 . 2 * [dup -- 4 * * 2 + -] dip % 2397916 swap row_value
23000000000000 2397916 2397916 2 . * [dup -- 4 * * 2 + -] dip % 2397916 swap row_value
23000000000000 2397916 4795832 . [dup -- 4 * * 2 + -] dip % 2397916 swap row_value
23000000000000 2397916 4795832 [dup -- 4 * * 2 + -] . dip % 2397916 swap row_value
23000000000000 2397916 . dup -- 4 * * 2 + - 4795832 % 2397916 swap row_value
23000000000000 2397916 2397916 . -- 4 * * 2 + - 4795832 % 2397916 swap row_value
23000000000000 2397916 2397915 . 4 * * 2 + - 4795832 % 2397916 swap row_value
23000000000000 2397916 2397915 4 . * * 2 + - 4795832 % 2397916 swap row_value
23000000000000 2397916 9591660 . * 2 + - 4795832 % 2397916 swap row_value
23000000000000 22999994980560 . 2 + - 4795832 % 2397916 swap row_value
23000000000000 22999994980560 2 . + - 4795832 % 2397916 swap row_value
23000000000000 22999994980562 . - 4795832 % 2397916 swap row_value
5019438 . 4795832 % 2397916 swap row_value
5019438 4795832 . % 2397916 swap row_value
223606 . 2397916 swap row_value
223606 2397916 . swap row_value
2397916 223606 . row_value
2397916 223606 . over -- - abs +
2397916 223606 2397916 . -- - abs +
2397916 223606 2397915 . - abs +
2397916 -2174309 . abs +
2397916 2174309 . +
4572225 .