Advent_of_Code_2023_Intermate/pretty_read.md

7.1 KiB

Vet mooi notebook van Bas

Laten we beginnen met de imports

import re 
import numpy as np

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