2022-12-09 16:43:00 +00:00
|
|
|
from pprint import pprint as pp
|
2022-12-09 23:03:06 +00:00
|
|
|
|
|
|
|
from anim import Animate
|
2022-12-09 16:43:00 +00:00
|
|
|
import shared
|
|
|
|
import matrix
|
|
|
|
|
2022-12-09 23:03:06 +00:00
|
|
|
MATRIX_SIZE = 400
|
2022-12-12 07:41:14 +00:00
|
|
|
ATRIX_SIZE = 40 # sample
|
2022-12-09 16:43:00 +00:00
|
|
|
HALF = MATRIX_SIZE // 2
|
|
|
|
|
2022-12-12 07:41:14 +00:00
|
|
|
H = [HALF, HALF]
|
|
|
|
T = [HALF, HALF]
|
2022-12-09 16:43:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
# returns (x,y) - so remember to take dx,dy lower
|
|
|
|
DIRS = {
|
2022-12-12 07:41:14 +00:00
|
|
|
"U": matrix.M_U, # (0, -1)
|
|
|
|
"D": matrix.M_D,
|
|
|
|
"L": matrix.M_L,
|
|
|
|
"R": matrix.M_R,
|
|
|
|
"UR": matrix.M_UR, # (+1, -1)
|
|
|
|
"DR": matrix.M_DR,
|
|
|
|
"UL": matrix.M_UL,
|
|
|
|
"DL": matrix.M_DL,
|
2022-12-09 16:43:00 +00:00
|
|
|
}
|
|
|
|
|
2022-12-12 07:41:14 +00:00
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
def part1(steps):
|
2022-12-12 07:41:14 +00:00
|
|
|
field = matrix.matrix_of_size(MATRIX_SIZE, MATRIX_SIZE)
|
2022-12-09 23:03:06 +00:00
|
|
|
anim = Animate(field, day="09")
|
2022-12-09 16:43:00 +00:00
|
|
|
|
|
|
|
for direction, amount in steps:
|
|
|
|
# move HEAD
|
|
|
|
amount = int(amount)
|
|
|
|
for x in range(amount):
|
|
|
|
|
2022-12-12 07:41:14 +00:00
|
|
|
dx, dy = DIRS[direction]
|
|
|
|
H[0] += dy
|
2022-12-09 16:43:00 +00:00
|
|
|
H[1] += dx
|
2022-12-12 07:41:14 +00:00
|
|
|
HY, bX = H
|
2022-12-09 16:43:00 +00:00
|
|
|
# head is in new position
|
2022-12-12 07:41:14 +00:00
|
|
|
kY, kX = T
|
|
|
|
field[kY][kX] = 1 # 'T'
|
2022-12-09 16:43:00 +00:00
|
|
|
|
|
|
|
# Check if same
|
|
|
|
if kY == HY and kX == bX:
|
|
|
|
continue
|
|
|
|
touching = False
|
|
|
|
for _, d in DIRS.items():
|
2022-12-12 07:41:14 +00:00
|
|
|
dx, dy = d
|
|
|
|
t_y, t_x = H[0] + dy, H[1] + dx
|
2022-12-09 16:43:00 +00:00
|
|
|
if kY == t_y and kX == t_x:
|
|
|
|
touching = True
|
|
|
|
break
|
|
|
|
if touching:
|
|
|
|
continue
|
|
|
|
|
|
|
|
# assume the same row/column, no movement needed
|
|
|
|
tY = 0
|
|
|
|
tX = 0
|
2022-12-12 07:41:14 +00:00
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
# if Head X is less than Tail X, move Tail X 1 left
|
|
|
|
if bX < kX:
|
|
|
|
tX = -1
|
|
|
|
# if Head X is greater than Tail X, move Tail X 1 left
|
|
|
|
elif bX > kX:
|
|
|
|
tX = 1
|
2022-12-12 07:41:14 +00:00
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
# if Head Y is less than Tail Y, move Tail Y 1 up
|
|
|
|
if HY < kY:
|
|
|
|
tY = -1
|
|
|
|
# if Head Y is greater than Tail Y, move Tail Y 1 down
|
|
|
|
elif HY > kY:
|
|
|
|
tY = 1
|
2022-12-12 07:41:14 +00:00
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
T[0] += tY
|
|
|
|
T[1] += tX
|
2022-12-09 23:03:06 +00:00
|
|
|
anim.add_frame(field)
|
2022-12-09 16:43:00 +00:00
|
|
|
|
2022-12-12 07:41:14 +00:00
|
|
|
field[T[0]][T[1]] = 1 # mark visited tails
|
2022-12-09 16:43:00 +00:00
|
|
|
print(matrix.sum_matrix(field))
|
2022-12-09 23:03:06 +00:00
|
|
|
anim.animate()
|
2022-12-09 16:43:00 +00:00
|
|
|
|
2022-12-12 07:41:14 +00:00
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
def part2(steps):
|
2022-12-12 07:41:14 +00:00
|
|
|
field = matrix.matrix_of_size(MATRIX_SIZE, MATRIX_SIZE)
|
2022-12-09 23:03:06 +00:00
|
|
|
anim = Animate(field, day="09")
|
2022-12-12 07:41:14 +00:00
|
|
|
S = [
|
|
|
|
[HALF, HALF],
|
|
|
|
] # HEAD ONLY
|
2022-12-09 23:03:06 +00:00
|
|
|
_cur_frame = 0
|
2022-12-09 16:43:00 +00:00
|
|
|
for x in range(9):
|
2022-12-12 07:41:14 +00:00
|
|
|
S.append([HALF, HALF])
|
2022-12-09 16:43:00 +00:00
|
|
|
|
|
|
|
for direction, amount in steps:
|
|
|
|
# move HEAD
|
|
|
|
amount = int(amount)
|
|
|
|
for x in range(amount):
|
2022-12-12 07:41:14 +00:00
|
|
|
HEAD_dx, HEAD_dy = DIRS[direction]
|
|
|
|
S[0][0] += HEAD_dy
|
2022-12-09 16:43:00 +00:00
|
|
|
S[0][1] += HEAD_dx
|
2022-12-12 07:41:14 +00:00
|
|
|
# print(HEAD_dy,HEAD_dx, S)
|
2022-12-09 16:43:00 +00:00
|
|
|
# HEAD MOVED one step
|
2022-12-12 07:41:14 +00:00
|
|
|
|
|
|
|
for knot_idx, _ in enumerate(S):
|
2022-12-09 16:43:00 +00:00
|
|
|
if knot_idx == 0:
|
|
|
|
# Skip Head
|
|
|
|
continue
|
|
|
|
knot = S[knot_idx]
|
2022-12-12 07:41:14 +00:00
|
|
|
kY, kX = knot
|
2022-12-09 16:43:00 +00:00
|
|
|
|
2022-12-12 07:41:14 +00:00
|
|
|
bY, bX = S[knot_idx - 1]
|
2022-12-09 16:43:00 +00:00
|
|
|
|
2022-12-12 07:41:14 +00:00
|
|
|
# Check if same
|
2022-12-09 16:43:00 +00:00
|
|
|
if kY == bY and kX == bX:
|
|
|
|
continue
|
|
|
|
|
|
|
|
touching = False
|
|
|
|
for _, d in DIRS.items():
|
2022-12-12 07:41:14 +00:00
|
|
|
dx, dy = d
|
|
|
|
t_y, t_x = S[knot_idx - 1][0] + dy, S[knot_idx - 1][1] + dx
|
2022-12-09 16:43:00 +00:00
|
|
|
if kY == t_y and kX == t_x:
|
|
|
|
touching = True
|
|
|
|
break
|
|
|
|
if touching:
|
|
|
|
continue
|
|
|
|
|
|
|
|
# assume the same row/column, no movement needed
|
2022-12-12 07:41:14 +00:00
|
|
|
tY, tX = 0, 0
|
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
# if Head X is less than Tail X, move Tail X 1 left
|
|
|
|
if bX < kX:
|
|
|
|
tX = -1
|
|
|
|
# if Head X is greater than Tail X, move Tail X 1 left
|
|
|
|
elif bX > kX:
|
|
|
|
tX = 1
|
2022-12-12 07:41:14 +00:00
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
# if Head Y is less than Tail Y, move Tail Y 1 up
|
|
|
|
if bY < kY:
|
|
|
|
tY = -1
|
|
|
|
# if Head Y is greater than Tail Y, move Tail Y 1 down
|
|
|
|
elif bY > kY:
|
|
|
|
tY = 1
|
2022-12-12 07:41:14 +00:00
|
|
|
|
2022-12-09 16:43:00 +00:00
|
|
|
S[knot_idx][0] += tY
|
|
|
|
S[knot_idx][1] += tX
|
2022-12-09 23:03:06 +00:00
|
|
|
if _cur_frame % 25 == 0:
|
|
|
|
anim.add_frame(field)
|
|
|
|
_cur_frame += 1
|
2022-12-12 07:41:14 +00:00
|
|
|
field[S[-1][0]][S[-1][1]] = 1 # mark visited tails
|
2022-12-09 16:43:00 +00:00
|
|
|
print(matrix.sum_matrix(field))
|
2022-12-09 23:03:06 +00:00
|
|
|
anim.animate()
|
2022-12-09 16:43:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
rows = [x.split(" ") for x in shared.load_rows(9)]
|
2022-12-12 07:41:14 +00:00
|
|
|
# part1(rows)
|
2022-12-09 16:43:00 +00:00
|
|
|
part2(rows)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|