Skip to content

Instantly share code, notes, and snippets.

@vcaldas
Last active December 3, 2023 21:58
Show Gist options
  • Save vcaldas/69c12f7d073c58a9d49a7eb10a9c3866 to your computer and use it in GitHub Desktop.
Save vcaldas/69c12f7d073c58a9d49a7eb10a9c3866 to your computer and use it in GitHub Desktop.
day3.py
import re
with open('input.txt', 'r') as f:
lines = f.readlines()
def get_symbols(lines):
symbols = []
all_lines = " ".join(line.strip() for line in lines)
for c in all_lines:
if (c not in symbols) and (not c.isdigit()):
symbols.append(c)
symbols.remove('.')
return symbols
SYMBOLS = get_symbols(lines)
l = len(lines[0])
def get_locations(line,regex=False):
pattern = r'\b\d+\b'
return [(m.start(0), m.end(0)) for m in re.finditer(pattern, line)]
def adjusted_lines(i, lines):
current_line = '.' + lines[i] + '.'
if i == 0:
previous_line = '.'*len(current_line)
else:
previous_line = '.' + lines[i-1] + '.'
if i == len(lines)-1:
next_line = '.'*len(current_line)
else:
next_line = '.' + lines[i+1] + '.'
return previous_line, current_line, next_line
def get_surroundings(previous_line, current_line, next_line, start, finish):
left_position = start
right_position = finish + 2
upper_line = previous_line[left_position:right_position]
this_line = current_line[left_position:right_position]
lower_line = next_line[left_position:right_position]
surroundings = this_line+lower_line+upper_line
return surroundings
def get_number_to_add(i, lines, number_position, symbols=SYMBOLS):
start, finish = number_position
previous_line, current_line, next_line = adjusted_lines(i, lines)
surroundings = get_surroundings(previous_line, current_line, next_line, start, finish)
# print("Upper", upper_line, f" {i}", left_position, right_position, number_size)
# print("this ", this_line, f" {any(e in symbols for e in surroundings)}")
# print("lower", lower_line)
# print("$$$$$$$$$$$$$$$$$$$$$$$$-")
valid = any(e in symbols for e in surroundings)
if valid:
return int(lines[i][start:finish])
else:
return 0
def symbol_position(line, start, i):
position = line.find('*')
if position > -1:
position = start + position
return (i, position)
else :
return None
def all_positions(upper_line, this_line, lower_line, start, i):
positions = []
upper_pos = symbol_position(upper_line, start, i-1)
this_pos = symbol_position(this_line, start, i)
lower_pos = symbol_position(lower_line, start, i+1)
if upper_pos:
positions.append(upper_pos)
if this_pos:
positions.append(this_pos)
if lower_pos:
positions.append(lower_pos)
return positions
def get_number_to_add_with_position(i, lines, number_position, symbols=SYMBOLS):
start, finish = number_position
number = int(lines[i][start:finish])
previous_line, current_line, next_line = adjusted_lines(i, lines)
left_position = start
right_position = finish + 2
upper_line = previous_line[left_position:right_position]
this_line = current_line[left_position:right_position]
lower_line = next_line[left_position:right_position]
surroundings = this_line+lower_line+upper_line
valid = any(e in symbols for e in surroundings)
if valid:
positions = all_positions(upper_line, this_line, lower_line, start, i)
return int(lines[i][start:finish]), positions
else:
return 0, []
total = 0
for i, line in enumerate(lines):
locations = get_locations(line)
for location in locations:
number = get_number_to_add(i, lines, number_position=location)
total += int(number)
my_dict = {}
total_2 = 0
for i, line in enumerate(lines):
locations = get_locations(line)
for location in locations:
number, positions = get_number_to_add_with_position(i, lines, number_position=location, symbols=['*'])
for pos in positions:
if pos in my_dict:
my_dict[pos].append(number)
else:
my_dict[pos] = [number]
for key, value in my_dict.items():
if len(value) == 2:
total_2 += value[0]*value[1]
print("Part 1", total)
print("Part 2", total_2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment