# Vet mooi notebook van Bas Laten we beginnen met de imports ```python import re import numpy as np from functools import reduce from math import factorial ``` ## Puzzel 1 ### Deel 1 ```python f = open('data/puzzle_1.txt', 'r') total = 0 for line in f: digit_1 = re.search('(\d)', line).group() digit_2 = re.search('(?:\d)(?!.*\d)', line).group() total += int(digit_1+digit_2) total ``` 55834 ### Deel 2 ```python l = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] digits = '|'+'|'.join(l) f = open('data/puzzle_1.txt', 'r') total = 0 for line in f: string_digits = re.findall('(?=(\d'+digits+'))', line) string_digits = [digit if (digit not in l) else str(l.index(digit)+1) for digit in string_digits] total += int(string_digits[0] + string_digits[-1]) total ``` 53221 ## Puzzel 2 ```python data = open('data/puzzle_2.txt', 'r').readlines() ``` ### Deel 1 ```python color_dict = { 'red': 12, 'green': 13, 'blue': 14 } total = 0 for line in data: possible = True for amount, color in re.findall('(\d+)\W*(red|green|blue)', line): if (color_dict[color] < int(amount)): possible = False if possible: total += int(re.findall('(\d+)', line)[0]) total ``` 3035 ### Deel 2 ```python total = 0 for line in data: color_dict = {'red': [], 'green': [], 'blue': []} for pair in re.findall('(\d+)\W*(red|green|blue)', line): color_dict[pair[1]].append(int(pair[0])) total += max(color_dict['red']) * max(color_dict['green']) * max(color_dict['blue']) total ``` 66027 ## Puzzel 3 ```python data = open('data/puzzle_3.txt', 'r').readlines() ``` ```python data_list = [re.sub('\n', '', line) for line in data] data_list = [re.sub('[^\d\.]', 'X', line) for line in data_list] total = 0 for line_number, line in enumerate(data_list): matches = re.findall('\d+', line) for number in matches: match = re.search(number, line) surrounding_string = "" start, end = match.span() if start > 0: start -= 1 if end <= len(line): end += 1 if line_number != 0: surrounding_string += data_list[line_number-1][start:end] surrounding_string += line[start:end] if line_number != len(data_list)-1: surrounding_string += data_list[line_number+1][start:end] if 'X' in surrounding_string: total += int(match.group()) line = re.sub(match.group(), len(match.group())*'.', line, 1) match = re.search('\d+', line) total ``` 517021 ```python data_list = [re.sub('\n', '', line) for line in data] asterisks = [] numbers = [] for line_number, line in enumerate(data_list): match = re.search('(\*)|(\d+)', line) while match is not None: x, y = match.span() if match.group() == '*': asterisks.append({'x_pos': x, 'line_number': line_number}) else: numbers.append({'x_start':x, 'x_end': y, 'line_number': line_number, 'number': int(match.group())}) line = re.sub('(\*)|(\d+)', len(match.group())*'.', line, 1) match = re.search('(\*)|(\d+)', line) for asterisk in asterisks: asterisk_numbers = [] for number in numbers: if number['line_number'] == asterisk['line_number']: if number['x_end'] == asterisk['x_pos']: asterisk_numbers.append(number['number']) continue if number['x_start']-1 == asterisk['x_pos']: asterisk_numbers.append(number['number']) continue if (number['line_number']+1 == asterisk['line_number']) or (number['line_number']-1 == asterisk['line_number']): if asterisk['x_pos'] in [num for num in range(number['x_start']-1, number['x_end']+1)]: asterisk_numbers.append(number['number']) asterisk['numbers'] = asterisk_numbers total = 0 for asterisk in asterisks: if len(asterisk['numbers']) == 2: total+= asterisk['numbers'][0] * asterisk['numbers'][1] total ``` 81296995 ## Puzzel 4 ### Deel 1 ```python data = open('data/puzzle_4.txt', 'r').readlines() ``` ```python # initiating output variable total = 0 for line in data: # Cleaning identifier as it is not necessary line_number_part = line.split(':')[1] # Removing the \n line_number_part = re.sub('\n', '',line_number_part) # Creating a set with winning numbers and with owned numbers winning_numbers, owned_numbers = line_number_part.split('|') # Getting the seperate numbers winning_numbers = re.findall('(\d+)', winning_numbers) owned_numbers = re.findall('(\d+)', owned_numbers) # Converting to a set to prepare for intersect winning_set = set(winning_numbers) owned_set = set(owned_numbers) # Only numbers that are both owned and winning will be left winning_numbers_owned = winning_set.intersection(owned_set) # Get the number of matches matched_number_count = len(winning_numbers_owned) # If there are no matches, we add nothing to total, so we check for zero matches if matched_number_count > 0: # We then add to the total 2 to the power of the total number of matches minus one, as we start at 1 instead of 2 and 2^0 is 1 total += 2**(matched_number_count-1) print(total) ``` 21568 ### Deel 2 ```python # initiating output variable total = 0 winning_numbers_on_card = [] card_numbers = [] copies_of_card = [] for line in data: # Cleaning identifier card_identifier_part, line_number_part = line.split(':') identifier = int(re.search('\d+', card_identifier_part).group()) # adding to the list card_numbers.append(identifier) # Also adding a 1 to the owned cards list copies_of_card.append(1) # Removing the \n line_number_part = re.sub('\n', '',line_number_part) # Creating a set with winning numbers and with owned numbers winning_numbers, owned_numbers = line_number_part.split('|') # Getting the seperate numbers winning_numbers = re.findall('(\d+)', winning_numbers) owned_numbers = re.findall('(\d+)', owned_numbers) # Converting to a set to prepare for intersect winning_set = set(winning_numbers) owned_set = set(owned_numbers) # Only numbers that are both owned and winning will be left winning_numbers_owned = winning_set.intersection(owned_set) # Get the number of matches matched_number_count = len(winning_numbers_owned) # Add to card info list winning_numbers_on_card.append(matched_number_count) # Just simulating the rounds, if a card has winining numbers, loop over a range and add that loop variable to the card number # if the card number exists, we simply add the number of copies of the current card to that card # etc. for i, card_id in enumerate(card_numbers): winning_numbers = winning_numbers_on_card[i] for number in range(1, winning_numbers+1): if (card_id+number) in card_numbers: id_to_add_to = card_numbers.index(card_id+number) copies_of_card[id_to_add_to] += copies_of_card[i] # just sum the total cards at the end print(sum(copies_of_card)) ``` 11827296 # AANSCHOUW!!!!! Het wonder, het fantastischste ding ooit, oneliners ```python reduce(lambda total, multipliers: (total + 2**(multipliers-1) if (multipliers > 0) else total) ,map(lambda numbers: len(numbers)-len(set(numbers)), [re.findall('(?:(\d+)\s|\n)', line) for line in open('data/puzzle_4.txt')]), 0) ``` 21568 ```python sum([y for (x,y) in reduce(lambda total, cards: total + [(cards[0], 1)] + [(card, 1+sum([total_card[1] for total_card in total if total_card[0] == cards[0]])) for card in cards[1]], enumerate([j+1+i for j in range(len(re.findall(r'(?:\b(\d+)\s)(?=.*\s\1\b)', line)))] for i, line in enumerate(open('data/puzzle_4.txt'))), [])]) ``` 11827296 ## Puzzel 5 ### Deel 1 ```python data = open('data/puzzle_5.txt','r').readlines() seeds = [int(seed) for seed in re.findall(r'\d+', data[0])] seed_maps = [] map_names = [] mapping = [] for line in data[1:]: if 'map' in line: mapping = [] map_names.append(line) if line == '\n': seed_maps.append(mapping) ints = [int(value) for value in re.findall(r'\b(\d+)', line)] if len(ints) > 0: mapping.append(ints) seed_maps.append(mapping) for mapping in seed_maps: if len(mapping) < 1: continue new_seeds = [] for map_row in mapping: for seed in seeds: if (map_row[1]+map_row[2]) > seed >= map_row[1]: new_seeds.append(seed+map_row[0]-map_row[1]) seeds = new_seeds print(seeds) min(seeds) ``` [3871578677, 1724133724, 199602917, 2982314302, 595680226, 692431340, 2899305373, 2926286942, 4220409748, 2324727144, 2504054106, 2942258417, 1481150454, 1479468889, 2022824054, 4001340211, 3089202785] 199602917 ## Deel 2 ```python data = open('data/puzzle_5.txt','r').readlines() seeds = [{'start': int(x), 'end': int(x) + int(y)} for (x,y) in re.findall(r'(?:(\d+)\s(\d+))', data[0])] seed_maps = [] map_names = [] mapping = [] for line in data[1:]: if 'map' in line: mapping = [] map_names.append(line) if line == '\n': if len(mapping) > 0: seed_maps.append(mapping) ints = [int(value) for value in re.findall(r'\b(\d+)', line)] if len(ints) > 0: mapping.append({'start': ints[1], 'end': ints[1]+ints[2], 'change': ints[0] - ints[1]}) seed_maps.append(mapping) for seed_map in seed_maps: new_seeds = [] for seed in seeds: bounds = [(seed['start'], 0), (seed['end'], 0)] for row in seed_map: if (row['start'] >= seed['end']) or (row['end'] <= seed['start']): continue if row['start'] <= seed['start']: bounds.append((seed['start'], row['change'])) else: bounds.append((row['start'], row['change'])) if row['end'] < seed['end']: bounds.append((row['end'], 0)) bounds.sort(key=lambda x: x[0]) for i in range(len(bounds)-1): lower_bound = bounds[i] upper_bound = bounds[i+1] if lower_bound[0] != lower_bound[1]: new_seeds.append({'start': lower_bound[0]+lower_bound[1], 'end': upper_bound[0]+lower_bound[1]}) seeds = new_seeds min([seed['start'] for seed in seeds]) ``` 2254686 ## Puzzel 6 ## Deel 1 ```python data = open('data/puzzle_6.txt', 'r').readlines() times = [int(time) for time in re.findall(r'(\d+)', data[0])] distances = [int(distance) for distance in re.findall(r'(\d+)', data[1])] ``` [358, 1054, 1807, 1080] [46, 68, 98, 66] ```python total_wins = [] for time, distance in zip(times, distances): wins = 0 for time_pressed in range(0, time+1): distance_travelled = time_pressed * (time-time_pressed) if distance_travelled > distance: wins += 1 total_wins.append(wins) score = 1 for win in total_wins: score = score*win score ``` 138915 ## Deel 2 ```python time = [time for time in re.findall(r'(\d+)', data[0])] time = int(''.join(time)) distance = [distance for distance in re.findall(r'(\d+)', data[1])] distance = int(''.join(distance)) discriminant = (time**2) - (4 * distance) x0 = ((-time) + np.sqrt(discriminant))/-2 x1 = ((-time) - np.sqrt(discriminant))/-2 print(x0, x1) round(x1) - round(x0)-1 ``` 9674509.498754364 37015356.50124563 27340847 ```python [round(number[0] - number[1]) for number in [[(-1 * numbers[1] + np.sqrt(numbers[0]))/2, ((-1 * numbers[1]) - np.sqrt(numbers[0]))/2] for numbers in [[((numbers[0]**2) - (4 * numbers[1]))]+numbers for numbers in [[int(''.join(re.findall('(\d+)', line))) for line in open('data/puzzle_6.txt')]]]]][0] ``` 27340847 ## Puzzel 7 ## Deel 1 ```python data = re.findall(r'(\w+)\s(\d+)',open('data/puzzle_7.txt', 'r').read(), flags=re.MULTILINE) values = "AKQJT98765432" hands = [{'cards': x, 'bid': int(y)} for x,y in data] fivek = [] fourk = [] fh = [] threek = [] twop = [] onep = [] hc = [] for hand in hands: hand['values'] = np.array([hand['cards'].count(letter) for letter in values]) max_card = np.argmax(hand['values']) if max(hand['values']) == 5: fivek.append(hand) elif max(hand['values']) == 4: fourk.append(hand) elif max(hand['values']) == 3: if np.any(hand['values'] == 2): fh.append(hand) else: threek.append(hand) elif max(hand['values']) == 2: if sum(hand['values'] > 1) == 2: twop.append(hand) else: onep.append(hand) else: hc.append(hand) combos = [fivek, fourk, fh, threek, twop, onep, hc] for combo in combos: combo.sort(key=lambda hand: ''.join([chr(values.index(letter)+96) for letter in hand['cards']])) combos = [val for sublist in combos for val in sublist] combos = combos[::-1] sum([(i+1)*hand['bid'] for i, hand in enumerate(combos)]) ``` 250120186 ### Deel 2 ```python data = re.findall(r'(\w+)\s(\d+)',open('data/puzzle_7.txt', 'r').read(), flags=re.MULTILINE) values = "AKQT98765432J" hands = [{'cards': x, 'bid': int(y)} for x,y in data] fivek = [] fourk = [] fh = [] threek = [] twop = [] onep = [] hc = [] for hand in hands: hand['values'] = np.array([hand['cards'].count(letter) for letter in values if letter != 'J']) max_card = np.argmax(hand['values']) hand['values'][max_card] += hand['cards'].count('J') if max(hand['values']) == 5: fivek.append(hand) elif max(hand['values']) == 4: fourk.append(hand) elif max(hand['values']) == 3: if np.any(hand['values'] == 2): fh.append(hand) else: threek.append(hand) elif max(hand['values']) == 2: if sum(hand['values'] > 1) == 2: twop.append(hand) else: onep.append(hand) else: hc.append(hand) combos = [fivek, fourk, fh, threek, twop, onep, hc] for combo in combos: combo.sort(key=lambda hand: ''.join([chr(values.index(letter)+96) for letter in hand['cards']])) combos = [val for sublist in combos for val in sublist] combos = combos[::-1] sum([(i+1)*hand['bid'] for i, hand in enumerate(combos)]) ``` 250665248 ## Puzzel 8 ### Deel 1 ```python data = open('data/puzzle_8.txt', 'r').read() directions = re.search(r'(\w+)', data).group() nodes = {x: {'L': y, 'R': z} for x,y,z in re.findall(r'(\w{3}).*\((\w{3}).*(\w{3})', data, flags=re.MULTILINE)} steps = 0 current_node = 'AAA' while current_node != 'ZZZ': for direction in directions: current_node = nodes[current_node][direction] steps += 1 if current_node == 'ZZZ': break print(steps) ``` 20777 ### Deel 2 ```python current_nodes = re.findall('(\w{2}A)\s', data, flags=re.MULTILINE) all_matches = [] for node in current_nodes: matches = [] steps = 0 while len(matches) < 10: for letter in directions: node = nodes[node][letter] steps += 1 if node[2] == 'Z': matches.append(steps) all_matches.append(matches) lowest = [matches[0] for matches in all_matches] val = np.gcd.reduce(lowest) total = 1 for x in [x/val for x in lowest]: total *= x int(total * val) ``` 13289612809129 ## Puzzel 10!!! ### Deel 1 ```python data = open('data/puzzle_10.txt', 'r').readlines() data = [re.sub('\n', '', line) for line in data] start_position = [(i, line.index('S')) for i, line in enumerate(data) if 'S' in line][0] start_position ``` (42, 8) ```python def get_next_direction(current_direction, pipe): if pipe in 'FJ': current_direction = (-current_direction[1], -current_direction[0]) if pipe in '7L': current_direction = (current_direction[1], current_direction[0]) return current_direction ``` ```python current_position = start_position answers = [] for current_direction in [(1,0),(-1,0),(0,1),(0,-1)]: current_position = start_position steps = 0 while data[current_position[0]][current_position[1]] != 'S' or steps == 0: current_position = (current_position[0] + current_direction[0], current_position[1] + current_direction[1]) steps += 1 current_direction = get_next_direction(current_direction, data[current_position[0]][current_position[1]]) if data[current_position[0]][current_position[1]] == '.': break answers.append(steps) max(answers)/2 ``` 6838.0 ```python current_position = start_position current_pipe = 'X' loop = [['.'] * len(line) for line in data] current_direction = (1, 0) while current_pipe != 'S': current_position = tuple(map(sum, zip(current_position, current_direction))) current_pipe = data[current_position[0]][current_position[1]] current_direction = get_next_direction(current_direction, current_pipe) loop[current_position[0]][current_position[1]] = current_pipe loop[42][8] = 'F' total = 0 for line in loop: in_loop = False last = '' for item in line: if item in 'FL': last = item elif item in '||': in_loop = not in_loop elif item == '7' and last == 'L': in_loop = not in_loop last = item elif item == 'J' and last == 'F': in_loop = not in_loop last = item if item == '.' and in_loop: total += 1 print(total) ``` 451