33 KiB
33 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)), end=' ')3 2 1 0 1 2 3 4
In [4]:
for n in range(2 * k):
print(abs(n - (k - 1)) + k, end=' ')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), end=' ')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]:
\displaystyle 4 k \left(k + 1\right) + 2In [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 27.8 ms, sys: 5 µs, total: 27.8 ms Wall time: 27.3 ms
\displaystyle 2397916In [20]:
%time rank_and_offset(23000000000000)Out [20]:
CPU times: user 216 ms, sys: 89 µs, total: 216 ms Wall time: 215 ms
\displaystyle \left( 2397916, \ 223606\right)In [21]:
y = symbols('y')In [22]:
g, f = solve(E - y, k)In [23]:
gOut [23]:
\displaystyle - \frac{\sqrt{y - 1}}{2} - \frac{1}{2}In [24]:
fOut [24]:
\displaystyle \frac{\sqrt{y - 1}}{2} - \frac{1}{2}In [25]:
floor(f) + 1Out [25]:
\displaystyle \left\lfloor{\frac{\sqrt{y - 1}}{2} - \frac{1}{2}}\right\rfloor + 1In [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 60 µs, sys: 4 µs, total: 64 µs Wall time: 67 µs
\displaystyle 2397916In [29]:
from math import floor as mfloor, sqrt
def mrank_of(n):
return int(mfloor(sqrt(n - 1) / 2 - 0.5) + 1)In [30]:
%time mrank_of(23000000000000)Out [30]:
CPU times: user 7 µs, sys: 1 µs, total: 8 µs Wall time: 10 µs
\displaystyle 2397916In [31]:
def offset_of(n, k):
return (n - 2 + 4 * k * (k - 1)) % (2 * k)In [32]:
offset_of(23000000000000, 2397916)Out [32]:
\displaystyle 223606In [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]:
\displaystyle 2In [35]:
aoc20173(23000)Out [35]:
\displaystyle 105In [36]:
aoc20173(23000000000000)Out [36]:
\displaystyle 4572225In [37]:
%time aoc20173(23000000000000000000000000) # Fast for large values.Out [37]:
CPU times: user 22 µs, sys: 2 µs, total: 24 µs Wall time: 26.7 µs
\displaystyle 2690062495969In [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 •