Advent_of_Code_2023_Intermate/pretty_read.md

20 KiB

Vet mooi notebook van Bas

Laten we beginnen met de imports

import re 
import numpy as np
from functools import reduce
from math import factorial

Puzzel 1

Deel 1

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

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

data = open('data/puzzle_2.txt', 'r').readlines()

Deel 1

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

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

data = open('data/puzzle_3.txt', 'r').readlines()
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
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

data = open('data/puzzle_4.txt', 'r').readlines()
# 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

# 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

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
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

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

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

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]
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

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
[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

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

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

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

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

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)
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
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
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

Puzzel 11

Deel 1

data = open('data/puzzle_11.txt', 'r').readlines()
data = [re.sub('\n', '', line) for line in data]

new_data = []
# expand rows
for line in data:
    if len(set(list(line))) == 1:
        new_data.append(line)
    new_data.append(line)
data = new_data

new_data = []

# expand galaxy columns
for line in data:
    new_line = ""
    for i, value in enumerate(line):
        if '#' not in [row[i] for row in data]:
            new_line += '..'
        else:
            total += 1
            new_line += value
    new_data.append(new_line)

galaxies = []
for row_number, line in enumerate(new_data):
    for col_number, value in enumerate(line):
        if value == '#':
            galaxies.append((row_number, col_number))
pairs = set([frozenset([galaxy_1, galaxy_2]) for galaxy_1 in galaxies for galaxy_2 in galaxies if galaxy_1 != galaxy_2])
distances = []
for galaxy_pair in pairs:
    pair = list(galaxy_pair)

    x_diff = abs(pair[0][0] - pair[1][0])
    y_diff = abs(pair[0][1] - pair[1][1])
    distances.append(x_diff + y_diff)
sum(distances)
            
        
9605127
data = open('data/puzzle_11.txt', 'r').readlines()
data = [re.sub('\n', '', line) for line in data]
galaxies = []
for row_number, line in enumerate(data):
    for col_number, value in enumerate(line):
        if value == '#':
            galaxies.append((row_number, col_number))

expanded_rows = [i for i, line in enumerate(data) if "#" not in line]
expanded_cols = [i for i in range(len(data[0])) if '#' not in [row[i] for row in data]]

pairs = set([frozenset([galaxy_1, galaxy_2]) for galaxy_1 in galaxies for galaxy_2 in galaxies if galaxy_1 != galaxy_2])
distances = []
for galaxy_pair in pairs:
    pair = list(galaxy_pair)
    x1, y1 = pair[0]
    x2, y2 = pair[1]
    x_diff = abs(x1-x2)
    y_diff = abs(y1-y2)
    
    for expanded_row in expanded_rows:
        if x2 < expanded_row < x1:
            x_diff += 999999
        if x1 < expanded_row < x2:
            x_diff += 999999
    for expanded_col in expanded_cols:
        if y1 < expanded_col < y2:
            y_diff += 999999
        if y2 < expanded_col < y1:
            y_diff += 999999
    

    
    distances.append(x_diff + y_diff)
sum(distances)
458191688761