AdventOfCode/2024/14/solution.py

189 lines
5.7 KiB
Python

#!/bin/python3
import sys,time,re
from pprint import pprint
from termcolor import colored
sys.path.insert(0, '../../')
from fred import list2int,get_re,lprint,loadFile,addTuples,grid_valid,bfs,dfs,flood_fill
start_time = time.time()
input_f = 'test'
size_r = 7
size_c = 11
input_f = 'input'
size_r = 103
size_c = 101
grid = [['.']*size_c]*size_r
def nprint(grid,pos=None,x=None,positions:list=None):
for r in range(size_r):
for c in range(size_c):
if (c,r) == pos and positions is None:
print(x,end='')
elif positions is not None:
if (c,r) in positions:
print(x,end='')
else:
print(colored(grid[r][c],'red'),end='')
else:
print(colored(grid[r][c],'red'),end='')
print()
#########################################
# #
# Part 1 #
# #
#########################################
def part1():
instructions = loadFile(input_f)
for idx,inst in enumerate(instructions):
match = get_re(r"^p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)",inst)
instructions[idx] = [(int(match.group(1)),int(match.group(2))),(int(match.group(3)),int(match.group(4)))]
coordinates = {}
initial = {}
for idx,inst in enumerate(instructions):
#inst = [(2,4),(2,-3)]
#print(inst)
#print('Initial state')
pos = inst[0]
vel = inst[1]
if pos not in initial:
initial[pos] = 0
initial[pos] += 1
#nprint(grid,pos,'1')
length = 100
for i in range (0,length):
pos = addTuples(pos,vel)
#print('After',i+1,'seconds')
if pos[0] < 0:
pos = (pos[0]+size_c,pos[1])
if pos[0] >= size_c:
pos = (pos[0]-size_c,pos[1])
if pos[1] < 0:
pos = (pos[0],pos[1]+size_r)
if pos[1] >= size_r:
pos = (pos[0],pos[1]-size_r)
#print('Position inside grid: ', grid_valid(pos[1],pos[0],grid))
#nprint(grid,pos,'1')
#print(pos)
#input()
if pos not in coordinates:
coordinates[pos] = 0
coordinates[pos] += 1
#print('End State')
#nprint(grid,pos,'1')
#input()
#pprint(coordinates)
# print(instructions)
# print()
# print(initial)
# print()
# for r in range(size_r):
# for c in range(size_c):
# if (c,r) in initial.keys():
# print(initial[(c,r)],end='')
# else:
# print(grid[r][c],end='')
# print()
# print('----------------------')
# print(coordinates)
# for r in range(size_r):
# for c in range(size_c):
# if (c,r) in coordinates.keys():
# print(coordinates[(c,r)],end='')
# else:
# print(grid[r][c],end='')
# print()
center = (int((size_r-1)/2),int((size_c-1)/2))
TL = 0 #top left
BL = 0 #bottom left
TR = 0 #top right
BR = 0 #bottom right
for v in coordinates:
if v[0] < center[1] and v[1] < center[0]:
#print(v,'top left',coordinates[v])
TL += coordinates[v]
if v[0] > center[1] and v[1] < center[0]:
#print(v,'top right',coordinates[v])
TR += coordinates[v]
if v[0] > center[1] and v[1] > center[0]:
#print(v,'bot right',coordinates[v])
BR += coordinates[v]
if v[0] < center[1] and v[1] > center[0]:
#print(v,'bot left',coordinates[v])
BL += coordinates[v]
#print(center)
return TL*TR*BR*BL
start_time = time.time()
print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')
#########################################
# #
# Part 2 #
# #
#########################################
def part2():
instructions = loadFile(input_f)
cords = []
for idx,inst in enumerate(instructions):
match = get_re(r"^p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)",inst)
instructions[idx] = [(int(match.group(1)),int(match.group(2))),(int(match.group(3)),int(match.group(4)))]
cords.append(instructions[idx][0])
count = 0
def generate():
coordinates = {}
for idx,inst in enumerate(instructions):
pos = inst[0]
vel = inst[1]
pos = addTuples(pos,vel)
if pos[0] < 0:
pos = (pos[0]+size_c,pos[1])
if pos[0] >= size_c:
pos = (pos[0]-size_c,pos[1])
if pos[1] < 0:
pos = (pos[0],pos[1]+size_r)
if pos[1] >= size_r:
pos = (pos[0],pos[1]-size_r)
instructions[idx] = [pos,vel]
cords[idx] = pos
if pos not in coordinates:
coordinates[pos] = 0
coordinates[pos] += 1
return coordinates
while True:
coordinates = generate()
count += 1
visited = []
if 2 not in coordinates.values():
for pos in coordinates.keys():
if pos not in visited:
t_visited = flood_fill(coordinates.keys(),pos)
visited += t_visited
if len(t_visited) > 10:
nprint(grid,x='*',positions=coordinates)
return count
start_time = time.time()
print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms')