2023 day 21, version 2.
This commit is contained in:
parent
5f8c74fd1c
commit
c496ea25c9
@ -39,8 +39,7 @@ print(f"answer 1 is {answer_1}")
|
||||
# rhombus every n steps
|
||||
#
|
||||
# we are going to find the number of cells reached for the initial rhombus, n steps
|
||||
# after and n * 2 steps after, and then interpolate the value to get a 2nd order
|
||||
# polynomial
|
||||
# after and n * 2 steps after
|
||||
#
|
||||
cycle = len(map)
|
||||
rhombus = (len(map) - 3) // 2 + 1
|
||||
@ -56,9 +55,9 @@ if logging.root.getEffectiveLevel() == logging.INFO:
|
||||
rows = [
|
||||
[
|
||||
map[i % n_rows][j % n_cols] if (i, j) not in tiles else "O"
|
||||
for j in range(-2 * cycle, 3 * cycle + 1)
|
||||
for j in range(-2 * cycle, 3 * cycle)
|
||||
]
|
||||
for i in range(-2 * cycle, 3 * cycle + 1)
|
||||
for i in range(-2 * cycle, 3 * cycle)
|
||||
]
|
||||
|
||||
for i in range(len(rows)):
|
||||
@ -71,6 +70,64 @@ if logging.root.getEffectiveLevel() == logging.INFO:
|
||||
|
||||
logging.info(f"values to fit: {values}")
|
||||
|
||||
# version 1:
|
||||
#
|
||||
# after 3 cycles, the figure looks like the following:
|
||||
#
|
||||
# I M D
|
||||
# I J A K D
|
||||
# H A F A L
|
||||
# C E A K B
|
||||
# C G B
|
||||
#
|
||||
# after 4 cycles, the figure looks like the following:
|
||||
#
|
||||
# I M D
|
||||
# I J A K D
|
||||
# I J A B A K D
|
||||
# H A B A B A L
|
||||
# C E A B A N F
|
||||
# C E A N F
|
||||
# C G F
|
||||
#
|
||||
# the 'radius' of the rhombus is the number of cycles minus 1
|
||||
#
|
||||
# the 4 'corner' (M, H, L, G) are counted once, the blocks with a corner triangle (D, I,
|
||||
# C, B) are each counted radius times, the blocks with everything but one corner (J, K,
|
||||
# E, N) are each counted radius - 1 times
|
||||
#
|
||||
# there are two versions of the whole block, A and B in the above (or odd and even),
|
||||
# depending on the number of cycles, either A or B will be in the center
|
||||
#
|
||||
|
||||
counts = [
|
||||
[
|
||||
sum(
|
||||
(i, j) in tiles
|
||||
for i in range(ci * cycle, (ci + 1) * cycle)
|
||||
for j in range(cj * cycle, (cj + 1) * cycle)
|
||||
)
|
||||
for cj in range(-2, 3)
|
||||
]
|
||||
for ci in range(-2, 3)
|
||||
]
|
||||
|
||||
radius = (26501365 - rhombus) // cycle - 1
|
||||
A = counts[2][2] if radius % 2 == 0 else counts[2][1]
|
||||
B = counts[2][2] if radius % 2 == 1 else counts[2][1]
|
||||
answer_2 = (
|
||||
(radius + 1) * A
|
||||
+ radius * B
|
||||
+ 2 * radius * (radius + 1) // 2 * A
|
||||
+ 2 * radius * (radius - 1) // 2 * B
|
||||
+ sum(counts[i][j] for i, j in ((0, 2), (-1, 2), (2, 0), (2, -1)))
|
||||
+ sum(counts[i][j] for i, j in ((0, 1), (0, 3), (-1, 1), (-1, 3))) * (radius + 1)
|
||||
+ sum(counts[i][j] for i, j in ((1, 1), (1, 3), (-2, 1), (-2, 3))) * radius
|
||||
)
|
||||
print(f"answer 2 (v1) is {answer_2}")
|
||||
|
||||
# version 2: fitting a polynomial
|
||||
#
|
||||
# the value we are interested in (26501365) can be written as R + K * C where R is the
|
||||
# step at which we find the first rhombus, and K the repeat step, so instead of fitting
|
||||
# for X values (R, R + K, R + 2 K), we are going to fit for (0, 1, 2), giving us much
|
||||
@ -89,4 +146,4 @@ a, b, c = (y1 + y3) // 2 - y2, 2 * y2 - (3 * y1 + y3) // 2, y1
|
||||
|
||||
n = (26501365 - rhombus) // cycle
|
||||
answer_2 = a * n * n + b * n + c
|
||||
print(f"answer 2 is {answer_2}")
|
||||
print(f"answer 2 (v2) is {answer_2}")
|
||||
|
Loading…
Reference in New Issue
Block a user