fallshare
: fallshare
fallshare |
Advent of Code 2021
I decided to go with python for another year since I did not do much with it since the last AoC. Might also have a look at go or rust. We will see :)
Run the solution with python solution.py
print("hello world")
Advent of Code 2021
Using Gitpod + VSCode Remote plugin. Nice developer experience.
with open('input.txt') as input_file:
input = []
for line in input_file:
input.append(int(line.strip('\n')))
assert int(input[0]) == 195
def getDepthIncrement_Star1(input):
previousDepth = input[0]
increment = 0
for depth in input:
if depth > previousDepth:
increment += 1
previousDepth = depth
return increment
def getDepthIncrementSlidingWindow_Star2(input):
previousDepthWindow = input[0] + input[1] + input [2]
increment = 0
for i in range(1, len(input) - 2 , 1):
currentDepthWindow = input[i] + input[i+1] + input [i+2]
if currentDepthWindow > previousDepthWindow:
increment += 1
previousDepthWindow = currentDepthWindow
print(str(i))
return increment
print("Star 1: Depth increase is " + str(getDepthIncrement_Star1(input)))
print("Star 1: Depth increase is " + str(getDepthIncrementSlidingWindow_Star2(input)))
Advent of Code 2021
Not much to say. Finding proper names for variables is hard.
class Submarine:
depth = 0
horizontal_pos = 0
def down(self, depth):
self.depth += depth
def up(self, depth):
self.depth -= depth
def forward(self, distance):
self.horizontal_pos += distance
def get_depth(self):
return self.depth
def get_horizontal_pos(self):
return self.horizontal_pos
def dive(self, input):
with open(input, "r") as f:
for line in f:
(direction, value) = line.split(" ")
value = int(value)
if direction == "down":
self.down(value)
elif direction == "up":
self.up(value)
elif direction == "forward":
self.forward(value)
else:
raise Exception(f"Unknown direction!")
def get_Star1():
submarine = Submarine()
submarine.dive("input.txt")
result = submarine.get_depth() * submarine.get_horizontal_pos()
print(f"Result for first star: {result}")
class Aiming_Submarine:
depth = 0
horizontal_pos = 0
aim = 0
def down(self, depth):
self.aim += depth
def up(self, depth):
self.aim -= depth
def forward(self, distance):
self.horizontal_pos += distance
self.depth += distance * self.aim
def get_depth(self):
return self.depth
def get_horizontal_pos(self):
return self.horizontal_pos
def dive(self, input):
with open(input, "r") as f:
for line in f:
(direction, value) = line.split(" ")
value = int(value)
if direction == "down":
self.down(value)
elif direction == "up":
self.up(value)
elif direction == "forward":
self.forward(value)
else:
raise Exception(f"Unknown direction!")
def get_Star2():
submarine = Aiming_Submarine()
submarine.dive("input.txt")
result = submarine.get_depth() * submarine.get_horizontal_pos()
print(f"Result for second star: {result}")
get_Star1()
get_Star2()
Advent of Code 2021
Groundhog day. Pass by value vs. pass by reference. === Start 2 Today I learned that Python is rounding to the next even number..
import math
input = list()
with open("input.txt", "r") as f:
for line in f:
current_line = list(map(int, line.rstrip() ))
input.append(current_line)
def list_to_int(input_list):
binary_list = input_list[:]
number = 0
binary_list.reverse()
for i in range(len(binary_list)):
number += binary_list[i] * (2 ** i)
return number
msb = list()
lsb = list()
for column in range(len(input[0])):
one_amount = 0
for row in range(len(input)):
if input[row][column] == 1:
one_amount += 1
if one_amount >= round(len(input) / 2):
msb.append(1)
lsb.append(0)
else:
msb.append(0)
lsb.append(1)
print("Solution Star 1:")
print(f"Gamma rate: {list_to_int(msb)}")
print(f"Epsilon rate: {list_to_int(lsb)}")
print(f"Power consumption: {list_to_int(msb) * list_to_int(lsb)}")
print("---------------------------")
print("Solution Star 2:")
remaining_numbers = input.copy()
for column in range(len(input[0])):
#determine msb of renaming numbers at position column
most_commonvalue = 0
least_commonvalue = 0
one_amount = 0
for row in range(len(remaining_numbers)):
if remaining_numbers[row][column] == 1:
one_amount += 1
if one_amount >= round(len(remaining_numbers) / 2):
most_commonvalue = 1
least_commonvalue = 0
else:
most_commonvalue = 0
least_commonvalue = 1
#add numbers that match bit criteria to remaining numbers
matching_numbers = list()
for row in range(len(remaining_numbers)):
if remaining_numbers[row][column] == most_commonvalue:
matching_numbers.append(remaining_numbers[row])
remaining_numbers = matching_numbers
oxygen_gen_rate = list_to_int(remaining_numbers[0])
remaining_numbers = input.copy()
for column in range(len(input[0])):
#determine msb of renaming numbers at position column
most_commonvalue = 0
least_commonvalue = 0
one_amount = 0
for row in range(len(remaining_numbers)):
if remaining_numbers[row][column] == 1:
one_amount += 1
print(f"{one_amount} - {math.ceil(len(remaining_numbers) / 2)}")
if one_amount >= math.ceil(len(remaining_numbers) / 2):
most_commonvalue = 1
least_commonvalue = 0
else:
most_commonvalue = 0
least_commonvalue = 1
print(remaining_numbers)
print(least_commonvalue)
#add numbers that match bit criteria to remaining numbers
matching_numbers = list()
for row in range(len(remaining_numbers)):
if remaining_numbers[row][column] == least_commonvalue:
matching_numbers.append(remaining_numbers[row])
remaining_numbers = matching_numbers
if len(remaining_numbers) == 1:
break
scrubbing_rate = list_to_int(remaining_numbers[0])
print(f"Oxygen generator rate: {oxygen_gen_rate}")
print(f"CO2 scrubber rate: {scrubbing_rate}")
print(f"Life support rate: {oxygen_gen_rate * scrubbing_rate}")
Advent of Code 2021
First time using numpy. === Start 2 Heck this took a lot of time.
import re
import numpy as np
# read in input
# line ranmdom numbers
# blank
# 5 zeilen a 5 nummern
#blank
# 5 zeile
#am ende kein blank mehr
# file einlesen in array?
# line 0 -> random numbers zerlenegne
# blank überspringen
# 5 zeilen ienlsen
# while current pos + 5
with open('input.txt') as file:
lines = file.readlines()
lines = [line.strip() for line in lines]
current_line = 0
random_numbers = lines[current_line].split(',')
random_numbers = list(map(int, random_numbers))
current_line += 2
bingo_boards = list()
while current_line + 5 <= len(lines):
bingo_board = np.zeros((5,5), dtype=int)
for x in range(5):
bingo_line = re.split(r'\s+',lines[current_line])
bingo_line = list(map(int, bingo_line))
bingo_board[x] = np.asarray(bingo_line, dtype=np.int8)
# bingo_board.append(bingo_line)
current_line += 1
bingo_boards.append(bingo_board)
# skip over whitespace between bingo boards
current_line += 1
#setup hit boxes
hit_boxes = list()
for board in bingo_boards:
hit_boxes.append( np.zeros((5, 5),np.int8))
runs = 0
bingo = False
drawn_numbers = []
winner_board = 0
for number in random_numbers:
if bingo:
break
drawn_numbers.append(number)
runs += 1
for board in range(len(bingo_boards)):
for y in range(5):
for x in range (5):
if bingo_boards[board][y][x] == number:
hit_boxes[board][y][x] = 1
# print(f"{x} - {y}")
#check if any row or column in correunt bingo board is a bingo
if (np.sum(hit_boxes[board], axis=0)[x] == 5) or (np.sum(hit_boxes[board], axis=1)[y] == 5):
print(f"Bingo found in board: {board} after {runs} runs with number {number}")
bingo = True
winner_board = board
print(f"Drawn numbers: {np.asarray(drawn_numbers)}")
print(f"Bingo numbers {np.asarray(bingo_boards[winner_board]).flatten()}")
remaining_numbers = np.setdiff1d(np.asarray(bingo_boards[winner_board]).flatten(),np.asarray(drawn_numbers))
print(f"Remaining numbers: {remaining_numbers}")
remaining_sum = np.sum(remaining_numbers)
print(f"Remaining sum: {remaining_sum}")
print(f"Solution Star 1: {remaining_sum} * {drawn_numbers[-1]}= {remaining_sum * drawn_numbers[-1]}")
#setup hit boxes
hit_boxes = list()
for board in bingo_boards:
hit_boxes.append( np.zeros((5, 5),np.int8))
last_bingo = False
unfinished_boards = list(range(len(bingo_boards)))
drawn_numbers = []
for number in random_numbers:
if last_bingo:
break
drawn_numbers.append(number)
for board in unfinished_boards:
remaining_bingo_boards = unfinished_boards.copy()
board_has_bingo = False
for y in range(5):
if board_has_bingo:
break
for x in range (5):
if board_has_bingo:
break
if bingo_boards[board][y][x] == number:
hit_boxes[board][y][x] = 1
if (np.sum(hit_boxes[board], axis=0)[x] == 5) or (np.sum(hit_boxes[board], axis=1)[y] == 5):
if len(unfinished_boards) == 1:
print(f"Last Bingo found in {unfinished_boards[0]} in after {len(drawn_numbers)} runs with number {number}")
board_has_bingo = True
last_bingo = True
else:
remaining_bingo_boards.remove(board)
board_has_bingo = True
unfinished_boards = remaining_bingo_boards
print(f"Drawn numbers: {np.asarray(drawn_numbers)}")
print(f"Bingo numbers {np.asarray(bingo_boards[unfinished_boards[0]]).flatten()}")
remaining_numbers = np.setdiff1d(np.asarray(bingo_boards[unfinished_boards[0]]).flatten(),np.asarray(drawn_numbers))
print(f"Remaining numbers: {remaining_numbers}")
remaining_sum = np.sum(remaining_numbers)
print(f"Remaining sum: {remaining_sum}")
print(f"Solution Star 2: {remaining_sum} * {drawn_numbers[-1]}= {remaining_sum * drawn_numbers[-1]}")
Advent of Code 2021
Day 5 done. Having not that much time. Hence just hacking a little bit :)
import numpy as np
file1 = open('input.txt', 'r')
lines = list()
for line in file1:
string_coordinates = line.rstrip().replace(" -> ", ",").split(",")
coordinates = list(map(int, string_coordinates))
lines.append(coordinates)
biggest_x = 0
for i in range(len(lines)):
if lines[i][0] > biggest_x:
biggest_x = lines[i][0]
if lines[i][2] > biggest_x:
biggest_x = lines[i][2]
print("Biggest X: {}".format( biggest_x))
biggest_y = 0
for i in range(len(lines)):
if lines[i][1] > biggest_y:
biggest_y = lines[i][1]
if lines[i][3] > biggest_y:
biggest_y = lines[i][3]
print("Biggest Y: {}".format( biggest_y))
vent_map = np.zeros((biggest_x + 1,biggest_y + 1), dtype=int)
for i in range(len(lines)):
x_start = lines[i][0]
x_end = lines[i][2]
y_start = lines[i][1]
y_end = lines[i][3]
if x_start == x_end : #horizontal line?
if y_start > y_end:
y_start, y_end = y_end, y_start
for y in range(y_start, y_end + 1):
vent_map[y][x_start] += 1
elif y_start == y_end: #vertical line?
if x_start > x_end:
x_start, x_end = x_end, x_start
for x in range(x_start, x_end + 1):
vent_map[y_start][x] += 1
count = np.count_nonzero(vent_map > 1)
print("Solution Start 1:")
print(f"Points where at least two lines cross: {count}")
# Star 2
vent_map = np.zeros((biggest_x + 1,biggest_y + 1), dtype=int)
for i in range(len(lines)):
x_start = lines[i][0]
x_end = lines[i][2]
y_start = lines[i][1]
y_end = lines[i][3]
if x_start == x_end : #horizontal line?
if y_start > y_end:
y_start, y_end = y_end, y_start
for y in range(y_start, y_end + 1):
vent_map[y][x_start] += 1
elif y_start == y_end: #vertical line?
if x_start > x_end:
x_start, x_end = x_end, x_start
for x in range(x_start, x_end + 1):
vent_map[y_start][x] += 1
else:
if x_start > x_end:
x_start, x_end = x_end, x_start
y_start, y_end = y_end, y_start
y_direction = 1
if y_start > y_end:
y_direction = -1
y = y_start
for x in range(x_start, x_end + 1):
vent_map[y][x] += 1
y += y_direction
count = np.count_nonzero(vent_map > 1)
print("Solution Start 2:")
print(f"Points where at least two lines cross: {count}")
Advent of Code 2021
Easy peasy.
This is a very cool task. The easy peasy implentation was sufficient efficient for Star 1. But now it is not anymore due to exponential growth. Hence a nother approach is required. It is especially nice that the first part is designed to lead you to a list based implentation.
file1 = open('input.txt', 'r')
string_list = file1.readline().rstrip().split(",")
lantern_fishes = list(map(int, string_list))
max_days = 80
for day in range(0, max_days):
for fish in range(len(lantern_fishes)):
lantern_fishes[fish] -= 1
if lantern_fishes[fish] == -1:
lantern_fishes[fish] = 6
lantern_fishes.append(8)
print("Star 1")
print(f"After 80 days {len(lantern_fishes)} fishes are found")
#Star 2
# Exponential growth
file1 = open('input.txt', 'r')
string_list = file1.readline().rstrip().split(",")
lantern_fishes = list(map(int, string_list))
fish_counter = [0] * 9
for fish in range(len(lantern_fishes)):
fish_age = lantern_fishes[fish]
fish_counter[fish_age] += 1
print(fish_counter)
max_days = 256
for day in range(0, max_days):
new_fish_counter = [0] * 9
for age in reversed(range(9)):
if age == 0:
new_fish_counter[8] = fish_counter[age]
new_fish_counter[6] += fish_counter[age]
else:
new_fish_counter[age - 1] = fish_counter[age]
fish_counter = new_fish_counter
print("Star 2")
print(f"After {max_days} days {sum(fish_counter)} fishes are found")
Advent of Code 2021
Done. === Star 2 Took me some time to remember the formula to calculate the fuel consumption.
file1 = open('input.txt', 'r')
string_list = file1.readline().rstrip().split(",")
crab_positions = list(map(int, string_list))
closest_crab = min(crab_positions)
furthest_crab = max(crab_positions)
max_distance = furthest_crab - closest_crab
print(f"Closest crab: {closest_crab}")
print(f"Furthest crab: {furthest_crab}")
print(f"Crab distance: {max_distance}")
min_distance = max_distance * len(crab_positions)
distance_sum = 0
best_position = max_distance
for current_position in range(closest_crab, furthest_crab):
for crab_position in crab_positions:
distance_sum += abs(current_position - crab_position)
if distance_sum < min_distance:
min_distance = distance_sum
best_position = current_position
distance_sum = 0
print("Start 1")
print(f"Best position is: {best_position}")
print(f"Fuel to spend: {min_distance}")
def distance_to_fuel_star2(distance):
return (distance * (distance + 1)) / 2
min_distance = max_distance * len(crab_positions) * len(crab_positions)
distance_sum = 0
best_position = max_distance
for current_position in range(closest_crab, furthest_crab):
for crab_position in crab_positions:
distance_sum += distance_to_fuel_star2(abs(current_position - crab_position))
if distance_sum < min_distance:
min_distance = distance_sum
best_position = current_position
distance_sum = 0
print("Start 2")
print(f"Best position is: {best_position}")
print(f"Fuel to spend: {min_distance}")
Advent of Code 2021
file1 = open('input.txt', 'r')
# Star 1
unique_digits = 0
for line in file1:
output_part = line.split("|")[1]
output_digits = output_part.split()
for digit in output_digits:
segment_cnt = len(digit)
if (segment_cnt == 2) or (segment_cnt == 4) or (segment_cnt == 3) or (segment_cnt == 7):
unique_digits += 1
print(f"Star 1: {unique_digits} unique digits")
# Star 2
file1 = open('input.txt', 'r')
output_value_sum = 0
for line in file1:
signals = line.split("|")
signal_pattern = signals[0].split()
output_pattern = signals[1].split()
digits = dict()
# Find Digit 1
for signal in signal_pattern:
if len(signal) == 2:
digits[1] = set(signal)
break
# Find Digit 4
for signal in signal_pattern:
if len(signal) == 4:
digits[4] = set(signal)
break
# Find Digit 7
for signal in signal_pattern:
if len(signal) == 3:
digits[7] = set(signal)
break
# Find Digit 8
for signal in signal_pattern:
if len(signal) == 7:
digits[8] = set(signal)
break
# Find digit 5
overlap = digits[4] - digits[1]
for signal in signal_pattern:
if (len(signal) == 5) and (overlap.issubset(set(signal)) ):
digits[5] = set(signal)
# Find digit 2
overlap = digits[8] - digits[5] # 2 ist the oposit of 5. So 2 must contain remaining elemnts that are not in 5
for signal in signal_pattern:
if (len(signal) == 5) and (overlap.issubset(set(signal)) ):
digits[2] = set(signal)
# Find digit 3
for signal in signal_pattern:
if (len(signal) == 5) and not (set(signal).issubset(digits[2])) and not (set(signal).issubset(digits[5])):
digits[3] = set(signal)
# Find digit 9
for signal in signal_pattern:
if (len(signal) == 6) and (digits[4].issubset((set(signal)))): # 4 fits only into 9 (of the digits with 6 characters)
digits[9] = set(signal)
# Find digit 6
for signal in signal_pattern:
if (len(signal) == 6) and not(digits[1].issubset((set(signal)))):
digits[6] = set(signal)
# Find digit 0
for signal in signal_pattern:
if (len(signal) == 6) and not (set(signal).issubset(digits[6])) and not (set(signal).issubset(digits[9])):
digits[0] = set(signal)
number_string = ""
for digit in output_pattern:
digit_string = list(digits.keys())[list(digits.values()).index(set(digit))]
number_string = number_string + str(digit_string)
output_value_sum += int(number_string)
print(f"Star 2: Total sum is {output_value_sum}")
Advent of Code 2021
file1 = open('input.txt', 'r')
import sys
print(sys.getrecursionlimit())
sys.setrecursionlimit(10000)
heat_map = list()
for line in file1:
x_coordinates = list(line.strip())
heat_map.append(list(map(int, x_coordinates)))
risk_level_sum = 0
low_points = list()
for y in range(len(heat_map)):
for x in range(len(heat_map[0])):
#print(f"x:{x} , y:{y}, value: {heat_map[y][x]}")
smallest_number = True
#hoch
if (x > 0) and (heat_map[y][x] >= heat_map[y][x - 1]):
smallest_number = False
#runter
if (x < (len(heat_map[0])-1)) and (heat_map[y][x] >= heat_map[y][x + 1]):
smallest_number = False
#links
if (y > 0) and (heat_map[y][x] >= heat_map[y - 1][x]):
smallest_number = False
#rechts
if (y < (len(heat_map)-1)) and (heat_map[y][x] >= heat_map[y + 1][x]):
smallest_number = False
if smallest_number:
print(f"Low point found at: {x}-{y}")
risk_level_sum += (heat_map[y][x] + 1)
low_points.append((x,y))
print(f"Star 1: Risk level sum: {risk_level_sum}")
def basin_size(x, y, heat_map, visited_locations):
locations = {(x, y)}
visited_locations.update({(x,y)})
#links
if (x > 0) and (heat_map[y][x] <= heat_map[y][x - 1]) and (heat_map[y][x - 1] != 9) and not {(x-1,y)}.issubset(visited_locations):
locations.update(basin_size((x - 1), y, heat_map, visited_locations))
#rechts
if (x < (len(heat_map[0])-1)) and (heat_map[y][x] <= heat_map[y][x + 1]) and (heat_map[y][x + 1] != 9)and not {(x+1,y)}.issubset(visited_locations):
locations.update(basin_size((x + 1), y, heat_map, visited_locations))
#hoch
if (y > 0) and (heat_map[y][x] <= heat_map[y - 1][x]) and ( heat_map[y - 1][x] != 9) and not {(x,y-1)}.issubset(visited_locations):
locations.update(basin_size(x, (y - 1), heat_map, visited_locations))
#runter
if (y < (len(heat_map)-1)) and (heat_map[y][x] <= heat_map[y + 1][x]) and (heat_map[y + 1][x] != 9) and not {(x,y+1)}.issubset(visited_locations):
locations.update(basin_size(x, (y + 1), heat_map, visited_locations))
return locations
basin_sizes = list()
for low_point in low_points:
visited_locations = set()
basin_size_cnt = len(basin_size(low_point[0],low_point[1],heat_map, visited_locations))
basin_sizes.append(basin_size_cnt)
basin_sizes.sort()
largest_basins = basin_sizes[-3:]
basin_product = 1
for basin in largest_basins:
basin_product *= basin
print(f"Star 2: product of largest basins is: {basin_product}")
Advent of Code 2021
from collections import Counter
file1 = open('input.txt', 'r')
syntax_error_map = {
")" : 3,
"]" : 57,
"}" : 1197,
">" : 25137
}
lines = list()
incomplete_lines = list()
for line in file1:
lines.append(list(line.strip()))
def isOpeningBracket(bracket):
if bracket == "<" or bracket == "{" or bracket == "[" or bracket == "(":
return True
else:
return False
def isMatchingBracket(bracket1, bracket2):
mapping = {
"<": ">",
">": "<",
"(": ")",
")": "(",
"{": "}",
"}": "{",
"[": "]",
"]": "[",
}
#print(f"bracket 1: {bracket1}, bracket 2 {bracket2[0]}, ==? {mapping[bracket1]} = {mapping[bracket1] == bracket2}")
if mapping[bracket1] == bracket2[0]:
return True
else:
return False
syntax_error_score = 0
for line in lines:
stack = list()
#print(line)
incomplete_line = True
for bracket in line:
if isOpeningBracket(bracket):
stack.append(bracket)
else:
if isMatchingBracket(bracket, stack[-1:]):
stack.pop()
else:
#print(f"illegal bracket found: {bracket}")
syntax_error_score += syntax_error_map[bracket]
incomplete_line = False
break
if incomplete_line:
incomplete_lines.append(line)
print(f"Star 1: Total Syntax error score: {syntax_error_score}")
scores = list()
for line in incomplete_lines:
stack = list()
for bracket in line:
if isOpeningBracket(bracket):
stack.append(bracket)
else:
if isMatchingBracket(bracket, stack[-1:]):
stack.pop()
score = 0
stack.reverse()
for bracket in stack:
score *= 5
if bracket == "(":
score += 1
if bracket == "[":
score += 2
if bracket == "{":
score += 3
if bracket == "<":
score += 4
scores.append(score)
scores.sort()
print(f"Star 2: Middle score is: {scores[len(scores)//2]}")
Advent of Code 2021
import numpy as np
file1 = open('input.txt', 'r')
lines = list()
for line in file1:
lines.append(list(map(int,list(line.strip()))))
grid = np.zeros((10,10), dtype=int)
for y in range(10):
row = list(map(int,list(lines[y])))
grid[y] = np.asarray(row, dtype=np.int8)
print(grid)
def power_up_neighbours(x,y,grid,flashed_octopusses):
for dx in (-1, 0, 1):
for dy in (-1, 0, 1):
x_n = x + dx
y_n = y + dy
if (x_n >= 0 and x_n < 10 ) and (y_n >= 0 and y_n < 10 ):
if(not flashed_octopusses[y_n][x_n]):
grid[y_n][x_n] += 1
flash_count = 0
for iteration in range(0,100):
flashed_octopusses = np.zeros((10,10), dtype=bool)
#increase engery level by one
for y in range(0, len(grid)):
for x in range(0, len(grid[0])):
grid[y][x] += 1
#let octopusses lash
while((grid > 9).sum() != 0):
for y in range(0, len(grid)):
for x in range(0, len(grid[0])):
if grid[y][x] > 9:
flashed_octopusses[y][x] = True
flash_count += 1
grid[y][x] = 0
power_up_neighbours(x,y,grid,flashed_octopusses)
print(f"Star 1: There have been {flash_count} flashes after 100 itterations")
itterations = 100
flashed_octopusses = np.zeros((10,10), dtype=bool)
while( flashed_octopusses.sum() != 100):
flashed_octopusses = np.zeros((10,10), dtype=bool)
#increase engery level by one
for y in range(0, len(grid)):
for x in range(0, len(grid[0])):
grid[y][x] += 1
#let octopusses flash
while((grid > 9).sum() != 0):
for y in range(0, len(grid)):
for x in range(0, len(grid[0])):
if grid[y][x] > 9:
flashed_octopusses[y][x] = True
flash_count += 1
grid[y][x] = 0
power_up_neighbours(x,y,grid,flashed_octopusses)
itterations += 1
print(f"Star 2: All flash after {itterations} itterations")