<repo_name>pelma24/AdventOfCode<file_sep>/2022/day5.py
from copy import deepcopy
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re

inputArrangement = [['N','T','B','S','Q','H','G','R'], ['J','Z','P','D','F','S','H'], ['V','H','Z'], ['H','G','F','J','Z','M'], ['R','S','M','L','D','C','Z','T'], ['J','Z','H','V','W','T','M'], ['Z','L','P','F','T'], ['S','W','V','Q'], ['C','N','D','T','M','L','H','W']]


def do1(splitInput):
	arrangement = deepcopy(inputArrangement)
	for line in splitInput:
		match = re.match('move (?P<number>\d+) from (?P<start>\d) to (?P<end>\d)', line)
		start = int(match.group('start')) - 1
		number = int(match.group('number'))
		end = int(match.group('end')) - 1
	
		for _ in range(number):
			arrangement[end].insert(0, arrangement[start].pop(0))
		
	result = ''
	for part in arrangement:
		result = result + part[0]

	return result

def do2(splitInput):
	arrangement = deepcopy(inputArrangement)	
	for line in splitInput:
		match = re.match('move (?P<number>\d+) from (?P<start>\d) to (?P<end>\d)', line)
		start = int(match.group('start')) - 1
		number = int(match.group('number'))
		end = int(match.group('end')) - 1

		movedParts = arrangement[start][0:number]
		arrangement[start] = arrangement[start][number:]
		arrangement[end] = movedParts + arrangement[end] 
	
	result = ''
	for part in arrangement:
		result = result + part[0]

	return result

def do():
	strInput = readInputFile(5)

	splitInput = strInput.split('\n')
	
	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day5.py
from HelperFunctions import inputsplit

def do1(puzzleInput):

    seatIDs = getSeatIDs(puzzleInput)
    
    return max(seatIDs)

def do2(puzzleInput):
    seatIDs = getSeatIDs(puzzleInput)
    
    seatIDs.sort()

    seatBeforeMissingSeat = [x for x in range(len(seatIDs) - 1) if seatIDs[x + 1] - seatIDs[x] > 1]

    return seatIDs[seatBeforeMissingSeat[0]] + 1

def getSeatIDs(puzzleInput):
    
    seatIDs = []

    for boardingPass in puzzleInput:
        seatID = calculateSeatID(boardingPass)
        seatIDs.append(seatID)

    return seatIDs

def calculateSeatID(boardingPass):
    seatID = 0
    
    rowCalc = boardingPass[0:7]
    columnCalc = boardingPass[7:]

    row = calculatePosition(rowCalc, 127)
    column = calculatePosition(columnCalc, 7)
    seatID = row * 8 + column
    return seatID

def calculatePosition(instructions, upper):
    lower = 0

    for instruction in instructions:
        if instruction in ['F', 'L']:
            upper = lower + int((upper - lower) / 2)
        else:
            lower = lower + int((upper - lower) / 2) + 1
    return upper

def do():
    with open ('Input/day5.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2020/day3.py
from HelperFunctions import inputsplit

def do1(puzzleInput):
    
    return countTrees(puzzleInput, 1, 3)

def do2(puzzleInput, slopes):
    
    trees = 1

    for slope in slopes:
        trees *= countTrees(puzzleInput, slope[0], slope[1])

    return trees

def countTrees(puzzleInput, slopeRow, slopeColumn):
    trees = 0

    columnLength = len(puzzleInput[0])
    column = 0

    for row in range(slopeRow, len(puzzleInput), slopeRow):
        column = (column + slopeColumn) % columnLength
        if puzzleInput[row][column] == '#':
            trees += 1

    return trees

def do():
    with open ('Input/day3.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    slopes = [(1,1), (1,3), (1,5), (1,7), (2,1)]

    print(do1(splitInput))
    print(do2(splitInput, slopes))
    
do()<file_sep>/2020/day21.py
from HelperFunctions import inputsplit
import re
from copy import deepcopy

def do1(puzzleInput):
    completeListOfIngredients, possibleAllergens = getIngredients(puzzleInput)

    badIngredients = extractBadIngredients(possibleAllergens)

    goodIngredients = countGoodIngredients(completeListOfIngredients, badIngredients)

    return goodIngredients

def do2(puzzleInput):
    _, possibleAllergens = getIngredients(puzzleInput)

    badIngredients = extractBadIngredients(possibleAllergens)

    canonical = getCanonicalDangerousList(badIngredients)

    return canonical

def getCanonicalDangerousList(badIngredients):
    sortedAllergens = sorted(list(badIngredients.keys()))

    result = ''
    for allergen in sortedAllergens:
        result += badIngredients[allergen]
        if allergen != sortedAllergens[-1]:
            result += ','
    
    return result

def getIngredients(puzzleInput):
    allergensInIngredients = {}
    completeListOfIngredients = []
    for line in puzzleInput:
        match = re.match('(.+) \(contains (.+)\)', line)
        if match:
            allIngredients = match.groups()[0].split(' ')
            completeListOfIngredients += allIngredients
            ingredients = set(allIngredients)
            allergens = match.groups()[1].replace(' ', '').split(',')
            
            for allergen in allergens:
                if allergen not in allergensInIngredients.keys():
                    allergensInIngredients[allergen] = ingredients
                else:
                    allergensInIngredients[allergen] = allergensInIngredients[allergen] & ingredients

    return completeListOfIngredients, allergensInIngredients

def countGoodIngredients(ingredients, badIngredients):
    for value in badIngredients.values():
        ingredients = [x for x in ingredients if x != value]

    return len(ingredients)

def extractBadIngredients(allergens):
    solution = {}
    while (len(solution.keys()) != len(allergens.keys())):
        for allergen,ingredients in allergens.items():
            if len(ingredients) == 1:
                solution[allergen] = ingredients.pop()
                for value in allergens.values():
                    value.discard(solution[allergen])
    return solution

def do():
    with open ('Input/day21.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')
    
    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2020/day1.py
from HelperFunctions import inputsplit
from HelperFunctions import convertToInt

def do1(intInput):
    
    multiply = set([x*y for x in intInput for y in intInput if (x + y) == 2020])
    return multiply

def do2(intInput):
    
    multiply = set([x*y*z for x in intInput for y in intInput for z in intInput if (x + y + z) == 2020])
    return multiply

def do():
    with open ('Input/day1.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')
    intInput = convertToInt(splitInput)

    print(do1(intInput))
    print(do2(intInput))

do()<file_sep>/2019/day14.py
from collections import namedtuple
import re

input = """1 ZQVND => 2 MBZM
2 KZCVX, 1 SZBQ => 7 HQFB
1 PFSQF => 9 RSVN
2 PJXQB => 4 FSNZ
20 JVDKQ, 2 LSQFK, 8 SDNCK, 1 MQJNV, 13 LBTV, 3 KPBRX => 5 QBPC
131 ORE => 8 WDQSL
19 BRGJH, 2 KNVN, 3 CRKW => 9 MQJNV
16 DNPM, 1 VTVBF, 11 JSGM => 1 BWVJ
3 KNVN, 1 JQRML => 7 HGQJ
1 MRQJ, 2 HQFB, 1 MQJNV => 5 VQLP
1 PLGH => 5 DMGF
12 DMGF, 3 DNPM, 1 CRKW => 1 CLML
1 JSGM, 1 RSVN => 5 TMNKH
1 RFJLG, 3 CFWC => 2 ZJMC
1 BRGJH => 5 KPBRX
1 SZBQ, 17 GBVJF => 4 ZHGL
2 PLGH => 5 CFWC
4 FCBZS, 2 XQWHB => 8 JSGM
2 PFSQF => 2 KNVN
12 CRKW, 9 GBVJF => 1 KRCB
1 ZHGL => 8 PJMFP
198 ORE => 2 XQWHB
2 BWVJ, 7 CFWC, 17 DPMWN => 3 KZCVX
4 WXBF => 6 JVDKQ
2 SWMTK, 1 JQRML => 7 QXGZ
1 JSGM, 1 LFSFJ => 4 LSQFK
73 KNVN, 65 VQLP, 12 QBPC, 4 XGTL, 10 SWMTK, 51 ZJMC, 4 JMCPR, 1 VNHT => 1 FUEL
1 BWVJ, 7 MBZM => 5 JXZT
10 CFWC => 2 DPMWN
13 LQDLN => 3 LBTV
1 PFZW, 3 LQDLN => 5 PJXQB
2 RSVN, 2 PFSQF => 5 CRKW
1 HGQJ, 3 SMNGJ, 36 JXZT, 10 FHKG, 3 KPBRX, 2 CLML => 3 JMCPR
126 ORE => 4 FCBZS
1 DNPM, 13 MBZM => 5 PLGH
2 XQWHB, 10 FCBZS => 9 LFSFJ
1 DPMWN => 9 PFZW
1 ZJMC, 3 TMNKH => 2 SWMTK
7 TZCK, 1 XQWHB => 5 ZQVND
4 CFWC, 1 ZLWN, 5 RSVN => 2 WXBF
1 BRGJH, 2 CLML => 6 LQDLN
26 BWVJ => 2 GBVJF
16 PJXQB, 20 SDNCK, 3 HQFB, 7 QXGZ, 2 KNVN, 9 KZCVX => 8 XGTL
8 PJMFP, 3 BRGJH, 19 MRQJ => 5 SMNGJ
7 DNPM => 2 SZBQ
2 JQRML, 14 SDNCK => 8 FHKG
1 FSNZ, 6 RFJLG, 2 CRKW => 8 SDNCK
2 CLML, 4 SWMTK, 16 KNVN => 4 JQRML
8 TZCK, 18 WDQSL => 2 PFSQF
1 LSQFK => 8 VTVBF
18 BRGJH, 8 ZHGL, 2 KRCB => 7 VNHT
3 TZCK => 4 DNPM
14 PFZW, 1 PFSQF => 7 BRGJH
21 PLGH, 6 VTVBF, 2 RSVN => 1 ZLWN
149 ORE => 2 TZCK
3 JSGM => 1 RFJLG
4 PFSQF, 4 DMGF => 3 MRQJ"""


Ingredients = namedtuple('Ingredients', 'ingredients result')

usedOres = 0

def do2():
    splitInput = input.split('\n')

    recipes = getRecipes(splitInput)
    stuff = {}
    stuff['ORE'] = 1000000000000
    repeat = True
    while repeat:
        repeat, sumOfFuel = makeStuff(recipes, stuff, 'FUEL', 2)
    return sumOfFuel

def do():
    splitInput = input.split('\n')

    recipes = getRecipes(splitInput)
    stuff = {}
    makeStuff(recipes, stuff, 'FUEL', 1)

def getRecipes(splitInput):
    recipes = {}   

    for line in splitInput:
        match = re.findall('([0-9]+) ([A-Z]+)', line)

        ingredients = {}
        for i in range(len(match) - 1):
            ingredients[match[i][1]] = int(match[i][0])
        recipes[match[-1][1]] = Ingredients(result=int(match[-1][0]), ingredients=ingredients)

    return recipes

def makeStuff(recipes, stuff, name, part):
    global usedOres

    creationWorks = False
    while not creationWorks:
        allIngredients = True
        for ingredient in recipes[name].ingredients.keys():
            numberNeeded = recipes[name].ingredients[ingredient]
            if stuff.get(ingredient, 0) < numberNeeded:
                allIngredients = False
                if ingredient == 'ORE':
                    if part == 2:
                        return [False, stuff.get('FUEL', 0)]
                    else:
                        neededOres = numberNeeded - stuff.get('ORE', 0)
                        usedOres += neededOres
                        stuff['ORE'] = stuff.get('ORE', 0) + neededOres 
                else:
                    repeat, sum = makeStuff(recipes, stuff, ingredient, part)
                    if not repeat:
                        return [False, stuff.get('FUEL', 0)]

        
        if allIngredients:
            creationWorks = True           
    
    stuff[name] = stuff.get(name, 0) + recipes[name].result
    for ingredient in recipes[name].ingredients.keys():
        numberNeeded = recipes[name].ingredients[ingredient]
        stuff[ingredient] -= numberNeeded
    
    return [True, stuff.get('FUEL', 0)]



do()
print(usedOres)

print(do2())

<file_sep>/2021/day2.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	horizontal = 0
	depth = 0

	for line in splitInput:
		direction,value = line.split(' ')
		value = int(value)

		match direction:
			case 'forward':
				horizontal += value
			case 'up':
				depth -= value
			case 'down':
				depth += value
	
	return horizontal * depth

def do2(splitInput):
	horizontal = 0
	depth = 0
	aim = 0
	
	for line in splitInput:
		direction,value = line.split(' ')
		value = int(value)

		match direction:
			case 'forward':
				horizontal += value
				depth += aim * value
			case 'up':
				aim -= value
			case 'down':
				aim += value
	
	return horizontal * depth

def do():
	strInput = readInputFile(2)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day22.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re

def do1(splitInput):
	points = set()
	for line in splitInput:
		onorOff,xmin,xmax,ymin,ymax,zmin,zmax = getLine(line)

		if xmin < -50 or xmax > 50 or ymin < -50 or ymax > 50 or zmin < -50 or zmax > 50:
			continue

		for x in range(xmin, xmax + 1):
			for y in range(ymin, ymax + 1):
				for z in range(zmin, zmax + 1):
					match onorOff:
						case 'on':
							points.add((x,y,z))
						case 'off':
							if (x,y,z) in points:
								points.remove((x,y,z))
						case _:
							print('missing implementation')	
	return len(points)

def do2(splitInput):
	processed = []

	for line in splitInput:
		onorOff,xmin,xmax,ymin,ymax,zmin,zmax = getLine(line)
		cube = (xmin,xmax,ymin,ymax,zmin,zmax)

		newCubes = []
		
		for otherCube,activation in processed:
			intersectionCube = intersectCubes(cube, otherCube)
			if intersectionCube:
				if activation == 'on':
					newActivation = 'off'
				else:
					newActivation = 'on'
				newCubes.append((intersectionCube, newActivation))
			
		if onorOff == 'on':
			processed.append((cube, onorOff))	
		processed += newCubes

	on = 0

	for cube,activation in processed:
		volume = getCubeVolume(cube)
		if activation == 'on':
			on += volume
		else:
			on -= volume
	return on

def getCubeVolume(cube):
	if not cube:
		return 0
	xmin,xmax,ymin,ymax,zmin,zmax = cube

	return abs(xmax + 1 - xmin) * abs(ymax + 1 - ymin) * abs(zmax + 1 - zmin)

def intersectCubes(cube1, cube2):
	xmin1,xmax1,ymin1,ymax1,zmin1,zmax1 = cube1
	xmin2,xmax2,ymin2,ymax2,zmin2,zmax2 = cube2

	if xmin1 < xmin2:
		if xmin2 > xmax1:
			return []
	else:
		if xmin1 > xmax2:
			return []
	if ymin1 < ymin2:
		if ymin2 > ymax1:
			return []
	else:
		if ymin1 > ymax2:
			return []
	if zmin1 < zmin2:
		if zmin2 > zmax1:
			return []
	else:
		if zmin1 > zmax2:
			return []
	
	ixmin = max(xmin1, xmin2)
	iymin = max(ymin1, ymin2)
	izmin = max(zmin1, zmin2)

	ixmax = min(xmax1, xmax2)
	iymax = min(ymax1, ymax2)
	izmax = min(zmax1, zmax2)	

	return [ixmin,ixmax,iymin,iymax,izmin,izmax]

def getLine(line):
	match = re.findall('(on|off) x=(-?[0-9]+)\.\.(-?[0-9]+)',line)
	onOrOff,xmin,xmax = match[0]
	xmin,xmax = convertToInt((xmin,xmax))

	match = re.findall('y=(-?[0-9]+)\.\.(-?[0-9]+)',line)
	ymin,ymax = convertToInt(match[0])

	match = re.findall('z=(-?[0-9]+)\.\.(-?[0-9]+)',line)
	zmin,zmax = convertToInt(match[0])

	return onOrOff,xmin,xmax,ymin,ymax,zmin,zmax

def do():
	strInput = readInputFile(22)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day19.py
from HelperFunctions import inputsplit
import re
from HelperFunctions import convertToInt
from copy import deepcopy

def do1(puzzleInput):
    rules = getRules(puzzleInput[0])
    messages = puzzleInput[1].split('\n')

    result = checkMessages(messages, rules, 0)

    return result

def do2(puzzleInput):
    rules = getRules(puzzleInput[0])
    messages = puzzleInput[1].split('\n')

    result = checkMessages2(messages, rules, 0)

    return result

def getRules(puzzleInput):
    rules = {}
    missing = {}
    splitInput = puzzleInput.split('\n')
    newInput = deepcopy(splitInput)
    for rule in splitInput:
        match = re.match('([0-9]+): "(.+)"', rule)
        if match:
            rules[int(match.groups()[0])] = [match.groups()[1]]
            newInput.remove(rule)
        else:
            match = re.match('([0-9]+): (.+)', rule)
            missing[int(match.groups()[0])] = match.groups()[1]
        
    ls = deepcopy(missing)
    for key in ls.keys():
        getRule(key, rules, missing)

    return rules

def getRule(rule, rules, missing):
    if rule in rules.keys():
        return rules[rule]
    
    match = re.fullmatch('(([ ]?[0-9]+)+)', missing[rule])
    if match:
        subrules = convertToInt(match.groups()[0].split(' '))
        result = getResult(subrules, rules, missing)
        rules[rule] = result
    else:
        match = re.fullmatch('(([ ]?[0-9]+)+) \| (([ ]?[0-9]+)+)', missing[rule])
        if match:
            alternatives = []
            alternatives.append(match.groups()[0])
            alternatives.append(match.groups()[2])
            completeResult = []
            for alternative in alternatives:
                subrules = convertToInt(alternative.split(' '))
                result = getResult(subrules, rules, missing)
                completeResult += result
            rules[rule] = completeResult
    
    del missing[rule]
    return rules[rule]
    
def getResult(subrules, rules, missing):
    result = []
    for subrule in subrules:
        alternatives = getRule(subrule, rules, missing)
        if not result:
            result = deepcopy(alternatives)
        else:
            tmp = []
            for partResult in result:
                for alternative in alternatives:
                    tmp.append(partResult + alternative)
            result = tmp
    return result

def checkMessages(messages, rules, ruleNumber):
    count = 0
    for message in messages:
        if message in rules[ruleNumber]:
            count += 1

    return count

def checkMessages2(messages, rules, ruleNumber):
    blobSize = len(rules[42][0])
    
    count = 0
    for message in messages:
        if message in rules[ruleNumber]:
            count += 1
        else:
            count42 = 0
            count31 = 0
            successful = True
            for position in range(0, len(message) - blobSize + 1, blobSize):
                messageSlice = message[position:(position + blobSize)]
                if messageSlice in rules[42]:
                    count42 += 1
                    if count31:
                        successful = False
                        break
                elif messageSlice in rules[31]:
                    count31 += 1
            if successful and count31 and count42 - count31 > 0:
                count += 1

    return count


def do():
    with open ('Input/day19.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n\n')
    
    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2021/day14.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re
from collections import Counter
from copy import deepcopy
from itertools import pairwise

def do1(start, rules):
	ruleSet = getRules(rules)
	
	occurences = insert(start, ruleSet, 10)

	mostCommon = max(occurences.values())
	leastCommon = min(occurences.values())
	
	return mostCommon - leastCommon

def do2(start, rules):
	ruleSet = getRules(rules)
	
	occurences = insert(start, ruleSet, 40)
	
	mostCommon = max(occurences.values())
	leastCommon = min(occurences.values())

	return mostCommon - leastCommon

def getRules(rules):
	ruleSet = {}

	for rule in rules:
		match = re.fullmatch('([A-Z]+) -> ([A-Z])', rule)
		if match:
			ruleSet[(match.groups()[0][0], match.groups()[0][1])] = match.groups()[1]

	return ruleSet

def insert(start, ruleSet, steps):
	occurences = Counter()
	pairOccurences = Counter()

	for x in start:
		occurences[x] += 1

	pairs = pairwise(start)
	for pair in pairs:
		pairOccurences[pair] += 1

	newPairOccurences = deepcopy(pairOccurences)
	for _ in range(steps):
		pairOccurences = deepcopy(newPairOccurences)
		for (x,y),quantity in pairOccurences.items():
			if quantity == 0:
				continue
			newElement = ruleSet[(x,y)]
			occurences[newElement] += quantity

			newPairOccurences[(x,newElement)] += quantity
			newPairOccurences[(newElement, y)] += quantity
			newPairOccurences[(x,y)] -= quantity

	return occurences

def do():
	strInput = readInputFile(14)

	start,rules = strInput.split('\n\n')
	rules = rules.split('\n')

	print(do1(start, rules))
	print(do2(start, rules))

	print('done')


do()<file_sep>/2021/day24.py
from functools import cache

inputDict = {1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}

def do1():

	global inputDict
	k = [1, 10, 2, 5, 6, 0, 16, 12, 15, 7, 6, 5, 6, 15]
	special = {3: 10, 7: 11, 8: 7, 10: 13, 11: 0, 12: 11, 13: 0, }

	for position in range(1,14):
		newDict = inputDict.copy()
		for oldW, z in inputDict.items():
			if position in special.keys():
				w = (z % 26) - special[position]
				if w < 1 or w > 9:
					del newDict[oldW]
					continue
				znew = z // 26
				newDict[oldW * 10 + w] = znew	
			else:
				for w in range(1,10):
					znew = 26 * z + w + k[position]
					newDict[oldW * 10 + w] = znew
			del newDict[oldW]
		inputDict = newDict.copy()

	possibleValues = [x for x in inputDict.keys() if inputDict[x] == 0]

	return max(possibleValues)			

def do2():
	global inputDict
	
	possibleValues = [x for x in inputDict.keys() if inputDict[x] == 0]

	return min(possibleValues)

def do():
	
	print(do1())
	print(do2())

	print('done')


do()<file_sep>/2020/day13.py
from HelperFunctions import inputsplit

def do1(earliest, puzzleInput):
    bestBusID = 0
    leastWaitingTime = 100000000000

    for bus in puzzleInput:
        if bus == 'x':
            continue
        busDepartTime = 0
        busID = int(bus)
        while busDepartTime < earliest:
            busDepartTime += busID
        if (busDepartTime - earliest) < leastWaitingTime:
            leastWaitingTime = busDepartTime - earliest
            bestBusID = busID
    
    return bestBusID * leastWaitingTime

def do2(puzzleInput):

    maxBus = max([x for x in puzzleInput if x != 'x'])
    maxBusIndex = puzzleInput.index(maxBus)
    maxBus = int(maxBus)

    departTime = 487905974205117 - maxBus# 100000000000481-maxBusIndex
    works = False
    while not works:
        works = True
        departTime += maxBus
        for i in range(len(puzzleInput)):
            bus = puzzleInput[i]
            if bus == 'x':
                continue
            busID = int(bus)
            if (departTime + i) % busID != 0:
                works = False
                break
    
    return departTime

def do():
    with open ('Input/day13.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, ',')

    earliest = 1007125

    print(do1(earliest, splitInput))
    print(do2(splitInput))
    
do()
<file_sep>/2022/day23.py
from collections import namedtuple
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

directions = ['n', 's', 'w', 'e']

Neighbors = namedtuple('Neighbors', ['NW', 'N', 'NE', 'W', 'E', 'SW', 'S', 'SE'])

def do1(splitInput):
	elves = extractElves(splitInput)
	
	directionPos = 0

	for _ in range(10):
		newElves = {}
		for elf in elves:
			neighbors = getNeighbors(elf, elves)
			if not neighbors.N and not neighbors.NE and not neighbors.NW and not neighbors.W and not neighbors.E and not neighbors.SW and not neighbors.S and not neighbors.SE:
				continue
			for i in range(4):
				direction = directions[(directionPos + i) % 4]
				match direction:
					case 'n':
						if not neighbors.N and not neighbors.NE and not neighbors.NW:
							newElves[elf] = (elf[0] - 1, elf[1])
							break
					case 's':
						if not neighbors.S and not neighbors.SE and not neighbors.SW:
							newElves[elf] = (elf[0] + 1, elf[1])
							break
					case 'w':
						if not neighbors.W and not neighbors.NW and not neighbors.SW:
							newElves[elf] = (elf[0], elf[1] - 1)
							break
					case 'e':
						if not neighbors.E and not neighbors.NE and not neighbors.SE:
							newElves[elf] = (elf[0], elf[1] + 1)
							break
		directionPos = (directionPos + 1) % 4

		newPositions = list(newElves.values())
		for elf,newPos in newElves.items():
			if newPositions.count(newPos) == 1:
				elves.remove(elf)
				elves.append(newPos)

	xMin = min([elf[0] for elf in elves])
	xMax = max([elf[0] for elf in elves])
	yMin = min([elf[1] for elf in elves])
	yMax = max([elf[1] for elf in elves])

	freeTiles = 0
	for x in range(xMin, xMax + 1):
		for y in range(yMin, yMax + 1):
			if (x,y) not in elves:
				freeTiles += 1

	return freeTiles

def do2(splitInput):
	elves = extractElves(splitInput)
	
	directionPos = 0

	round = 0
	while True:
		round += 1
		newElves = {}
		for elf in elves:
			neighbors = getNeighbors(elf, elves)
			if not neighbors.N and not neighbors.NE and not neighbors.NW and not neighbors.W and not neighbors.E and not neighbors.SW and not neighbors.S and not neighbors.SE:
				continue
			for i in range(4):
				direction = directions[(directionPos + i) % 4]
				match direction:
					case 'n':
						if not neighbors.N and not neighbors.NE and not neighbors.NW:
							newElves[elf] = (elf[0] - 1, elf[1])
							break
					case 's':
						if not neighbors.S and not neighbors.SE and not neighbors.SW:
							newElves[elf] = (elf[0] + 1, elf[1])
							break
					case 'w':
						if not neighbors.W and not neighbors.NW and not neighbors.SW:
							newElves[elf] = (elf[0], elf[1] - 1)
							break
					case 'e':
						if not neighbors.E and not neighbors.NE and not neighbors.SE:
							newElves[elf] = (elf[0], elf[1] + 1)
							break
		directionPos = (directionPos + 1) % 4

		newPositions = list(newElves.values())
		if not newPositions:
			return round
		for elf,newPos in newElves.items():
			if newPositions.count(newPos) == 1:
				elves.remove(elf)
				elves.append(newPos)

def extractElves(splitInput):
	elves = []
	for lineNumber,line in enumerate(splitInput):
		for position,tile in enumerate(line):
			if tile == '#':
				elves.append((lineNumber,position))
	
	return elves

def getNeighbors(elf, elves):
	elfX,elfY = elf

	neighbors = []

	for xDiff in [-1, 0, 1]:
		for yDiff in [-1, 0, 1]:
			if xDiff == 0 and yDiff == 0:
				continue
			if (elfX + xDiff, elfY + yDiff) in elves:
				neighbors.append(True)
			else:
				neighbors.append(False)
	
	return Neighbors(NW=neighbors[0],N=neighbors[1],NE=neighbors[2],W=neighbors[3],E=neighbors[4],SW=neighbors[5],S=neighbors[6],SE=neighbors[7])
	



def do():
	strInput = readInputFile(23)
	#strInput = readExampleInput(23)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day25.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from copy import deepcopy

def do1(splitInput):
	map = []
	for line in splitInput:
		newLine = [x for x in line]
		map.append(newLine)	
	
	mapLength = len(map)

	newMap = deepcopy(map)
	moving = True
	steps = 0
	southfacing = True
	while moving or not southfacing:
		southfacing = not southfacing
		moving = False
		if not southfacing:
			steps += 1
		for lineNumber,line in enumerate(map):
			lineLength = len(line)
			for position,value in enumerate(line):
				match value:
					case '.':
						continue
					case 'v':
						if southfacing:
							neighborLine = (lineNumber + 1) % mapLength
							if map[neighborLine][position] == '.':
								newMap[neighborLine][position] = 'v'
								newMap[lineNumber][position] = '.'
								moving = True
					case '>':
						if not southfacing:
							neighborPos = (position + 1) % lineLength
							if line[neighborPos] == '.':
								newMap[lineNumber][neighborPos] = '>'
								newMap[lineNumber][position] = '.'
								moving = True
		map = deepcopy(newMap)		
	
	return steps

def do2():
	return 'Nothing to do'

def do():
	strInput = readInputFile(25)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2())

	print('done')


do()<file_sep>/2020/day8.py
from HelperFunctions import inputsplit

def do1(puzzleInput):
    success, acc = execute(puzzleInput)
    
    if not success:
        return acc
    else:
        return 'error'

def do2(oldPuzzleInput):
    replacePosition = -1
    while (replacePosition < len(oldPuzzleInput)):
        replacePosition += 1
        puzzleInput = oldPuzzleInput.copy()
        
        if not replaceInstruction(replacePosition, puzzleInput):
            continue
        
        success, acc = execute(puzzleInput)

        if success:
            return acc
        
    return 'error'    

def execute(puzzleInput):
    acc = 0

    visited = [0 for x in range(len(puzzleInput))]

    position = 0
    while True:
        if position == len(puzzleInput):
            return [True, acc]
        if visited[position] == 1:
            return [False, acc]
    
        instructions = puzzleInput[position].split(' ')

        if instructions[0] == 'nop':
            visited[position] = 1
            position += 1
            continue
        if instructions[0] == 'acc':
            visited[position] = 1
            acc += int(instructions[1])
            position += 1
            continue
        if instructions[0] == 'jmp':
            visited[position] = 1
            position += int(instructions[1])
            continue

def replaceInstruction(position, puzzleInput):
    if 'acc' in puzzleInput[position]:
        return False
    else:
        instructions = puzzleInput[position].split(' ')
        if instructions[0] == 'jmp':
            puzzleInput[position] = 'nop ' + instructions[1]
        else:
            puzzleInput[position] = 'jmp ' + instructions[1]
    return True

def do():
    with open ('Input/day8.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2022/day12.py
from collections import defaultdict
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt


def do1(strInput):
	distances = defaultdict(lambda: 1000)
	unvisited = []
	visited = []
	
	startingPos,endPos,heightMap = createHeightMap(strInput.split('\n'))

	distances[startingPos] = 0
	unvisited.append((startingPos))

	findShortestPath(heightMap, visited, unvisited, distances)
	
	return distances[endPos]

def do2(strInput):
	_,endPos,heightMap = createHeightMap(strInput.split('\n'))
	
	startingPositions = []
	for lineNumber,line in enumerate(heightMap):
		for index,position in enumerate(line):
			if position == ord('a'):
				startingPositions.append((lineNumber,index))

	distancesToDestination = []

	for startingPosition in startingPositions:
		unvisited = []
		visited = []
		distances = defaultdict(lambda: 1000)
		distances[startingPosition] = 0
		unvisited.append(startingPosition)
		findShortestPath(heightMap, visited, unvisited, distances)
		distancesToDestination.append(distances[endPos])

	return min(distancesToDestination)

def createHeightMap(map):
	for lineNumber,line in enumerate(map):
		for index,position in enumerate(line):
			if position == 'S':
				startingPos = (lineNumber,index)
			elif position == 'E':
				endPos = (lineNumber, index)
	
	heightMap = [[ord(x) for x in y] for y in map]
	heightMap[startingPos[0]][startingPos[1]] = ord('a')
	heightMap[endPos[0]][endPos[1]] = ord('z')

	return (startingPos, endPos, heightMap)

def findShortestPath(heightMap, visited, unvisited, distances):
	while unvisited:
		currentPos = None
		currentDistance = 0
		for position in unvisited:
			if currentPos == None:
				currentPos = position
				currentDistance = distances[position]
			elif distances[position] < distances[currentPos]:
				currentPos = position
				currentDistance = distances[position]
		
		neighbors = getPossibleNeighbors(currentPos, heightMap)
		for neighbor in neighbors:
			if neighbor not in visited and neighbor not in unvisited:
				unvisited.append(neighbor)
			if distances[neighbor] > currentDistance + 1:
				distances[neighbor] = currentDistance + 1
		
		visited.append(currentPos)
		unvisited.remove(currentPos)

def getPossibleNeighbors(position, map):
	possibleNeighbors = []
	line,index = position
	currentHeight = map[line][index]
	if line - 1 >= 0 and map[line-1][index] <= currentHeight + 1:
		possibleNeighbors.append((line-1,index))
	if line + 1 < len(map) and map[line+1][index] <= currentHeight + 1:
		possibleNeighbors.append((line+1,index))
	if index + 1 < len(map[0]) and map[line][index+1] <= currentHeight + 1:
		possibleNeighbors.append((line,index+1))
	if index - 1 >= 0 and map[line][index-1] <= currentHeight + 1:
		possibleNeighbors.append((line,index-1))
	
	return possibleNeighbors

def do():
	strInput = readInputFile(12)

	print(do1(strInput))
	print(do2(strInput))

	print('done')


do()<file_sep>/2022/day8.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	visibleTrees = 0
	for linePos,line in enumerate(splitInput):
		for position,_ in enumerate(line):
			if onlySmallerTrees(linePos,position,splitInput):
				visibleTrees += 1
	return visibleTrees

def do2(splitInput):
	scenicScores = []

	for linePos,line in enumerate(splitInput):
		for position,_ in enumerate(line):
			scenicScores.append(calculateScenicScore(linePos,position,splitInput))

	return max(scenicScores)

def onlySmallerTrees(linePos, position, map):
	tree = map[linePos][position]
	
	#left
	otherTrees = [x for x in map[linePos][0:position] if x >= tree]
	if not otherTrees:
		return True

	#right
	otherTrees = [x for x in map[linePos][position + 1:] if x >= tree]
	if not otherTrees:
		return True

	#up
	otherTrees = [x[position] for x in map[0:linePos] if x[position] >= tree]
	if not otherTrees:
		return True

	#down
	otherTrees = [x[position] for x in map[linePos+1:] if x[position] >= tree]
	if not otherTrees:
		return True

def calculateScenicScore(linePos,position,map):
	tree = map[linePos][position]
	
	#right
	scoreRight = 0
	for i in range(position + 1, len(map[linePos])):
		scoreRight += 1
		if map[linePos][i] >= tree:
			break
	
	#left
	scoreLeft = 0
	for i in range(position - 1, -1, -1):
		scoreLeft += 1
		if map[linePos][i] >= tree:
			break
	
	#down
	scoreDown = 0
	for i in range(linePos + 1, len(map)):
		scoreDown += 1
		if map[i][position] >= tree:
			break
	
	#up
	scoreUp = 0
	for i in range(linePos - 1, -1, -1):
		scoreUp += 1
		if map[i][position] >= tree:
			break
	
	return scoreRight * scoreLeft * scoreDown * scoreUp

def do():
	strInput = readInputFile(8)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2022/day13.py
import ast
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	rightOrderPairs = 0
	
	for index,pair in enumerate(splitInput):
		left,right = pair.split('\n')
		left = ast.literal_eval(left)
		right = ast.literal_eval(right)

		successful,result = compare(left,right)
		if successful and result:
			rightOrderPairs += index + 1		
	
	return rightOrderPairs

def do2(strInput):
	result = []
	
	strInput = strInput.replace('\n\n', '\n')
	splitInput = strInput.split('\n')
	splitInput.append('[[2]]')
	splitInput.append('[[6]]')

	first = ast.literal_eval(splitInput[0])
	result.append(first)

	for line in splitInput[1:]:
		inserted = False
		new = ast.literal_eval(line)
		for index,old in enumerate(result):
			successful,rightOrder = compare(old,new)
			if successful and not rightOrder:
				result.insert(index,new)
				inserted = True
				break
		if not inserted:
			result.append(new)		

	return (result.index([[2]]) + 1) * (result.index([[6]]) + 1) 

def compare(left,right):
	leftLength = len(left)
	rightLength = len(right)
	
	i = -1
	while True:
		i += 1
		if leftLength < i + 1 and rightLength >= i + 1:
			return True,True
		elif rightLength < i + 1 and leftLength >= i + 1:
			return True,False
		elif leftLength < i + 1 and rightLength < i + 1:
			return False,False
		leftPart = left[i]
		rightPart = right[i]

		if type(leftPart) == type(rightPart):
			if type(leftPart) is int:
					if leftPart < rightPart:
						return True,True
					elif rightPart < leftPart:
						return True,False
					else:
						continue
			elif type(leftPart) is list:
					successful,result = compare(leftPart,rightPart)
					if successful:
						return True,result
					else:
						continue
		if type(leftPart) is int:
			leftPart = [leftPart]
		else:
			rightPart = [rightPart]
		successful,result = compare(leftPart,rightPart)
		if successful:
			return True,result
		else:
			continue

def do():
	strInput = readInputFile(13)

	splitInput = strInput.split('\n\n')

	print(do1(splitInput))
	print(do2(strInput))

	print('done')


do()<file_sep>/2022/day10.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

image = []

def do1(splitInput):
	signalStrengths = []
	cycle = 0
	x = 1
	for line in splitInput:
		cycle += 1
		if cycle == 20 or (cycle-20) % 40 == 0:
			signalStrengths.append(x * cycle)
		match line.split(' '):
			case ['addx', value]:
				cycle += 1
				if cycle == 20 or (cycle-20) % 40 == 0:
					signalStrengths.append(x * cycle)
				x = x + int(value)
	
	return sum(signalStrengths)

def do2(splitInput):
	spritePos = 1
	cycle = 0
	for line in splitInput:
		cycle += 1
		draw(spritePos, cycle)
		match line.split(' '):
			case ['addx', value]:
				cycle += 1
				draw(spritePos, cycle)
				spritePos += int(value)
	
	for line in image:
		print(line)
	return 'done'

def draw(spritePos, cycle):
	line = int((cycle - 1) / 40)
	if len(image) < line + 1:
		image.append(['.' for x in range(40)])
	position = (cycle - 1) % 40
	if position in [spritePos-1,spritePos,spritePos+1]:
		image[line][position] = '#'

def do():
	strInput = readInputFile(10)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2018/day6.py
input = """118, 274
102, 101
216, 203
208, 251
309, 68
330, 93
91, 179
298, 278
201, 99
280, 272
141, 312
324, 290
41, 65
305, 311
198, 68
231, 237
164, 224
103, 189
216, 207
164, 290
151, 91
166, 250
129, 149
47, 231
249, 100
262, 175
299, 237
62, 288
228, 219
224, 76
310, 173
80, 46
312, 65
183, 158
272, 249
57, 141
331, 191
163, 359
271, 210
142, 137
349, 123
55, 268
160, 82
180, 70
231, 243
133, 353
246, 315
164, 206
229, 97
268, 94"""

import string
import re

def nearest(coordinates, dic):
    xpoint,ypoint = coordinates
    nearestDistance = 10000
    result = 0
    for entry in dic:
        x,y = dic[entry]
        distance = abs(x - xpoint) + abs(y - ypoint) 
        if distance < nearestDistance:
            nearestDistance = distance
            result = entry
        elif distance == nearestDistance:
            result = 0
    return result

def nearEnough(coordinates, dic):
    xpoint,ypoint = coordinates
    maxDistance = 10000
    distanceSum = 0
    for entry in dic:
        x,y = dic[entry]
        distanceSum += abs(x - xpoint) + abs(y - ypoint)
        if distanceSum >= maxDistance:
            return False
        
    return True
    

def doOne():
    splitInput = input.split('\n')
    dic ={}
    count = 1
    for coordinates in splitInput:
        dic[count] = [int(x) for x in re.findall('[0-9]+', coordinates)]
        count += 1

    width, height = 350, 370
    matrix = [[0 for x in range(width)] for y in range(height)]

    resultdic = {}

    for x in range(width):
        for y in range(height):
            near = nearest([x,y], dic)
            matrix[y][x] = near
            if near not in resultdic:
                resultdic[near] = 0
            
            if x == width - 1 or y == height - 1 or x == 0 or y == 0:
                resultdic[near] = -1

            if resultdic[near] != -1:
                resultdic[near] += 1   
    
    
    return resultdic

def doTwo():
    splitInput = input.split('\n')
    dic ={}
    count = 1
    for coordinates in splitInput:
        dic[count] = [int(x) for x in re.findall('[0-9]+', coordinates)]
        count += 1

    width, height = 500, 500
    matrix = [[0 for x in range(width)] for y in range(height)]

    result = 0

    for x in range(width):
        for y in range(height):
            nearenough = nearEnough([x,y], dic)
            if nearenough:
              result += 1

    return result  

print(max(doOne().values()))

print(doTwo())<file_sep>/2020/day23.py
from collections import deque

def do1(puzzleInput):
    queue = deque([int(x) for x in puzzleInput])

    play(queue, 100)

    return cupOrder(queue)

def do2(puzzleInput):
    queue = [int(x) for x in puzzleInput] + list(range(10, 1000000+1))
    
    linkedList = play2(queue, 10000000)

    return findStars(linkedList)

def cupOrder(queue):
    result = ''

    first = queue.index(1)
    queue.rotate(-(first + 1))

    for _ in range(len(queue) - 1):
        result += str(queue.popleft())

    return result

def findStars(linkedList):
    first = linkedList[1]
    second = linkedList[first]

    return first * second

def play(queue, turns):
    maxValue = max(queue)
    minValue = min(queue)

    for _ in range(1, turns + 1):
        currentElement = queue.popleft()
        removed = [queue.popleft(), queue.popleft(), queue.popleft()]

        newElement = currentElement - 1

        if newElement < minValue:
            newElement = maxValue

        while newElement in removed:
            newElement -= 1
            if newElement < minValue:
                newElement = maxValue
        newIndex = queue.index(newElement)

        queue.rotate(- (newIndex + 1))
        queue.extendleft(removed[::-1])
        queue.rotate(newIndex + 1)

        queue.append(currentElement)

def play2(queue, turns):
    maxValue = max(queue)
    minValue = min(queue)
    
    linkedList = {}

    for index,item in enumerate(queue[0:-1]):
        linkedList[item] = queue[index + 1]
    linkedList[queue[-1]] = queue[0]

    currentIndex = queue[-1]

    for _ in range(1, turns + 1):
        currentElement = linkedList[currentIndex]
        removed = [linkedList[currentElement], linkedList[linkedList[currentElement]], linkedList[linkedList[linkedList[currentElement]]]]
        nextafternextafternext = removed[-1]
        newElement = currentElement - 1

        if newElement < minValue:
            newElement = maxValue
        while newElement in removed:
            newElement -= 1
            if newElement < minValue:
                newElement = maxValue

        tmp1 = linkedList[newElement]
        tmp2 = linkedList[nextafternextafternext]
        linkedList[newElement] = linkedList[currentElement]
        linkedList[nextafternextafternext] = tmp1
        linkedList[currentElement] = tmp2

        currentIndex = currentElement
        
    return linkedList

def do():
    with open ('Input/day23.txt') as f:
        strInput = f.read()

    print(do1(strInput))
    print(do2(strInput))
    
do()<file_sep>/2022/day11.py
from copy import deepcopy
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re

class Monkey:
	def __init__(self, items, operation, value, testMethod, throwIfTrue, throwIfFalse):
		self.items = items
		self.operation = operation
		self.value = value
		self.testMethod = testMethod
		self.throwIfTrue = throwIfTrue
		self.throwIfFalse = throwIfFalse
		self.inspectedItems = 0
	
	def addItem(self, item):
		self.items.append(item)

originalMonkeys = []

def multiply(value, old):
	return old * value
def add(value, old):
	return old + value
def multiplyWithItself(old,value):
	return old * old

def do1(splitInput):
	createMonkeys(splitInput)	
	
	monkeys = deepcopy(originalMonkeys)

	for _ in range(20):
		monkeyIndex = 0
		for _ in range(len(monkeys)):
			currentMonkey = monkeys[monkeyIndex]
			while currentMonkey.items:
				currentMonkey.inspectedItems += 1
				item = currentMonkey.items.pop(0)
				item = currentMonkey.operation(value=currentMonkey.value, old=item)
				item = int(item / 3)
				if item % currentMonkey.testMethod == 0:
					monkeys[currentMonkey.throwIfTrue].addItem(item)
				else:
					monkeys[currentMonkey.throwIfFalse].addItem(item)
			monkeyIndex += 1
	
	inspectedItems = [x.inspectedItems for x in monkeys]
	inspectedItems.sort(reverse=True)

	return inspectedItems[0] * inspectedItems[1]

def do2(splitInput):
	monkeys = deepcopy(originalMonkeys)
	
	divisor = 1
	for monkey in monkeys:
		divisor *= monkey.testMethod

	for _ in range(10000):
		monkeyIndex = 0
		for _ in range(len(monkeys)):
			currentMonkey = monkeys[monkeyIndex]
			while currentMonkey.items:
				currentMonkey.inspectedItems += 1
				item = currentMonkey.items.pop(0)
				item = currentMonkey.operation(value=currentMonkey.value, old=item)
				item = item - (int(item / divisor) * divisor)
				if item % currentMonkey.testMethod == 0:
					monkeys[currentMonkey.throwIfTrue].addItem(item)
				else:
					monkeys[currentMonkey.throwIfFalse].addItem(item)
			monkeyIndex += 1
	
	inspectedItems = [x.inspectedItems for x in monkeys]
	inspectedItems.sort(reverse=True)

	return inspectedItems[0] * inspectedItems[1]

def createMonkeys(splitInput):
	for monkey in splitInput:
		lines = monkey.split('\n')
		startingItems = [int(x[0:2]) for x in lines[1].split(' ')[4:]]
		match lines[2].split(' '):
			case [*stuff, '*', 'old']:
				operation = multiplyWithItself
				value = 0
			case [*stuff, '*', value]:
				operation = multiply
				value = int(value)
			case [*stuff, '+', value]:
				operation = add
				value = int(value)
		matchTest = re.match('  Test: divisible by (\d+)', lines[3])
		testMethod = int(matchTest.groups()[0])
		throwIfTrue = int(lines[4][-1])
		throwIfFalse = int(lines[5][-1])

		originalMonkeys.append(Monkey(startingItems, operation, value, testMethod, throwIfTrue, throwIfFalse))

def do():
	strInput = readInputFile(11)

	splitInput = strInput.split('\n\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2022/day14.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	map = buildWalls(splitInput)
	sand = set()

	rested,restingPos = letTheSandFall(map, sand)
	while rested:
		sand.add(restingPos)
		rested,restingPos = letTheSandFall(map, sand)

	return len(sand)

def do2(splitInput):
	map = buildWalls(splitInput)
	sand = set()

	highestY = max([x[1] for x in map])
	# add floor
	for x in range(-1000, 1000+1):
		map.add((x, highestY + 2))

	rested,restingPos = letTheSandFall(map, sand)
	while rested:
		sand.add(restingPos)
		if restingPos == (500,0):
			break
		rested,restingPos = letTheSandFall(map, sand)

	return len(sand)

def buildWalls(splitInput):
	map = set()
	for line in splitInput:
		parts = line.split(' -> ')
		for i in range(1, len(parts)):
			startX,startY = [int(x) for x in parts[i].split(',')]
			endX,endY = [int(x) for x in parts[i-1].split(',')]

			if startY == endY:
				x = sorted([startX, endX])
				for j in range(x[0], x[1] + 1):
					map.add((j, startY))
			else:
				y = sorted([startY, endY])
				for j in range(y[0], y[1] + 1):
					map.add((startX, j))
		
	return map

def letTheSandFall(map, sand):
	boundaryLeft = min([x[0] for x in map])
	boundaryRight = max([x[0] for x in map])
	
	sandStart = (500,0)
	position = sandStart
	while True:
		newPosition = (position[0], position[1] + 1)
		if newPosition in map or newPosition in sand:
			# diagonally left
			if (newPosition[0] - 1, newPosition[1]) in map or (newPosition[0] - 1, newPosition[1]) in sand:
				# diagonally right
				if (newPosition[0] + 1, newPosition[1]) in map or (newPosition[0] + 1, newPosition[1]) in sand:
					return True,position
				else:
					position = (position[0] + 1, position[1] + 1)
					if position[0] > boundaryRight:
						return False,(0,0)
					continue
			else:
				position = (position[0] - 1, position[1] + 1)
				if position[0] < boundaryLeft:
						return False,(0,0)
				continue
		else:
			position = newPosition

def do():
	strInput = readInputFile(14)

	splitInput = strInput.split('\n')
	
	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2022/day18.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	cubes = extractCubes(splitInput)
	openSides = 0
	for x,y,z in cubes:
		sides = 6
		for oX,oY,oZ in cubes:
			if oX == x and oY == y and abs(oZ - z) == 1:
				sides -= 1
			elif oX == x and oZ == z and abs(oY - y) == 1:
				sides -= 1
			elif oY == y and oZ == z and abs(oX - x) == 1:
				sides -= 1
		openSides += sides		

	return openSides

def do2(splitInput):
	cubes = extractCubes(splitInput)
	maxX = max(x for x,y,z in cubes) + 1
	maxY = max(y for x,y,z in cubes) + 1
	maxZ = max(z for x,y,z in cubes) + 1

	sides = 0
	newAir = set()
	newAir.add((maxX,maxY,maxZ))
	visitedAir = set()

	while len(newAir) > 0:
		cube = newAir.pop()
		cubeNeighbors,airNeighbors = getNeighbors(cube,cubes,maxX,maxY,maxZ,visitedAir)
		sides += len(cubeNeighbors)
		newAir = newAir.union(airNeighbors)
		visitedAir.add(cube)
	return sides

def extractCubes(splitInput):
	cubes = set()
	for line in splitInput:
		cube = [int(x) for x in line.split(',')]
		cubes.add((cube[0], cube[1], cube[2]))
	return cubes

def getNeighbors(cube, cubes, maxX, maxY, maxZ, visitedAir):
	cubeNeighbors = set()
	airNeighbors = set()
	cubeX,cubeY,cubeZ = cube
	if cubeX - 1 >= -1:
		if (cubeX - 1, cubeY, cubeZ) in cubes:
			cubeNeighbors.add((cubeX - 1, cubeY, cubeZ))
		elif (cubeX - 1, cubeY, cubeZ) not in visitedAir:
			airNeighbors.add((cubeX - 1, cubeY, cubeZ))
	if cubeX + 1 <= maxX:
		if (cubeX + 1, cubeY, cubeZ) in cubes:
			cubeNeighbors.add((cubeX + 1, cubeY, cubeZ))
		elif (cubeX + 1, cubeY, cubeZ) not in visitedAir:
			airNeighbors.add((cubeX + 1, cubeY, cubeZ))
	if cubeY - 1 >= -1:
		if (cubeX, cubeY - 1, cubeZ) in cubes:
			cubeNeighbors.add((cubeX, cubeY - 1, cubeZ))
		elif (cubeX, cubeY - 1, cubeZ) not in visitedAir:
			airNeighbors.add((cubeX, cubeY - 1, cubeZ))
	if cubeY + 1 <= maxY:
		if (cubeX, cubeY + 1, cubeZ) in cubes:
			cubeNeighbors.add((cubeX, cubeY + 1, cubeZ))
		elif (cubeX, cubeY + 1, cubeZ) not in visitedAir:
			airNeighbors.add((cubeX, cubeY + 1, cubeZ))
	if cubeZ - 1 >= -1:
		if (cubeX, cubeY, cubeZ - 1) in cubes:
			cubeNeighbors.add((cubeX, cubeY, cubeZ - 1))
		elif (cubeX, cubeY, cubeZ - 1) not in visitedAir:
			airNeighbors.add((cubeX, cubeY, cubeZ - 1))
	if cubeZ + 1 <= maxZ:
		if (cubeX, cubeY, cubeZ + 1) in cubes:
			cubeNeighbors.add((cubeX, cubeY, cubeZ + 1))
		elif (cubeX, cubeY, cubeZ + 1) not in visitedAir:
			airNeighbors.add((cubeX, cubeY, cubeZ + 1))
	
	return cubeNeighbors,airNeighbors


def do():
	strInput = readInputFile(18)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day24.py
from HelperFunctions import inputsplit
from copy import deepcopy

directions = {'e': (1,-1,0), 'w': (-1,1,0), 'se': (0,-1,1), 'sw': (-1,0,1), 'ne': (1,0,-1), 'nw': (0,1,-1)}

def do1(puzzleInput):
    tiles = set()
    
    rotate(puzzleInput, tiles)

    return len(tiles)    

def do2(puzzleInput):
    tiles = set()
    
    rotate(puzzleInput, tiles)

    newTiles = gameOfLife(tiles, 100)
    
    return len(newTiles)

def rotate(puzzleInput, tiles):
    for line in puzzleInput:
        tile = (0,0,0)
        direction = ''
        for thing in line:
            direction += thing
            if direction in directions:
                xStep,yStep,zStep = directions[direction]
                x,y,z = tile
                tile = (x + xStep, y + yStep, z + zStep)
                direction = ''
        if tile in tiles:
            tiles.remove(tile)
        else:
            tiles.add(tile)

def gameOfLife(tiles, rounds):
    newTiles = deepcopy(tiles)
    for _ in range(rounds):
        tiles = deepcopy(newTiles)
        neighbors = set()
        for tile in tiles:
            allNeighbors = getNeighbors(tile, tiles)
            neighbors = neighbors.union(allNeighbors)
            blackNeighbors = countBlackNeighbors(allNeighbors, tiles)
            if blackNeighbors == 0 or blackNeighbors > 2:
                newTiles.remove(tile)
        for neighbor in neighbors:
            if neighbor in tiles:
                continue
            blackNeighbors = countBlackNeighbors(getNeighbors(neighbor, tiles), tiles)
            if blackNeighbors == 2:
                newTiles.add(neighbor)    
    return newTiles

def getNeighbors(tile, tiles):
    x,y,z = tile
    
    neighbors = set([(x + xStep, y + yStep, z + zStep) for xStep,yStep,zStep in directions.values()])

    return neighbors

def countBlackNeighbors(neighbors, tiles):
    count = len([neighbor for neighbor in neighbors if neighbor in tiles])
    return count

def do():
    with open ('Input/day24.txt') as f:
        strInput = f.read()

    puzzleInput = strInput.split('\n')

    print(do1(puzzleInput))
    print(do2(puzzleInput))
    
do()<file_sep>/2021/day17.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(xRange, yRange):
	xMin,xMax = convertToInt(xRange.split(','))
	yMin,yMax = convertToInt(yRange.split(','))

	maxY = -100000

	for xVel in range(1, xMax + 1):
		for yVel in range(0, 200):
			currentMaxY = fly((0,0), (xVel,yVel), (xMin,xMax), (yMin, yMax))
			maxY = max(maxY, currentMaxY)
	
	return maxY

def do2(xRange, yRange):
	xMin,xMax = convertToInt(xRange.split(','))
	yMin,yMax = convertToInt(yRange.split(','))

	landingVels = []

	for xVel in range(1, xMax + 1):
		for yVel in range(-100, 200):
			currentMaxY = fly((0,0), (xVel,yVel), (xMin,xMax), (yMin, yMax))
			if currentMaxY != -1000000:
				landingVels.append((xVel,yVel))

	return len(landingVels)

def step(xPos, yPos, xVel, yVel):

	xPos = xPos + xVel
	yPos = yPos + yVel
	if xVel > 0:
		xVel -= 1
	elif xVel < 0:
		xVel += 1
	yVel -= 1

	return (xPos, yPos, xVel, yVel)

def fly(position, velocity, targetX, targetY):
	maxY = -1000000
	x,y = position
	xVel,yVel = velocity
	yMin,_ = targetY

	while True:	
		x,y,xVel,yVel = step(x, y, xVel, yVel)
		maxY = max(maxY, y)
		if isInTargetArea((x, y), targetX, targetY):
			return maxY
		if y < yMin and yVel <= 0:
			return -1000000		

def isInTargetArea(position, targetX, targetY):
	x,y = position
	xMin,xMax = targetX
	yMin, yMax = targetY

	if xMin <= x <= xMax and yMin <= y <= yMax:
		return True
	
	return False

def do():
	strInput = readInputFile(17)

	xRange,yRange = strInput.split('\n')

	print(do1(xRange,yRange))
	print(do2(xRange,yRange))

	print('done')


do()<file_sep>/2021/day20.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from copy import deepcopy

def do1(enhancement,image):
	extendedImage = prepareImage(image, 10)
	
	newImage = imageEnhancement(extendedImage, enhancement, 2)
				
	return getNumberOfLitPixels(newImage)

def do2(enhancement,image):
	extendedImage = prepareImage(image, 100)
	
	newImage = imageEnhancement(extendedImage, enhancement, 50)
				
	return getNumberOfLitPixels(newImage)

def getNumberOfLitPixels(image):
	litPixels = 0
	for line in image:
		litPixels += len([x for x in line if x == '#'])

	return litPixels

def imageEnhancement(image, enhancement, repetitions):
	for _ in range(repetitions):
		image = enhanceImage(image, enhancement)
		newImage = []
		for lineNumber,line in enumerate(image):
			if lineNumber == 0 or lineNumber == len(image) - 1:
				continue
			newImage.append(line[1:-1])
		image = deepcopy(newImage)
	
	return image

def enhanceImage(image, enhancement):
	newImage = deepcopy(image)

	for lineNumber,line in enumerate(image):
		if lineNumber == 0 or lineNumber == len(image) - 1:
			continue
		for position,_ in enumerate(line):
			if position == 0 or position == len(line) - 1:
				continue
		
			neighbors = getNeighbors(image, lineNumber, position)
			pixels = ''
			for neighbor in neighbors:
				pixels += str(neighbor)
			index = int(pixels, 2)
			enhancementPixel = enhancement[index]

			newImage[lineNumber][position] = enhancementPixel
	
	return newImage

def getNeighbors(image, lineNumber, position):
	neighbors = []

	for lineDiff in [-1,0,1]:
		for posDiff in [-1,0,1]:
			neighbors.append(image[lineNumber + lineDiff][position + posDiff])

	neighbors = [0 if x == '.' else 1 for x in neighbors]
	return neighbors

def prepareImage(image, additionSize):
	newImage = []
	emptyLine = ['.' for x in range(additionSize)] + ['.' for x in range(len(image[0]))] + ['.' for x in range(additionSize)]
	for _ in range(additionSize):
		newImage.append(deepcopy(emptyLine))
	for line in image:
		newImage.append(['.' for x in range(additionSize)] + [x for x in line] + ['.' for x in range(additionSize)])	
	for _ in range(additionSize):
		newImage.append(deepcopy(emptyLine))
	
	return newImage

def do():
	strInput = readInputFile(20)

	enhancement,image = strInput.split('\n\n')
	image = image.split('\n')

	print(do1(enhancement,image))
	print(do2(enhancement,image))

	print('done')


do()<file_sep>/2019/day12.py
import re

input = """<x=14, y=2, z=8>
<x=7, y=4, z=10>
<x=1, y=17, z=16>
<x=-4, y=-1, z=1>"""


def do():
    splitInput = input.split('\n')

    moons = getMoons(splitInput)

    simulate(moons, 1000)

    energy = calculateEnergy(moons)

    return energy

def do2():
    splitInput = input.split('\n')

    moons = getMoons(splitInput)

    steps = simulateEndless(moons)

    return steps

def getMoons(splitInput):
    moons = {}
    for i in range(len(splitInput)):
        moons[i] = {}
        moon = splitInput[i]
        match = re.match('<x=([-]?[0-9]+), y=([-]?[0-9]+), z=([-]?[0-9]+)>', moon)

        positionX, positionY, positionZ = [int(x) for x in match.groups()]

        moons[i]['posX'] = positionX
        moons[i]['posY'] = positionY
        moons[i]['posZ'] = positionZ
        moons[i]['velX'] = 0
        moons[i]['velY'] = 0
        moons[i]['velZ'] = 0

    return moons

def simulate(moons, time):
    for i in range(time):
        for observedMoon in moons.keys():
            for otherMoon in moons.keys():
                #x
                if moons[observedMoon]['posX'] < moons[otherMoon]['posX']:
                    moons[observedMoon]['velX'] += 1
                elif moons[observedMoon]['posX'] > moons[otherMoon]['posX']:
                    moons[observedMoon]['velX'] -= 1
                #y
                if moons[observedMoon]['posY'] < moons[otherMoon]['posY']:
                    moons[observedMoon]['velY'] += 1
                elif moons[observedMoon]['posY'] > moons[otherMoon]['posY']:
                    moons[observedMoon]['velY'] -= 1
                #z
                if moons[observedMoon]['posZ'] < moons[otherMoon]['posZ']:
                    moons[observedMoon]['velZ'] += 1
                elif moons[observedMoon]['posZ'] > moons[otherMoon]['posZ']:
                    moons[observedMoon]['velZ'] -= 1
        moveMoons(moons)
    return moons

def simulateEndless(moons):
    steps = 0
    while True:
        for observedMoon in moons.keys():
            for otherMoon in moons.keys():
                #x
                if moons[observedMoon]['posX'] < moons[otherMoon]['posX']:
                    moons[observedMoon]['velX'] += 1
                elif moons[observedMoon]['posX'] > moons[otherMoon]['posX']:
                    moons[observedMoon]['velX'] -= 1
                #y
                if moons[observedMoon]['posY'] < moons[otherMoon]['posY']:
                    moons[observedMoon]['velY'] += 1
                elif moons[observedMoon]['posY'] > moons[otherMoon]['posY']:
                    moons[observedMoon]['velY'] -= 1
                #z
                if moons[observedMoon]['posZ'] < moons[otherMoon]['posZ']:
                    moons[observedMoon]['velZ'] += 1
                elif moons[observedMoon]['posZ'] > moons[otherMoon]['posZ']:
                    moons[observedMoon]['velZ'] -= 1
        moveMoons(moons)
        steps += 1
        if moons[0]['posX'] == 14 and moons[1]['posX'] == 7 and moons[2]['posX'] == 1 and moons[3]['posX'] == -4 and moons[0]['posY'] == 2 and moons[1]['posY'] == 4 and moons[2]['posY'] == 17 and moons[3]['posY'] == -1:
            print(steps)
            break
    return steps

def moveMoons(moons):
    for moon in moons.keys():
        moons[moon]['posX'] += moons[moon]['velX']
        moons[moon]['posY'] += moons[moon]['velY']
        moons[moon]['posZ'] += moons[moon]['velZ']

def calculateEnergy(moons):
    totalEnergy = 0
    for moon in moons.keys():
        potentialEnergy = 0
        kineticEnergy = 0
        potentialEnergy += abs(moons[moon]['posX'])
        potentialEnergy += abs(moons[moon]['posY'])
        potentialEnergy += abs(moons[moon]['posZ'])

        kineticEnergy += abs(moons[moon]['velX'])
        kineticEnergy += abs(moons[moon]['velY'])
        kineticEnergy += abs(moons[moon]['velZ'])

        moons[moon]['energy'] = potentialEnergy * kineticEnergy
        totalEnergy += potentialEnergy * kineticEnergy
    return totalEnergy

#part1
#print(do())

#part2
print(do2())<file_sep>/2020/day15.py
from HelperFunctions import inputsplit
from HelperFunctions import convertToInt

def do1(puzzleInput):
    numbers, lastNumber = prepareInput(puzzleInput)
        
    resultNumber = play(numbers, lastNumber, 2020)
    
    return resultNumber

def do2(puzzleInput):
    numbers, lastNumber = prepareInput(puzzleInput)
        
    resultNumber = play(numbers, lastNumber, 30000000)
    
    return resultNumber

def prepareInput(puzzleInput):
    intNumbers = convertToInt(puzzleInput)

    numbers = {}

    for i, number in enumerate(intNumbers):
        numbers[number] = [1, [i + 1]]
        lastNumber = number
    
    return [numbers, lastNumber]

def play(numbers, lastNumber, maxIterations):
    i = 1 + numbers[lastNumber][1][-1]
    while (i < maxIterations + 1):
        oldLastNumber = lastNumber
   
        if numbers[oldLastNumber][0] == 1:
            lastNumber = 0
        else:
            lastNumber = numbers[oldLastNumber][1][-1] - numbers[oldLastNumber][1][-2]
        
        if lastNumber not in numbers.keys():
            numbers[lastNumber] = [0, []]

        numbers[lastNumber][0] += 1
        numbers[lastNumber][1].append(i)
        numbers[lastNumber][1] = numbers[lastNumber][1][-2:]
        
        i += 1
    return lastNumber    

def do():
    with open ('Input/day15.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, ',')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2021/day9.py
from types import CodeType
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	map, _ = generateMap(splitInput)
	lowPoints = []
	
	for lineNumber,line in enumerate(map):
		for position,height in enumerate(line):
			if height == 9:
				continue
			if line[position - 1] <= height:
				continue
			if line[position + 1] <= height:
				continue
			if map[lineNumber - 1][position] <= height:
				continue
			if map[lineNumber + 1][position] <= height:
				continue
			lowPoints.append(height)
	
	riskLevels = [x + 1 for x in lowPoints]
	
	return sum(riskLevels)

def do2(splitInput):
	map,basins = generateMap(splitInput)
	
	basinNumber = 0
	for lineNumber,line in enumerate(map):
		for position,height in enumerate(line):
			if height == 9:
				continue
			if basins[lineNumber][position] != -1:
				continue
			search(lineNumber, position, map, basins, basinNumber)
			basinNumber += 1

	count = {}
	for i in range(basinNumber):
		sumI = 0
		for line in basins:
			sumI += len([x for x in line if x == i])
		count[i] = sumI
	
	maxBassins = [x for x in sorted(count.values(), reverse=True)][0:3]

	return maxBassins[0] * maxBassins[1] * maxBassins[2]

def generateMap(splitInput):
	map = []
	basins = []
	map.append([9] + [9 for x in splitInput[0]] + [9])
	basins.append([-1] + [-1 for x in splitInput[0]] + [-1])
	for line in splitInput:
		bassinLine = [-1] + [-1 for x in line] + [-1]
		intLine = [9] + convertToInt(line) + [9]
		map.append(intLine)
		basins.append(bassinLine)
	map.append([9] + [9 for x in splitInput[0]] + [9])
	basins.append([-1] + [-1 for x in splitInput[0]] + [-1])

	return (map,basins)

def search(line, position, map, basins, bassinNumber):
	currentHeight = map[line][position]
	while currentHeight != 9:
		if basins[line][position] != -1 and basins[line][position] != bassinNumber:
			print('Something is wrong')
			return		
		if basins[line][position] == bassinNumber:
			return
		basins[line][position] = bassinNumber
		search(line - 1, position, map, basins, bassinNumber)
		search(line + 1, position, map, basins, bassinNumber)
		search(line, position - 1, map, basins, bassinNumber)
		search(line, position + 1, map, basins, bassinNumber)

def do():
	strInput = readInputFile(9)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2022/day17.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

rocks = {0:[(0,0),(1,0),(2,0),(3,0)], 1:[(1,0),(0,1),(1,1),(2,1),(1,2)], 2:[(0,0),(1,0),(2,0),(2,1),(2,2)], 3:[(0,0),(0,1),(0,2),(0,3)], 4:[(0,0),(0,1),(1,0),(1,1)]}

def do1(movement):
	rockPositions = set([(0,0),(1,0),(2,0),(3,0),(4,0),(5,0),(6,0)])
	position = 0
	floor = 0
	fallenRocks = 0
	while fallenRocks <	2022:
		rock = rocks[fallenRocks % 5]
		leftCorner = (2,floor + 4)
		falling = True
		while falling:
			leftCorner = getPushed(movement[position], rockPositions, leftCorner, rock)
			position = (position + 1) % len(movement) 
			falling,leftCorner = fallDown(leftCorner, rockPositions, rock)
		fallenRocks += 1
		leftCornerX,leftCornerY = leftCorner
		for rockPartX,rockPartY in rock:
			rockPositions.add((leftCornerX + rockPartX, leftCornerY + rockPartY))
			floor = max(floor, leftCornerY + rockPartY)
	return max([y for (x,y) in rockPositions])

def getPushed(movement, rockPositions, leftCorner, rock):
	leftCornerX,leftCornerY = leftCorner
	match movement:
		case '<':
			leftCornerX -= 1
			for rockPartX,rockPartY in rock:
				if (leftCornerX + rockPartX,leftCornerY + rockPartY) in rockPositions or leftCornerX + rockPartX < 0:
					return leftCorner
			return (leftCornerX,leftCornerY)
		case '>':
			leftCornerX += 1
			for rockPartX,rockPartY in rock:
				if (leftCornerX + rockPartX,leftCornerY + rockPartY) in rockPositions or leftCornerX + rockPartX > 6:
					return leftCorner
			return (leftCornerX,leftCornerY)

def fallDown(leftCorner, rockPositions, rock):
	leftCornerX,leftCornerY = leftCorner
	leftCornerY -= 1
	for rockPartX,rockPartY in rock:
		if (leftCornerX + rockPartX,leftCornerY + rockPartY) in rockPositions:
			return False,leftCorner
	return True,(leftCornerX,leftCornerY)

def do2(movement):
	#cycle starts at position = 9 with 1720 fallen rocks and floor height = 2691, floor difference from cycle to cycle is +2728 with 1725 new rocks
	#missing rocks to reach 1000000000000 are 1605 which have a height of 2524 

	return 2691 + (int((1000000000000-1720) / 1725)) * 2728 + 2524

def do():
	strInput = readInputFile(17)

	print(do1(strInput))
	print(do2(strInput))

	print('done')


do()<file_sep>/2020/day12.py
from HelperFunctions import inputsplit
from enum import Enum

def do1(puzzleInput):
    east = 0
    north = 0
    direction = 0

    for movement in puzzleInput:
        action = movement[0]
        count = int(movement[1:])
        east, north, direction = move(east, north, action, count, direction)
    
    return abs(north) + abs(east)

def do2(puzzleInput):
    wayNorth = 1
    wayEast = 10

    east = 0
    north = 0

    for movement in puzzleInput:
        action = movement[0]
        count = int(movement[1:])
        wayNorth, wayEast, east, north = moveWithWaypoint(wayNorth, wayEast, east, north, action, count)

    return abs(north) + abs(east)

def moveWithWaypoint(wayNorth, wayEast, east, north, action, count):
    if action == 'N':
        wayNorth += count
    elif action == 'S':
        wayNorth -= count
    elif action == 'E':
        wayEast += count
    elif action == 'W':
        wayEast -= count
    elif action == 'L':
        wayNorth, wayEast = turnWaypoint(wayNorth, wayEast, 'L', count)
    elif action == 'R':
        wayNorth, wayEast = turnWaypoint(wayNorth, wayEast, 'R', count)
    elif action == 'F':
        east, north = driveToWaypoint(east, north, wayNorth, wayEast, count)

    return [wayNorth, wayEast, east, north]

def turnWaypoint(wayNorth, wayEast, turnOrder, count):
    if turnOrder == 'R':
        if count == 90:
            wayNorthtmp = wayNorth
            wayNorth = -wayEast
            wayEast = wayNorthtmp
        elif count == 180:
            wayNorth = -wayNorth
            wayEast = -wayEast
        elif count == 270:
            wayNorthtmp = wayNorth
            wayNorth = wayEast
            wayEast = -wayNorthtmp
    elif turnOrder == 'L':
        return turnWaypoint(wayNorth, wayEast, 'R', 360 - count)
    
    return [wayNorth, wayEast]

def driveToWaypoint(east, north, wayNorth, wayEast, count):

    for _ in range(count):
        east, north,_ = move(east, north, 'N', wayNorth)
        east, north,_ = move(east, north, 'E', wayEast)

    return [east, north]

def move(east, north, action, count, direction=0):
    if action == 'N':
        north += count
    elif action == 'S':
        north -= count
    elif action == 'E':
        east += count
    elif action == 'W':
        east -= count
    elif action == 'L':
        direction = turn(direction, 'L', count)
    elif action == 'R':
        direction = turn(direction, 'R', count)
    elif action == 'F':
        east, north = driveForward(east, north, direction, count)
    else:
        print('error')

    return [east, north, direction]

def turn(direction, turnOrder, degrees):
    if turnOrder == 'R':
        direction = (direction + int(degrees / 90)) % 4
    elif turnOrder == 'L':
        direction = (direction + (4 - int(degrees / 90))) % 4
    
    return direction

def driveForward(east, north, direction, count):
    actions = {0: 'E', 1: 'S', 2: 'W', 3: 'N'}
    
    action = actions.get(direction, 'X')
    
    east, north, _ = move(east, north, action, count, direction)
    
    return [east, north] 

def do():
    with open ('Input/day12.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2022/day9.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

TPositions = set()
tailPositions = set()

def do1(splitInput):
	HPos = (0,0)
	TPos = (0,0)
	TPositions.add(TPos)
	for line in splitInput:
		command,steps = line.split(' ')
		for _ in range(int(steps)):
			match command:
				case 'R':
					HPos = (HPos[0] + 1, HPos[1])
				case 'L':
					HPos = (HPos[0] - 1, HPos[1])
				case 'D':
					HPos = (HPos[0], HPos[1] - 1)
				case 'U':
					HPos = (HPos[0], HPos[1] + 1)
			TPos = updatePos(HPos, TPos)
			TPositions.add(TPos)	
	
	return len(TPositions)

def do2(splitInput):
	positions = [(0,0) for x in range(10)]
	tailPositions.add(positions[-1])
	for line in splitInput:
		command,steps = line.split(' ')
		for _ in range(int(steps)):
			headPos = positions[0]
			match command:
				case 'R':
					positions[0] = (headPos[0] + 1, headPos[1])
				case 'L':
					positions[0] = (headPos[0] - 1, headPos[1])
				case 'D':
					positions[0] = (headPos[0], headPos[1] - 1)
				case 'U':
					positions[0] = (headPos[0], headPos[1] + 1)
			for index,knot in enumerate(positions[1:]):
				positions[index + 1] = updatePos(positions[index], knot)
				tailPositions.add(positions[-1])
	
	return len(tailPositions)

def updatePos(HPos, TPos):
	TPositions.add(TPos)
	#same row or colum
	if TPos[0] == HPos[0]:
		match HPos[1] - TPos[1]:
			case 2:
				TPos = (TPos[0], TPos[1] + 1)
			case -2:
				TPos = (TPos[0], TPos[1] - 1)
	elif TPos[1] == HPos[1]:
		match HPos[0] - TPos[0]:
			case 2:
				TPos = (TPos[0] + 1, TPos[1])
			case -2:
				TPos = (TPos[0] - 1, TPos[1])
	#diagonally
	elif abs(HPos[0] - TPos[0]) + abs(HPos[1] - TPos[1]) == 2:
		return TPos
	else:
		# H is right from T:
		if HPos[0] > TPos[0]:
			if HPos[1] > TPos[1]:
				TPos = (TPos[0] + 1, TPos[1] + 1)
			else:
				TPos = (TPos[0] + 1, TPos[1] - 1)
		else:
			if HPos[1] > TPos[1]:
				TPos = (TPos[0] - 1, TPos[1] + 1)
			else:
				TPos = (TPos[0] - 1, TPos[1] - 1)
	return TPos

def do():
	strInput = readInputFile(9)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day10.py
from HelperFunctions import inputsplit
from HelperFunctions import convertToInt

def do1(puzzleInput):
    prepareInput(puzzleInput)
    
    differences = getDifferences(puzzleInput)

    return (differences.count(1)) * (differences.count(3))

def do2(puzzleInput):
    prepareInput(puzzleInput)
    
    return getNumberOfPossibilities(puzzleInput)

def prepareInput(puzzleInput):
    puzzleInput.insert(0,0)
    puzzleInput.insert(-1, max(puzzleInput) + 3)
    puzzleInput.sort()

def getDifferences(puzzleInput):
        
    differences = [puzzleInput[x+1] - puzzleInput[x] for x in range(len(puzzleInput)-1)]
    
    return differences

def getNumberOfPossibilities(puzzleInput):
    
    puzzleInput.reverse()

    possibilites = {puzzleInput[0]:1}

    for value in puzzleInput[1:]:
        sum = 0
        for i in [1,2,3]:
            sum += possibilites.get(value + i, 0)
        possibilites[value] = sum
    
    return possibilites[puzzleInput[-1]] 

def do():
    with open ('Input/day10.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')
    intInput = convertToInt(splitInput)

    print(do1(intInput))
    print(do2(intInput))
    
do()<file_sep>/2022/day15.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re

def do1(splitInput):
	pairs,sensors,beacons = extractSensorsAndBeacons(splitInput)

	impossiblePoints = set()
	y = 2000000

	for sensor,beacon in pairs.items():
		sensorX,sensorY = sensor
		distance = manhattanDistance(sensor,beacon)
		impossible = [(x,y) for x in range(sensorX-distance, sensorX+distance+1) if manhattanDistance(sensor,(x,y)) <= distance]
		impossiblePoints = impossiblePoints.union(set(impossible))

	sumImpossible = len([x for x in impossiblePoints if x[1] == y])
	sumBeacons = len([x for x in beacons if x[1] == y])
	sumSensors = len([x for x in sensors if x[1] == y])

	return sumImpossible - sumBeacons - sumSensors

def do2(splitInput):
	pairs,sensors,beacons = extractSensorsAndBeacons(splitInput)
	distances = {}

	for sensor,beacon in pairs.items():
		distances[sensor] = manhattanDistance(sensor,beacon)

	for sensor in sensors:
		sensorX,sensorY = sensor
		possiblePoints = []
		distance = distances[sensor]
		x = distance + 1
		y = 0
		while -distance - 1 <= x <= distance + 1:
			possiblePoints.append((sensorX + x, sensorY + y))
			x -= 1
			if x < 0:
				y -= 1
			else:
				y += 1
		for point in possiblePoints:
			pointX,pointY = point
			if not 0 <= pointX <= 4000000 or not 0 <= pointY <= 4000000:
				continue
			possible = True
			for otherSensor in sensors:
				if otherSensor == sensor:
					continue
				if manhattanDistance(point,otherSensor) <= distances[otherSensor]:
					possible = False
					break
			if possible:
				return point[0] * 4000000 + point[1]



def manhattanDistance(a,b):
	ax,ay = a
	bx,by = b
	return abs(ax-bx) + abs(ay-by)

def extractSensorsAndBeacons(splitInput):
	pairs = {}
	
	sensors = set()
	beacons = set()
	
	for line in splitInput:
		match = re.match('Sensor at x=(?P<xSensor>[-]?\d+), y=(?P<ySensor>[-]?\d+): closest beacon is at x=(?P<xBeacon>[-]?\d+), y=(?P<yBeacon>[-]?\d+)', line)
		sensorPos = (int(match.group('xSensor')), int(match.group('ySensor')))
		beaconPos = (int(match.group('xBeacon')), int(match.group('yBeacon')))

		pairs[sensorPos] = beaconPos
		sensors.add(sensorPos)
		beacons.add(beaconPos)
	
	return pairs,sensors,beacons

def do():
	strInput = readInputFile(15)
	
	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2022/day2.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

points = {'X':1, 'Y':2, 'Z':3}

choices = ['Y', 'A', 'Z', 'B', 'X', 'C', 'Y']
sameChoice = {'A':'X', 'B':'Y', 'C':'Z'}

def do1(splitInput):
	score = 0
	for line in splitInput:
		opponent,me = line.split(' ')

		if [opponent,me] in choices:
			winScore = 0
		elif [me,opponent] in choices:
			winScore = 6
		else:
			winScore = 3
		roundScore = points[me] + winScore
		score += roundScore

	return score

def do2(splitInput):
	score = 0
	for line in splitInput:
		opponent,result = line.split(' ')
		opponentIndex = choices.index(opponent)
		match result:
			case 'X':
				me = choices[opponentIndex + 1]
				winScore = 0
			case 'Y':
				me = sameChoice[opponent]
				winScore = 3
			case 'Z':
				me = choices[opponentIndex - 1]
				winScore = 6
		roundScore = points[me] + winScore
		score += roundScore

	return score

def do():
	strInput = readInputFile(2)
	
	splitInput = strInput.split('\n')
	
	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day21.py
from functools import cache
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from collections import Counter, deque

die = deque([i for i in range(1,101)])

def do1(player1,player2):
	
	score1,score2,diceRolls = play1(player1, player2)
	losingScore = min([score1, score2])

	return diceRolls * losingScore

def do2(player1,player2):

	wins = play2(player1, player2, 0, 0)

	return max(wins)

def getOptions():
	options = []
	for i in range(1,4):
		for j in range(1,4):
			for k in range(1,4):
				options.append(i+j+k)

	counts = Counter()
	for option in options:
		counts[option] += 1
	
	return counts

def play1(first, second):
	score1 = 0
	score2 = 0
	diceRolls = 0

	while score1 < 1000 and score2 < 1000:
		diceNumber = getDice()
		diceRolls += 3

		first = (first - 1 + diceNumber) % 10 + 1
		score1 += first
		if score1 >= 1000:
			return score1,score2,diceRolls

		diceNumber = getDice()
		diceRolls += 3

		second = (second - 1 + diceNumber) % 10 + 1
		score2 += second
		if score2 >= 1000:
			return score1,score2,diceRolls
	
	return score1,score2,diceRolls

@cache
def play2(first, second, score1, score2):
	if score1 >= 21:
		return (1,0)
	elif score2 >= 21:
		return (0,1)
	else:
		counts = getOptions()
		result = (0,0)
		for option,number in counts.items():

			newfirst = (first - 1 + option) % 10 + 1
			newscore1 = score1 + newfirst

			if newscore1 < 21:
				counts2 = getOptions()
				for option2,number2 in counts2.items():
					newsecond = (second - 1 + option2) % 10 + 1
					newscore2 = score2 + newsecond
			
					result1, result2 = play2(newfirst,newsecond,newscore1,newscore2)
					result = (result[0] + number * number2 * result1, result[1] + number * number2 * result2)
			else:
				result = (result[0] + number, result[1])
		return result

def getDice():
	diceNumbers =  []
	for _ in range(3):
		diceNumbers.append(die[0])
		die.rotate(-1)
	return sum(diceNumbers)

def do():
	strInput = readInputFile(21)

	player1,player2 = convertToInt(strInput.split('\n'))

	print(do1(player1,player2))
	print(do2(player1,player2))

	print('done')


do()<file_sep>/2020/HelperFunctions.py
def inputsplit(input, separator=' '):
    return input.split(separator)

def convertToInt(input):
    numbers = []
    for stringNumber in input:
        numbers.append(int(stringNumber))

    return numbers<file_sep>/2022/day4.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	fullyContained = 0
	for pair in splitInput:
		elf1Assignment,elf2Assignment = getElvesAssignments(pair)
		if elf1Assignment.issubset(elf2Assignment) or elf2Assignment.issubset(elf1Assignment):
			fullyContained += 1
	return fullyContained

def do2(splitInput):
	overlaps = 0
	for pair in splitInput:
		elf1Assignment,elf2Assignment = getElvesAssignments(pair)
		if elf1Assignment.intersection(elf2Assignment):
			overlaps += 1
	return overlaps

def getElvesAssignments(pair):
	assignments = []
	for elf in pair.split(','):
		elfStart,elfStop = [int(x) for x in elf.split('-')]
		elfAssignment = set([x for x in range(elfStart, elfStop + 1)])
		assignments.append(elfAssignment)
	return assignments

def do():
	strInput = readInputFile(4)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day6.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from copy import deepcopy
from collections import defaultdict

def do1(splitInput):

	fishes = growFishes(splitInput, 80)
	sumOfFishes = sum([x for x in fishes.values()])

	return sumOfFishes

def do2(splitInput):
	fishes = growFishes(splitInput, 256)
	sumOfFishes = sum([x for x in fishes.values()])

	return sumOfFishes

def growFishes(splitInput, days):
	fishes = defaultdict(lambda: 0)

	for fish in splitInput:
		fishes[fish] += 1
	
	for i in range(days):
		newFishes = defaultdict(lambda: 0)
		for key,value in fishes.items():
			if key == 0:
				newFishes[8] += value
				newFishes[6] += value
			else:
				newFishes[key - 1] += value
		fishes = deepcopy(newFishes)
	
	return fishes

def do():
	strInput = readInputFile(6)

	splitInput = strInput.split(',')
	intInput = convertToInt(splitInput)

	print(do1(intInput))
	print(do2(intInput))

	print('done')


do()<file_sep>/2019/day16.py
input = """59767332893712499303507927392492799842280949032647447943708128134759829623432979665638627748828769901459920331809324277257783559980682773005090812015194705678044494427656694450683470894204458322512685463108677297931475224644120088044241514984501801055776621459006306355191173838028818541852472766531691447716699929369254367590657434009446852446382913299030985023252085192396763168288943696868044543275244584834495762182333696287306000879305760028716584659188511036134905935090284404044065551054821920696749822628998776535580685208350672371545812292776910208462128008216282210434666822690603370151291219895209312686939242854295497457769408869210686246"""


def inputSplit(input):
    intInput = []
    for x in input:
        intInput.append(int(x))
    return intInput

def do():
    
    splitInput = inputSplit(input)
    result = splitInput.copy()
    
    for i in range(100):
        for outputPos in range(len(splitInput)):
            pattern = createPattern(outputPos)
            result[outputPos] = applyPattern(pattern, splitInput)
        splitInput = result.copy()
    
    return result

def applyPattern(pattern, splitInput):
    patternPos = 1
    sum = 0
    for pos in range(len(splitInput)):
        sum += splitInput[pos] * pattern[patternPos]
        patternPos = (patternPos + 1) % len(pattern)    
    return abs(sum) % 10

def createPattern(pos):
    pattern = [0, 1, 0, -1]
    resultPattern = []

    for position in range(len(pattern)):
        for repetition in range(pos + 1):
            resultPattern.append(pattern[position])
    
    return resultPattern



print(do()[:8])<file_sep>/2018/day2.py
input = """<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
ln<KEY>
lt<KEY>
ln<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
<KEY>
<KEY>
wn<KEY>
ln<KEY>
ln<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
fn<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
en<KEY>
gn<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
tn<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
l<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
ln<KEY>
l<KEY>
ln<KEY>"""

def inputsplit(input):
    return input.split()

def doPartOne():
    splitInput = inputsplit(input)

    twos = 0
    threes = 0

    for thing in splitInput:
        two = True
        three = True
        for letter in thing:
            if thing.count(letter) == 2 and two:
                twos += 1
                two = False
            if thing.count(letter) == 3 and three:
                threes += 1
                three = False
            
            thing = thing.replace(letter, '')

    print(str(twos) + ' ' + str(threes) + ' ' + str(twos*threes))

def doPartTwo():
    
    position = 0

    splitInput = inputsplit(input)

    while(position < len(splitInput[0])):        

        newInput = []
        for thing in splitInput:
            thing = thing[:position] + thing[(position + 1):]
            newInput.append(thing)
        
        for newthing in newInput:
            if newInput.count(newthing) == 2:
                print(newthing)
                return      

        position += 1


doPartOne()
doPartTwo()<file_sep>/2019/day6.py
input = """6CF)4J7
RC4)H87
LMS)RL4
KGS)1QW
H8N)KW5
JJM)YPS
P1W)ZKT
BSY)FMR
9T5)JK4
2X2)NQ5
H6R)FLY
8N9)H7L
5LR)TYT
VM7)V5V
GVF)Q8P
PQV)9NB
4W3)V84
H59)B3G
RGW)82C
BTQ)VRF
KQW)TNC
RT3)JHN
ZLY)15X
YJJ)55L
8Q2)6S7
963)PNL
8F3)WPH
H2Z)LMN
MFK)DMJ
JGN)H4X
P1C)Y9K
92D)8YS
2M2)PQ1
YY6)PRG
3J8)LBX
2WD)TK3
CNS)BJL
B53)JJ5
NND)CBM
FHS)RP5
RMS)6VH
FBB)QVC
SD2)WPN
BXL)76Q
V8H)LCW
MXC)2W2
CCX)KC9
JSQ)2T8
7HM)D24
XN9)N36
J3X)PRZ
6VQ)8ZV
QR4)MTL
KVT)V47
PXR)VFJ
VZN)P7W
WK6)72B
R46)J6N
5M4)LZB
4PL)V6R
WWR)BJ1
TPX)NRM
BS7)X7M
JJ5)8N2
V9N)D6W
7K2)2LZ
3JZ)FV1
2DJ)6N1
RC5)L5D
2RG)FK8
V8M)CL6
KLY)MBD
DMJ)KVD
6M6)6WX
HB1)1HD
KJW)G61
HZF)B1Q
2N4)73R
H8G)8XL
ZGK)RSY
35Y)FSR
H34)GLB
9MV)WR9
NBS)RV6
6QM)KLM
HN3)K2T
LCB)GNZ
LDJ)D3T
5PC)512
BXH)6MZ
XS7)W5B
LF3)6LJ
3Z8)ZTJ
3NT)9D9
65F)JVH
V6V)C9B
KTQ)KG8
6WP)92D
X4M)WGG
66R)B53
B5C)2MP
FC4)6T3
WWR)VRD
9DG)P94
XFV)TQQ
4LK)V21
2H8)HVS
JHN)QHZ
2GV)VSL
581)XRN
THC)ZGK
CB8)R2T
FN9)4Y9
1KH)RHQ
YF2)FNW
ZBW)JLW
YCK)R9D
2SH)X2M
512)W7P
TDK)FN9
TH8)HQZ
JK4)P62
BLG)CWW
V84)VYC
BTY)NXZ
8GC)DX1
CN5)YPZ
Y6J)CQP
L1X)NXF
SQ7)3QL
8KD)PS4
1SW)RHW
7X4)S86
RGS)581
2BC)DVS
6J8)XXQ
Q3S)TKF
T2K)TRL
NY4)16L
96Z)NMX
J1W)YRJ
8C3)29M
VRF)VX2
LD6)Y6M
RHX)FN3
J6N)LMY
BSB)JXV
PN4)L1X
M92)JPT
TBX)324
8RN)QKN
GNZ)J2D
GZ1)WJ4
783)96Z
SLD)L3C
9FK)V9L
D3T)PM2
1JL)MKH
CKL)PYR
SZD)YF2
8LD)4GQ
MQ2)JCP
CTW)GZ1
M7W)8NR
FWH)GBQ
1CX)BTC
YJL)RGX
FLY)ZDD
NCJ)8GC
PM2)2YG
T82)KM8
4M3)Q71
LGQ)JYC
K4Y)287
J48)THC
CNV)NCJ
9P7)SZY
QXP)XM5
S5Z)BSY
59Q)SLL
S79)16C
W66)JL4
L6Q)CZ2
7CB)7HP
DQ4)CLP
PQ1)FCR
5QP)163
RJB)H3J
CH5)25F
TQG)VLN
SDT)J67
1VL)X2B
5SM)G71
RSY)1J4
CZP)XNT
57T)37Z
1J4)3B2
7X4)WNS
BNT)NND
QMS)DVH
VW6)6QM
VFJ)4XH
17T)NLM
N8T)7HM
QPS)7LM
XXQ)2KV
WBS)8RF
95F)3Z8
NR1)WQM
S75)WNT
ZJ5)7WS
YNF)RDQ
2DY)XBV
7LM)V48
C78)64H
VHR)L2P
V47)9QN
9C5)Y5S
9D9)QDT
7DC)2DJ
H8P)H6P
QH4)X4N
K19)CYL
CXY)CMV
G8D)FDN
4Z3)LVF
V1Z)YHN
GM3)B2Q
LVF)VZH
2LZ)YOU
FNW)1R5
36J)2QT
2Y4)69H
LTZ)JGN
GTN)MZ3
FQX)WZP
3M8)P7L
16L)H78
9B1)NTB
PB7)86H
Z3P)T9T
M1X)KK5
6PS)5FQ
55L)2WZ
174)6GC
86H)2W7
WXH)R15
3B2)3Q6
BGQ)SPZ
1QW)NJT
WCK)5R8
ZKT)MTH
Z7S)67J
FK8)5J4
WJM)H83
4Y9)Z9B
LKC)3MW
6FM)MC3
163)68L
XJS)2PD
NVB)C8Q
WTV)S32
V9L)SVG
5HW)7LG
BTC)DX6
TKF)2DX
JJK)NPF
LQN)DSV
21B)JTT
9H8)ZY4
72B)W1Y
MF8)M3Q
6WF)SQ3
N34)4HL
1KB)32T
VYP)H6F
TTC)XHP
QM4)H2Z
NRM)7FK
ZGK)V13
XRN)361
324)ZMX
1PY)PH7
PDS)VLX
M88)XD4
1DZ)VF8
YL2)J9J
6GB)NR1
VX2)JJM
X4N)FN1
KK5)MZX
7ZT)GLZ
JDG)GGM
Q4N)8RN
JYC)N5Z
MTL)SPD
1KQ)135
9JX)FHS
NSF)PYT
QWF)QX9
FY1)48P
V4W)GXX
L5D)8KQ
P1C)F46
5R8)M1X
NSM)SV5
366)CXY
D24)Q83
ZKG)SD2
QKN)MC4
P4P)RK6
9QN)K4Y
38D)TJH
RG6)SZD
JL4)GQQ
Y6M)3NT
FR7)C3Q
DNH)7YW
SDL)M5X
JFT)YY6
5D9)KVT
JBL)GM3
C4V)FYC
KW5)Y7D
V76)VSH
CMV)ZKY
TK3)5KN
KDS)X34
NMY)QYZ
MDP)GVL
QSS)CY8
QFX)ZN1
Q54)VJP
VSH)3DK
ZY4)B19
X6Y)15G
L3C)78D
LDV)SJT
8M7)6VQ
22Z)BTQ
RHQ)NFK
9NT)DQ4
C9B)WB9
HGD)QXP
YDX)YMZ
VMQ)8C3
9RM)QTY
GQQ)9C1
LSG)KJW
6MS)GVF
ZTL)LLK
S86)W19
1FV)LGQ
C8Q)P4P
DMP)Y1X
48P)LGX
MZ3)9B1
LKH)2WL
NZJ)TNJ
F67)L34
9Y3)783
ZNJ)6WF
WX6)ZSC
15G)RTW
QHP)9YN
DQH)KY6
4LF)LY8
XHR)GK1
3MW)SRY
Q8N)RPX
R9X)SZL
V85)FR7
MVW)QLB
1DY)H29
43D)NY4
MKH)SBX
5FQ)ZT8
P97)2JM
DSV)RGW
37Z)5SJ
3WG)KTQ
Z9G)2N4
K7Q)HQV
BX1)2H8
7WS)G27
WHN)2DL
YHN)9YB
1JN)BGQ
PYP)VQ8
VXC)917
13Z)XTZ
9WT)N8Q
VVH)MP7
WDM)RC5
G8T)WHN
VYC)MR6
XM5)FWH
N8Q)V77
2YM)HH9
L4J)8G9
1TG)S6H
XCC)TD8
KRF)4KZ
19N)9FK
SMS)V1K
8N2)MZS
869)8F8
JGD)PYW
76V)CLW
NDZ)VM7
VLX)6WD
895)38D
1XZ)Q34
VF8)1F6
TNC)7DC
16C)MWQ
LDJ)C4L
ZV6)7XJ
NXZ)H34
BLS)4MM
GG6)NKG
BCD)KT9
PYW)LSG
LNP)7XQ
MZX)BY9
RGX)J8P
S32)DSS
J9J)LTZ
39P)S75
CNS)PDZ
PYW)CHG
Z19)V8Q
68L)9WR
V6R)MVW
LLK)MYP
9MV)MQT
1FH)4CK
P4N)MMM
4TD)96J
V77)CH4
MMW)CTW
MLN)3CS
W8G)2JS
4KZ)HBT
5PM)6PP
C81)JSQ
V11)WK6
FCR)MVH
YR2)KLY
W1H)XTX
SKL)NQG
2YM)VL7
M8K)6HN
1K6)JX8
ZDD)H1W
4JW)NV8
GS2)CMP
RDM)7XB
3QB)GTN
D6W)MJT
NRK)6PS
7WS)B1L
PKH)L4J
G61)WTV
2T8)8Q2
TL6)W7Z
1TC)KXM
1VL)DZD
LVZ)1DZ
1TQ)S3R
7BY)ZB6
JPT)1JN
LF3)K91
37D)LKM
9LN)VZN
MQT)Q1F
M6X)GTS
CNH)1WS
6GC)BSM
1F6)88V
FKP)XQZ
QX9)5SM
1HD)VP7
MMQ)RT3
QXX)9P7
GLT)SQ7
HQP)TLR
K2T)P6X
TTZ)Z7S
D49)3NV
DFD)V29
LPW)877
ZKT)BXL
YHN)TKD
FV1)9Y3
3ZB)57Z
WN1)35Y
SQ3)ZCF
DJF)ZNJ
R61)LCB
BMX)YFT
W5B)3VM
46C)174
BJ1)2XP
XZJ)KN9
2D7)N8T
TTF)KDS
1T5)8M7
Y5Q)SKL
6C8)WHW
QBH)6PZ
6RD)7BY
Z2Y)1KB
J3Q)X6Y
PBR)2D7
JLW)2CY
RP5)54P
PYT)9HC
N5M)FY1
MWG)N2M
V1K)M7W
55L)869
M3Q)Q8N
FSR)ZV6
MX8)RQF
LKM)SAN
KKP)WDM
FN1)1DW
WB9)VDR
G98)RMS
H7L)CCN
TL3)LJF
YNZ)K8V
KL2)66B
M28)P9Z
Q34)Y28
TNJ)NSM
W25)R9X
8XL)GS2
ZB6)26Z
BYR)5QP
MVH)BNW
TKD)P1C
9JW)WX6
8LC)J3Q
H8F)Y14
347)7SJ
8VL)RC4
38T)1FV
9FM)M39
CH4)LVQ
LNV)QPS
H87)FPL
9YN)LKH
9HB)PBR
9WR)NWL
X7M)BYR
3GM)N7X
67J)RJB
2XV)LNV
3VX)WWR
1R5)VMD
9HC)BTY
GVL)CVB
D8J)5LR
M39)VW6
NPF)MFK
7NQ)6M9
3DK)P76
ZQG)J1W
JCP)TBX
DX1)9DG
917)LDV
CBT)M9J
G71)H8P
4J7)FZJ
RGX)CB8
63W)P1W
V8Q)2DY
H42)YGG
RY7)1V6
W7Z)CYN
BGL)JJ8
TLR)X2S
X4H)2SB
MC4)QR4
Q8P)CCX
P8R)43D
J3R)VS6
TPK)9H8
D17)NMY
G27)9S9
1SV)RWF
MQ2)B47
L2P)VMF
V13)Y5Q
L5B)YJJ
WNT)MZF
B47)WN1
KN9)9VX
LFJ)GPB
F82)855
BD5)MLN
SBX)CBT
7XQ)H65
VJP)6WB
PH7)WKG
LBF)1SW
2YG)FSB
7LM)8DN
913)5D9
VLN)BLG
FM6)5PM
5W2)7W8
BY9)6M6
ZN1)FP5
2WZ)BSB
D24)4LK
8NR)R8W
414)QSS
ZMX)4TD
3VM)ZLY
HT3)LDJ
XDR)CJ6
R2T)22Z
L34)RY7
7FK)17T
X2S)TTZ
714)9C5
BNR)GYJ
RQF)KQW
3F9)GWN
FL6)DNH
6WB)YL4
7MT)V1Z
Q1F)LBY
PS4)Q54
82C)MDP
77H)MGJ
CVB)DXB
HGD)FBB
ZTJ)XH9
FXS)JP8
KB9)WYZ
C4L)XG8
C3Q)YR2
96J)F8M
W53)6C8
LZB)L6Q
Z78)62Y
361)G8D
FY1)RDM
S5Z)V9N
23W)PN4
SRX)Z3P
PRZ)PXR
7NF)R58
QTY)WY4
897)V3S
GVF)ZV3
PTP)21B
37G)H59
Y3R)LVZ
CWH)C81
W9M)GXC
V29)CKL
NXR)91Q
Y84)6RD
G2K)2JD
MR6)1CX
QDT)F67
ZM3)1BY
XHP)H8F
WVL)9JX
NRM)Y4R
CY8)CHJ
H6P)XJS
96Z)MT8
P6X)4M3
XQZ)SC7
J67)3J8
GCR)V85
H65)ZM3
K4Y)W74
WPN)6NJ
F46)LG7
H78)NXR
LBY)G98
FZJ)63T
21B)CT7
7G9)414
2D8)G7Z
QLB)VTR
1V6)VGH
R15)LQP
2QT)Y3R
Q83)7YN
BXL)NV4
J8P)JDG
76Q)C4V
SZY)PTP
7SJ)7G9
C8R)H42
VW6)8LC
135)6MB
4XH)WJM
8KT)93S
G7Z)7NQ
9C1)GSW
TC8)J26
3F4)W8G
CZ2)RPJ
9WT)BCD
LY8)533
548)PKH
K2M)6MQ
2X1)HN1
LSY)R9G
PVN)X3T
H3J)L65
7XB)DT6
DVS)XN9
SGN)DS4
NYD)WHP
DWD)C3V
LM8)MGP
ZCF)VSC
PXN)ZPT
7ZT)CWH
DGH)7K2
VSL)4CC
FP5)Z9G
6F2)MWG
RV6)MNB
8TQ)GTB
YPZ)QL2
14G)SMS
VML)XHR
Y4R)D46
MNB)1K6
FNP)9H6
X1T)5JP
1DW)28V
76P)4MK
WW4)53M
WZP)B5C
DS4)1PZ
B1L)DQW
RHX)RGS
42C)CBV
HQV)9T5
YDV)DFD
KG8)Q7R
72W)BSZ
369)ZBW
9YB)77H
MD3)YT8
YGG)VYP
3QL)289
X2B)548
Y5S)R64
9MM)P8R
W19)382
RPJ)QQG
P9Z)BNT
DNB)CCP
6HN)DMP
MW5)SLD
WRS)HWD
ZKR)186
WQM)LQN
NL4)JBS
WHW)TTC
WJ4)1T5
R9G)FQX
2W2)8VY
P3H)V11
243)XCC
SJT)7NF
3Y4)9SS
MP7)4ZD
186)BD5
NZ3)913
KLM)MMQ
8G9)5GZ
G38)YDV
85T)MX8
V4B)9FM
8RQ)NQ7
LX6)BMX
2SB)9MV
8KD)5VJ
J67)PGY
SD2)FC4
GWN)R2R
VL7)3W9
CB5)1TQ
5Q9)BV2
M5X)PXN
HHT)3ZB
NV4)JYQ
5TY)XQ5
RG5)NL4
CLW)Q3S
NMX)K2M
VQY)T82
FN3)CCF
TQQ)KGT
6MZ)KRF
N36)49V
Z8B)LSY
69H)M88
DX6)Y84
HQ7)1KQ
F1V)D17
JQM)8M4
QNV)Z5Z
NQ5)YJL
GSW)DDZ
6WX)3S2
CNV)T5Z
2JS)366
5JP)VPV
6LJ)6GB
YFT)347
GTS)J1D
KC9)S38
LBX)H8G
4NY)2KP
WHW)2D8
W25)9M2
R58)D8J
D17)88Z
8T7)8ZZ
7YN)HY6
ZBW)WB3
ZSC)DZK
X2B)R9B
VP7)GLT
2Q1)ZJ5
ZV3)T68
MTH)39P
SNY)4LF
2WL)JBN
WPL)D49
CCF)VVH
HPS)9M9
FYV)PQV
9N8)VMQ
92F)1DY
RWF)ZGM
CYL)V6K
3Z5)2Q1
VCN)HGD
NV8)LD6
KKV)V8H
6PZ)KVK
5VJ)KKP
GDT)NX1
CWW)4JW
Y9K)7ZT
DB4)CH5
DXB)VXC
SPD)4NV
YNV)4W3
KGT)2M2
YRJ)KV6
X9Y)TDK
S3R)L5B
8F3)7MT
XWR)TM1
Y8W)PB7
PGC)SWT
Q71)2XH
Y1X)32Q
2PD)81V
FY4)X1T
J8M)W25
WPH)2C1
N5Z)DQH
ZKY)LM8
HWD)3W8
395)429
3Q4)6NL
H4X)W8Z
WB3)MQ2
5G2)JGD
F5F)W9M
88V)HT3
GGM)J2X
FKN)P8V
VMD)3F4
RHW)9RR
RMS)243
MT8)Z8B
8YP)WW4
VLX)F82
3S2)LKC
8YS)9N8
XTX)Y2V
VGH)4W2
Z5Z)5BT
GLZ)FL6
93S)CVW
J26)ZQG
JSX)CZP
9SS)WPL
L4J)YNZ
M9J)395
5HW)8RQ
7K2)JBL
SWT)7T3
57W)Y8W
V21)WCK
9M9)NDZ
KVD)FY4
8WJ)1KH
W7K)HN3
72N)M6X
C66)1VL
JJ8)4ZS
6M9)QT9
RK6)BKR
7HP)S3V
H6F)XDR
4ZS)XZJ
R8W)4G3
6NL)H72
BGL)JP1
V5V)5G2
9M2)13Z
W7P)M28
BNW)V6V
P94)RG5
5G2)78H
2C1)HB1
ZGM)7VK
CBM)6FM
5Y3)NR2
FV1)85T
JTT)H8N
6C8)SGN
Y9M)BXH
877)DTS
JP1)TL3
D46)C5Z
2XP)XY7
H72)3VX
26Z)95S
RMV)QBH
69H)ZRT
2KV)897
4MK)JF2
P7W)DGH
RDQ)LX6
2DL)MP8
1PZ)GDT
ZTV)NVQ
KVV)NZC
22Z)9NT
B4W)S5Z
6MB)52R
B19)V8M
VRD)SDT
8ZZ)8Z4
WKG)9HB
R2R)MD3
VTP)CB5
T5Z)J3Y
KVK)QCV
DTS)23W
PCP)2X2
HN1)8KT
LGX)KKV
XG8)JFT
H1W)KZT
B1N)3Q4
NQ7)9JW
FWH)TCR
JBR)SSB
SX6)R3L
QCV)CNV
H29)QFX
TM1)2YM
ZZS)HZF
9VX)PYP
Y7D)V4B
TD8)J3R
82P)WXH
855)P2R
3W8)92F
BQZ)8WJ
VTR)JQM
NR2)5TY
L65)N34
64H)YL2
1BY)TPK
Y14)XS7
4KM)2BC
5H1)MCJ
T68)LBF
H83)SX6
HT6)C78
7W8)TFL
32T)QXX
TFL)FKP
CT7)5HW
QXP)NZ3
8C3)6J8
5GZ)FBY
V6K)9DJ
NWL)5W2
W74)ZTV
429)369
WYZ)Q7P
LJF)F5F
NVQ)S79
X7P)1TG
4CK)7X4
N9H)4NY
15X)H8Y
BV2)95F
WK6)9RM
JF2)46C
DNH)RZQ
LMN)GCR
CGB)YDQ
NXF)5H1
8RF)TVM
3VT)LFJ
LMY)2RG
7HM)C8R
GLB)MF8
5NR)QMS
CLP)V76
2W7)NYD
4W2)4PL
JBN)GPF
J3Y)XWR
C5Z)MW5
SPZ)65F
PWT)LNP
X2M)5Q9
CH5)RMV
FBY)ZZK
8Z4)R46
XH9)HT6
FDN)76V
NLM)HCM
MP8)YDX
R9B)SBW
1TQ)963
H8Y)CGB
5J4)FM6
9NB)3VT
XTZ)3Y4
CCN)714
TCR)SRX
3W9)WVL
2DL)JBR
XBV)PBL
S38)B8B
SZT)Z78
GK1)CZC
B3D)QHP
ZT8)DNB
TDK)KVV
HBT)MXC
VPV)ZTL
Q7P)NPD
QYZ)6WP
2KP)KGS
LQP)XFQ
LSG)8TQ
P62)72W
CPM)57W
2XH)XLN
R3L)DNY
TPX)X4M
KM8)64L
ZV6)82P
4NV)8N9
JP8)FYV
F8M)38T
64L)NZJ
QCV)VML
SBW)QNV
YDQ)2WD
T9F)GZ3
Z9B)8YP
KY6)2X1
TJH)LMS
YL4)W53
3CS)1JL
CVW)9LN
7DX)VTP
53M)W1H
NTB)V4W
PCP)TH8
SLL)ZZS
MJT)42C
62Y)DWD
WGC)7CB
XQ5)LMM
NKG)P97
NRK)F1V
BJL)4Z3
7YW)6MS
WHP)6F2
N7X)ZKG
WY4)JJK
NZC)G38
GBQ)BGL
8DN)3JZ
641)72N
XD4)B1N
WNT)6CF
92F)HPS
GYJ)HQP
P1W)Q17
R9D)5PC
PDZ)RHX
2CY)Z19
W1Y)5M4
32Q)2SH
BSM)NRK
QHZ)9G3
MBD)36J
TT4)NSF
PRG)VQY
4GQ)QH4
4MM)3WG
382)HC7
V48)8T7
CHG)J8M
N2M)NBS
2JD)PDS
SVG)5Y3
T9T)QFT
52R)T9F
9T5)2XV
8ZY)1SV
RL4)VHR
S6H)1TC
MGJ)TPX
WR9)SQG
6N1)XFV
DNY)X7P
TYT)HHT
XFQ)2Y4
KZT)X9Y
J1D)4KM
Y2V)W66
NC5)N9H
MGP)2GV
88Z)37G
LCW)S7P
XJL)Q4G
9G3)KL2
DZK)CNS
NJT)BS7
SC7)K19
HVS)SZT
P7L)14G
NTB)YNV
1NH)8LD
WNS)8VL
Q17)N5M
MQT)LPW
PGY)1FH
78H)M92
8ZV)BLS
FSB)BX1
9FM)9MM
FPL)GG6
29M)9NY
P76)8SN
COM)PWT
9DJ)8F3
LVQ)Y9M
C2R)SDL
6NJ)WGC
4VX)RYG
8M7)63W
MZF)59Q
61G)895
25F)W7K
28V)9WT
ZZK)T2K
L6Q)19N
NFK)P3H
B3G)CN5
P2R)1XZ
NQG)95L
HY6)1NH
BSZ)CNH
4CC)H6R
JX8)8KD
91Q)YCK
5SJ)B3D
KV6)57T
JXV)4VX
VS6)KB9
NQG)QWF
FMR)RG6
DDZ)MMW
B2Q)X4H
YMZ)PCP
MMM)BNR
SZL)36D
289)G2K
YT8)TT4
9HC)TTF
QVC)TC8
VMF)FNP
CL6)Q4N
95L)SNY
Q4G)R61
8M4)B57
JYQ)C2R
VDR)3F9
4G3)C66
R64)BQZ
X34)QF1
DQW)XJL
GPB)QM4
C3V)CPM
4J7)66R
95S)37D
B57)ZKR
78D)61G
CYN)NC5
CMP)FKN
HQ3)VCN
CZC)JSX
K8V)G8T
KT9)WBS
VZH)Y6J
9H6)PVN
CCP)3M8
VP7)DB4
KXM)TQG
5KN)Z2Y
QL2)LF3
9NY)FXS
8VY)M8K
JBS)B4W
DZD)P4N
RQF)3Z5
3Q6)WRS
GXX)5NR
63W)3QB
W8Z)J3X
6VH)VJ6
4BW)YNF
MC3)TL6
SLD)J48
MYP)HQ7
DT6)G8J
GPF)1PY
6PP)KFB
GZ3)76P
CHJ)3GM
DX1)NVB
7LG)8ZY
QF1)HQ3
85T)7DX
6T3)K7Q
49V)4BW
Y3R)DJF
4HL)641
FYC)PGC"""



def do():
    splitInput = input.split()

    orbits = getOrbits(splitInput)

    count = countOrbits(orbits)

    return [orbits, count]


def getOrbits(splitInput):
    orbits = {}

    for orbitDescription in splitInput:
        center, orbit = orbitDescription.split(')')

        orbits[orbit] = center
    
    return orbits

def countOrbits(orbits):
    count = 0
    for key in orbits.keys():
        currentOrbit = key
        while currentOrbit:            
            currentOrbit = orbits.get(currentOrbit, 0)
            if currentOrbit:
                count += 1
                
    return count


def countSingleOrbit(orbits, orbit):
    count = 0
    currentOrbit = orbit
    while currentOrbit:
        currentOrbit = orbits.get(currentOrbit, None)
        if currentOrbit:
            count += 1
    return count
       
def move(orbit1, orbit2, commonOrbit):
    countSan = countSingleOrbit(orbits, orbit1)
    countYou = countSingleOrbit(orbits, orbit2)
    countDouble = countSingleOrbit(orbits, commonOrbit)

    return countSan + countYou - 2*countDouble - 2

def orbitList(orbits, orbit):
    orbitList = []

    currentOrbit = orbit
    while currentOrbit:
        currentOrbit = orbits.get(currentOrbit, None)
        if currentOrbit:
            orbitList.append(currentOrbit)
    
    return orbitList

def findCommonOrbit(orbitList1, orbitList2):
    for orbit in orbitList1:
        if orbit in orbitList2:
            return orbit

def do2(orbits):
    orbitList1 = orbitList(orbits, 'SAN')   
    orbitList2 = orbitList(orbits, 'YOU')

    commonOrbit = findCommonOrbit(orbitList1, orbitList2)

    return move('SAN', 'YOU', commonOrbit)


orbits, count = do()

#part1
print(count)

#part2
print(do2(orbits))

<file_sep>/2019/day2.py
input = "1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,9,19,1,19,5,23,1,13,23,27,1,27,6,31,2,31,6,35,2,6,35,39,1,39,5,43,1,13,43,47,1,6,47,51,2,13,51,55,1,10,55,59,1,59,5,63,1,10,63,67,1,67,5,71,1,71,10,75,1,9,75,79,2,13,79,83,1,9,83,87,2,87,13,91,1,10,91,95,1,95,9,99,1,13,99,103,2,103,13,107,1,107,10,111,2,10,111,115,1,115,9,119,2,119,6,123,1,5,123,127,1,5,127,131,1,10,131,135,1,135,6,139,1,10,139,143,1,143,6,147,2,147,13,151,1,5,151,155,1,155,5,159,1,159,2,163,1,163,9,0,99,2,14,0,0"

#input = "1,0,0,0,99"

def inputSplit(input):
    return input.split(',')

def do(noun, verb):
    splitInput = inputSplit(input)
    intInput = convertToInt(splitInput)

    intInput[1] = noun
    intInput[2] = verb

    positions = range(0, len(input) - 1, 4)

    for position in positions:
        action = intInput[position]

        if action == 99:
            return intInput

        arg1 = intInput[intInput[position + 1]]
        arg2 = intInput[intInput[position + 2]]
        resultPos = intInput[position + 3]

        if action == 1:
            result = arg1 + arg2        
        elif action == 2:
            result = arg1 * arg2
        else:
            print("Failure")
            return

        intInput[resultPos] = result

def convertToInt(input):
    numbers = []
    for stringNumber in input:
        numbers.append(int(stringNumber))

    return numbers


for noun in range(0,99):
    for verb in range(0,99):
        if do(noun, verb)[0] == 19690720:
            print(100 * noun + verb)<file_sep>/2018/day11.py

def calculateGreatestPower(dic, kernel):
    indexX = -1
    indexY = -1
    powerSums = [[0 for x in range(len(dic) - kernel)] for y in range(len(dic[0]) - kernel)]
    maxPowerSum = -10000
    for y in range(len(dic) - kernel):
        for x in range(len(dic[0]) - kernel):

            powerSum = 0
            for i in range(kernel):
                for j in range(kernel):
                    powerSum += dic[y + i][x + j]

            powerSums[y][x] = powerSum
            if powerSum > maxPowerSum:
                maxPowerSum = powerSum
                indexX = x
                indexY = y
    
    return [indexX + 1,indexY + 1, maxPowerSum]

def do():
    serial = 5034

    width = 300
    height = 300

    kernelwidth = 3

    powermatrix = [[0 for x in range(width)] for y in range(height)]

    for y in range(1, height + 1):
        for x in range(1, width + 1):
            rackID = x + 10
            powerlevel = (rackID * y + serial) * rackID
            
            powermatrix[y-1][x-1] = int((powerlevel % 1000) / 100) - 5

    maxPower = -10000
    size = 0
    topleft = []
    for i in range(1,301):
        topleftX, topleftY, powerSum = calculateGreatestPower(powermatrix, i)
        if powerSum > maxPower:
            maxPower = powerSum
            size = i
            topleft = [topleftX, topleftY]

    return [topleft, size]



print(do())<file_sep>/2018/day9_test.py
import unittest
from day9 import do

class Day9Test(unittest.TestCase):

    def test1(self):
        self.assertEqual(do(10, 1618), 8317)

    def test2(self):
        self.assertEqual(do(13, 7999), 146373)

    def test3(self):
        self.assertEqual(do(17, 1104), 2764)

    def test4(self):
        self.assertEqual(do(21, 6111), 54718)

    def test5(self):
        self.assertEqual(do(30, 5807), 37305)

if __name__ == '__main__':
    unittest.main()
<file_sep>/2021/day4.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput

def do1(splitInput):
	numbers = convertToInt(splitInput[0].split(','))

	boards = splitInput[1:]
	intBoards = prepareBoards(boards)

	return play(numbers, intBoards, True)		
	

def do2(splitInput):
	numbers = convertToInt(splitInput[0].split(','))

	boards = splitInput[1:]
	intBoards = prepareBoards(boards)
	
	return play(numbers, intBoards, False)

def prepareBoards(boards):
	intBoards = []
	for board in boards:
		splitBoard = board.split('\n')
		intSplitBoard = []
		for line in splitBoard:
			intSplitBoard.append(convertToInt(line.split(' ')))
		intBoards.append(intSplitBoard)
	return intBoards

def convertToInt(input):
	numbers = []
	for stringNumber in input:
		if stringNumber == '' :
			continue
		else:
			numbers.append(int(stringNumber))
	return numbers

def play(numbers, boards, firstWins):
	for number in numbers:
		for board in boards:
			playNumberOnBoard(board, number)
		winners = winningBoards(boards)
		if winners:
			if firstWins or len(boards) == 1:
				return number * winningScore(boards[winners[0]])
			for winner in sorted(winners, reverse=True):
				boards.pop(winner)		
		
def playNumberOnBoard(board, number):
	for line in board:
		if number in line:
			index = line.index(number)
			line[index] = 'X'			

def winningBoards(boards):
	winning = []
	for number,board in enumerate(boards):
		if ['X', 'X', 'X', 'X', 'X'] in board:
			winning.append(number)
		else:
			for i in range(len(board[0])):
				completeLine = True
				for j in range(len(board)):
					if board[j][i] != 'X':
						completeLine = False
						break
				if completeLine:
					winning.append(number)
					break
	return winning

def winningScore(board):
	winningSum = 0
	for line in board:
		winningSum += sum([x for x in line if x != 'X'])

	return winningSum

def do():
	strInput = readInputFile(4)
	
	splitInput = strInput.split('\n\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day12.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from collections import defaultdict

def do1(splitInput):
	paths = preparePaths(splitInput)
	ways = findPossibleWays(paths, 'start', 'end', [], maxAmount=defaultdict(lambda: 1))
	return len(ways)

def do2(splitInput):
	paths = preparePaths(splitInput)

	maxAmount = {}
	lowerKeys = [x for x in paths.keys() if x.islower()]
	for key in lowerKeys:
		maxAmount[key] = 1

	allWays = []
	for key in lowerKeys:
		if key == 'start' or key == 'end':
			continue
		maxAmount[key] = 2
		ways = findPossibleWays(paths, 'start', 'end', [], maxAmount)
		for way in ways:
			if way not in allWays:
				allWays.append(way)
		maxAmount[key] = 1
	return len(allWays)

def preparePaths(splitInput):
	paths = defaultdict(lambda: set())
	
	for line in splitInput:
		first,second = line.split('-')
		firstSet = {first}
		secondSet = {second}
		paths[first] = paths[first].union(secondSet)
		paths[second]= paths[second].union(firstSet)
	
	return paths

def findPossibleWays(paths, start, end, path, maxAmount):
	path = path + [start]
	if start == end:
		return [path]

	newPaths = []
	for connected in paths[start]:
		if connected.isupper() or path.count(connected) < maxAmount[connected]:
			possiblePaths = findPossibleWays(paths, connected, end, path, maxAmount)
			for possiblePath in possiblePaths:
				newPaths.append(possiblePath)
	return newPaths

def do():
	strInput = readInputFile(12)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day22.py
from HelperFunctions import inputsplit
from HelperFunctions import convertToInt

def do1(puzzleInput):
    player1 = convertToInt(puzzleInput[0].split('\n')[1:])
    player2 = convertToInt(puzzleInput[1].split('\n')[1:])

    winner = play(player1, player2)

    winningScore = getWinningScore(winner)

    return winningScore

def do2(puzzleInput):
    player1 = convertToInt(puzzleInput[0].split('\n')[1:])
    player2 = convertToInt(puzzleInput[1].split('\n')[1:])

    memory = []
    winner = playRecursive(player1, player2, memory)

    if winner == 1:
        return getWinningScore(player1)
    else:
        return getWinningScore(player2)

def play(player1, player2):
    while True:
        card1 = player1.pop(0)
        card2 = player2.pop(0)

        if card1 < card2:
            player2.append(card2)
            player2.append(card1)
        else:
            player1.append(card1)
            player1.append(card2)
        
        if len(player1) == 0:
            return player2
        if len(player2) == 0:
            return player1

def playRecursive(player1, player2, memory):
    while True:
        if (player1, player2) in memory:
            return 1
        else:
            memory.append((player1.copy(), player2.copy()))

        card1 = player1.pop(0)
        card2 = player2.pop(0)

        if len(player1) >= card1 and len(player2) >= card2:
            winner = playRecursive(player1[0:card1].copy(), player2[0:card2].copy(), [])   
        else:
            if card1 < card2:
                winner = 2
            else:
                winner = 1
        
        if winner == 1:
            player1.append(card1)
            player1.append(card2)
        else:
            player2.append(card2)
            player2.append(card1)     

        if len(player1) == 0:
            return 2
        if len(player2) == 0:
            return 1   

def getWinningScore(player):
    value = range(len(player), 0, -1)
    score = sum([a*b for a,b in zip(player, value)])
    
    return score

def do():
    with open ('Input/day22.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n\n')
    
    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2021/day16.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

hex = {'0': '0000', '1': '0001', '2': '0010', '3': '0011', '4': '0100', '5': '0101', '6': '0110', '7': '0111', '8': '1000', '9': '1001', 'A': '1010', 'B': '1011', 'C': '1100', 'D': '1101', 'E': '1110', 'F': '1111'}

class Package:
	def __init__(self, version, typeID):
		self.size = 0
		self.number = 0
		self.packages = []
		self.version = version
		self.typeID = typeID
	def setSize(self, size):
		self.size = size
	def getSize(self):
		return self.size
	def setNumber(self, number):
		self.number = number
	def getNumber(self):
		return self.number
	def addPackage(self, package):
		self.packages.append(package)
	def setPackages(self, packages):
		self.packages = packages
	def getPackages(self):
		return self.packages
	def getVersion(self):
		return self.version
	def getTypeID(self):
		return self.typeID

def do1(splitInput):
	binaryStr = ''

	for bit in splitInput:
		binaryStr += hex[bit]

	package = decodePackage(binaryStr)
	
	versions = getAllVersionNumbers(package, [])

	return sum(versions)

def do2(splitInput):
	binaryStr = ''

	for bit in splitInput:
		binaryStr += hex[bit]

	package = decodePackage(binaryStr)

	result = calculateResult(package)

	return result

def getAllVersionNumbers(package, versions):
	versions.append(package.getVersion())

	for subPackage in package.getPackages():
		getAllVersionNumbers(subPackage, versions)
	
	return versions

def calculateResult(package):
	match package.getTypeID():
		case 0:
			result = 0
			for subPackage in package.getPackages():
				result += calculateResult(subPackage)
			return result
		case 1:
			result = 1
			for subPackage in package.getPackages():
				result *= calculateResult(subPackage)
			return result
		case 2:
			values = []
			for subPackage in package.getPackages():
				values.append(calculateResult(subPackage))
			return min(values)
		case 3:
			values = []
			for subPackage in package.getPackages():
				values.append(calculateResult(subPackage))
			return max(values)
		case 4:
			return package.getNumber()
		case 5:
			subPackages = package.getPackages()
			firstValue = calculateResult(subPackages[0])
			secondValue = calculateResult(subPackages[1])
			if firstValue > secondValue:
				return 1
			else:
				return 0
		case 6:
			subPackages = package.getPackages()
			firstValue = calculateResult(subPackages[0])
			secondValue = calculateResult(subPackages[1])
			if firstValue < secondValue:
				return 1
			else:
				return 0
		case 7:
			subPackages = package.getPackages()
			firstValue = calculateResult(subPackages[0])
			secondValue = calculateResult(subPackages[1])
			if firstValue == secondValue:
				return 1
			else:
				return 0
		case _:
			print('TypeID unknown')
			return -1


def decodePackage(binaryStr):
	version = int(binaryStr[0:3], 2)
	typeID = int(binaryStr[3:6], 2)
	package = Package(version, typeID)
	match typeID:
		case 4:
			size,number = decodeLiteral(binaryStr[6:])
			package.setSize(size)
			package.setNumber(number)
		case _:
			lengthType, subPackages = getSubPackages(binaryStr[6:])
			package.setPackages(subPackages)
			size = 7
			if lengthType == 1:
				size += 11
			else:
				size += 15
			for subPackage in subPackages:
				size += subPackage.getSize()
			package.setSize(size)

	return package

def decodeLiteral(binaryStr):
	notEnded = True
	binaryNumber = ''
	position = 0
	numberOfParts = 0
	while notEnded:
		numberOfParts += 1
		firstBit = binaryStr[position]
		position += 1
		if firstBit == '0':
			notEnded = False
		
		binaryNumber += binaryStr[position: (position + 4)]
		position += 4
	
	totalSize = 6 + numberOfParts * 5
	
	return totalSize,int(binaryNumber, 2)

def getSubPackages(binaryStr):
	lengthType = int(binaryStr[0],2)

	packages = []
	match lengthType:
		case 1:
			# number of subpackets
			numberOfPackages = int(binaryStr[1:12], 2)
			position = 12
			for i in range(numberOfPackages):
				package = decodePackage(binaryStr[position:])
				packages.append(package)
				position += package.getSize()
		case 0:
			# length of subpackages
			lengthOfSubpackages = int(binaryStr[1:16], 2)
			position = 16
			while position < 16 + lengthOfSubpackages:
				package = decodePackage(binaryStr[position:])
				packages.append(package)
				position += package.getSize()
	return lengthType, packages

def do():
	strInput = readInputFile(16)

	print(do1(strInput))
	print(do2(strInput))

	print('done')


do()<file_sep>/2021/day1.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
    
    bigger = [(x,y) for (x,y) in zip(splitInput, splitInput[1:]) if y > x]

    return len(bigger)

def do2(splitInput):
    
    window = [a + b + c for (a,b,c) in zip(splitInput, splitInput[1:], splitInput[2:])]
    
    return do1(window)

def do():
    strInput = readInputFile(1)

    splitInput = strInput.split('\n')
    intInput = convertToInt(splitInput)
    print(do1(intInput))
    print(do2(intInput))

do()

<file_sep>/2022/day7.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re

tree = {}
dirSizes = {}
fileSizes ={}
parentDir = {}

def do1(splitInput):
	buildFileSystemTree(splitInput)
	calculateSizes('/')
	
	smallDirs = sum([value for value in dirSizes.values() if value <= 100000])
	
	return smallDirs

def do2(splitInput):
	unUsedSpace = 70000000 - dirSizes['/']
	neededSpace = 30000000 - unUsedSpace
	possibleDirs = [value for value in dirSizes.values() if value >= neededSpace]
	
	return min(possibleDirs)

def buildFileSystemTree(splitInput):
	currentDirectory = '/'
	for line in splitInput:
		match line.split(' '):
			case ['$', 'cd', '..']:
				currentDirectory = parentDir[currentDirectory]
			case ['$','cd', '/']:
				currentDirectory = '/'
			case ['$','cd', directory]:
				currentDirectory = currentDirectory + '/' + directory
			case ['$', 'ls']:
				tree[currentDirectory] = []
			case ['dir', folder]:
				tree[currentDirectory].append(currentDirectory + '/' + folder)
				parentDir[currentDirectory + '/' + folder] = currentDirectory
			case [size, name]:
				tree[currentDirectory].append(currentDirectory + '/' + name)
				fileSizes[currentDirectory + '/' + name] = int(size)

def calculateSizes(key):
	if key in fileSizes.keys():
		return fileSizes[key]
	else:
		dirSizes[key] = 0
		for child in tree[key]:
			dirSizes[key] += calculateSizes(child)
		return dirSizes[key]

def do():
	strInput = readInputFile(7)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day7.py
from HelperFunctions import inputsplit
import re

bagCounts = {}

def do1(puzzleInput):
    
    bags = getBags(puzzleInput, False)

    bagsToHoldAShinyGoldBag = []

    for bag in bags.keys():
        if containsShinyBag(bags, bag):
            bagsToHoldAShinyGoldBag.append(bag)

    return len(bagsToHoldAShinyGoldBag)

def do2(puzzleInput):
    
    bags = getBags(puzzleInput, True)

    return bagCount('shiny gold', bags)

def getBags(puzzleInput, numberIsImportant):
    bags = {}
    
    for line in puzzleInput:
        match1 = re.search('(.+) bags contain', line)
        match2 = re.findall('([0-9]+) (\D+) bag[s]?[\.|, ]', line)

        bag = match1.groups()[0]
        bags[bag] = []
        for innerBag in match2:
            if numberIsImportant:
                for _ in range(int(innerBag[0])):
                    bags[bag].append(innerBag[1])
            else:
                bags[bag].append(innerBag[1])
    return bags

def bagCount(bag, bags):    
    if bag in bagCounts.keys():
        return bagCounts[bag]

    count = len(bags[bag])
    for innerbag in bags[bag]:
        count += bagCount(innerbag, bags)
    
    bagCounts[bag] = count

    return count

def containsShinyBag(bags, bag):

    if 'shiny gold' in bags[bag]:
        return True
    for innerBag in bags[bag]:
        if containsShinyBag(bags, innerBag):
            return True
    return False

def do():
    with open ('Input/day7.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2022/day22.py
from enum import IntEnum
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

class Direction(IntEnum):
	NORTH = 3
	EAST = 0
	SOUTH = 1
	WEST = 2

turnRight = {Direction.NORTH:Direction.EAST, Direction.EAST:Direction.SOUTH, Direction.SOUTH:Direction.WEST, Direction.WEST:Direction.NORTH}
turnLeft = {Direction.NORTH:Direction.WEST, Direction.EAST:Direction.NORTH, Direction.SOUTH:Direction.EAST, Direction.WEST:Direction.SOUTH}

east = {1: lambda x,y: (2,x,0,Direction.EAST), 2: lambda x,y: (5,49-x,49,Direction.WEST), 3: lambda x,y: (2,49,x,Direction.NORTH),4: lambda x,y: (5,x,0,Direction.EAST), 5: lambda x,y: (2,49-x,49,Direction.WEST), 6: lambda x,y: (5,49,x,Direction.NORTH)}
south = {1: lambda x,y: (3,0,y,Direction.SOUTH), 2: lambda x,y: (3,y,49,Direction.WEST), 3: lambda x,y: (5,0,y,Direction.SOUTH),4: lambda x,y: (6,0,y,Direction.SOUTH), 5: lambda x,y: (6,y,49,Direction.WEST), 6: lambda x,y: (2,0,y,Direction.SOUTH)}
north = {1:lambda x,y: (6,y,0,Direction.EAST), 2: lambda x,y: (6,49,y,Direction.NORTH), 3: lambda x,y: (1,49,y,Direction.NORTH), 4: lambda x,y: (3,y,0,Direction.EAST), 5: lambda x,y: (3,49,y,Direction.NORTH),6: lambda x,y: (4,49,y,Direction.NORTH)}
west = {1:lambda x,y: (4,49-x,0,Direction.EAST), 2: lambda x,y: (1,x,49,Direction.WEST), 3: lambda x,y: (4,0,x,Direction.SOUTH), 4: lambda x,y: (1,49-x,0,Direction.EAST), 5: lambda x,y: (4,x,49,Direction.WEST), 6: lambda x,y: (1,0,x,Direction.SOUTH)}

def do1(splitInput):
	mapInput,steps = splitInput

	map = createMap(mapInput)

	startY = min([y for (x,y) in map.keys() if x == 0])
	position = (0,startY)
	direction = Direction.EAST
	length = ''
	for char in steps:
		if char == 'R' or char == 'L':
			position = move(int(length),position,direction,map)
			length = ''
			direction = turn(char, direction)
		else:
			length += char
	position = move(int(length),position,direction,map)

	return 1000 * (position[0] + 1) + 4 * (position[1] + 1) + int(direction)
def do2(splitInput):
	mapInput,steps = splitInput
	
	map,cube = createCube(mapInput)
	position = (1,0,0)
	direction = Direction.EAST
	length = ''
	for char in steps:
		if char == 'R' or char == 'L':
			side,posX,posY,direction = moveCube(int(length),position,direction,map,cube)
			position = (side,posX,posY)
			length = ''
			direction = turn(char, direction)
		else:
			length += char
	side,posX,posY,direction = moveCube(int(length),position,direction,map,cube)

	mapPosX,mapPosY = cube[side][(posX,posY)]
	return 1000 * (mapPosX + 1) + 4 * (mapPosY + 1) + int(direction) 

def createMap(mapInput):
	map = {}
	for lineNumber,line in enumerate(mapInput.split('\n')):
		for position,tile in enumerate(line):
			if not tile == ' ':
				map[(lineNumber,position)] = tile
	return map

def createCube(mapInput):
	map = createMap(mapInput)
	cube = {1:{}, 2:{}, 3:{}, 4:{}, 5:{}, 6:{}}

	x = 0
	for j in range(0,50):
		y = 0
		for i in range(50, 100):
			cube[1][x,y] = (j,i)
			y += 1
		y = 0	
		for i in range(100, 150):
			cube[2][x,y] = (j,i)
			y += 1
		x += 1
	x = 0
	for j in range(50,100):
		y = 0
		for i in range(50, 100):
			cube[3][x,y] = (j,i)
			y += 1
		x += 1
	x = 0
	for j in range(100,150):
		y = 0
		for i in range(0,50):
			cube[4][x,y] = (j,i)
			y += 1
		y = 0
		for i in range(50,100):
			cube[5][x,y] = (j,i)
			y += 1
		x += 1
	x = 0
	for j in range(150,200):
		y = 0
		for i in range(0,50):
			cube[6][x,y] = (j,i)
			y += 1
		x += 1

	return map,cube	

def turn(direction, currentDirection):
	if direction == 'R':
		return turnRight[currentDirection]
	else:
		return turnLeft[currentDirection]

def move(steps,position,direction,map):
	currentPos = position
	match direction:
		case Direction.NORTH:
			for _ in range(steps):
				posX,posY = currentPos
				nextPos = (posX - 1, posY)
				if nextPos not in map.keys():
					nextPosX = max([x for (x,y) in map.keys() if y == posY])
					nextPos = (nextPosX,posY)
				if map[nextPos] == '#':
					return currentPos
				else:
					currentPos = nextPos
			return currentPos
		case Direction.EAST:
			for _ in range(steps):
				posX,posY = currentPos
				nextPos = (posX, posY + 1)
				if nextPos not in map.keys():
					nextPosY = min([y for (x,y) in map.keys() if x == posX])
					nextPos = (posX, nextPosY)
				if map[nextPos] == '#':
					return currentPos
				else:
					currentPos = nextPos
			return currentPos
		case Direction.SOUTH:
			for _ in range(steps):
				posX,posY = currentPos
				nextPos = (posX + 1, posY)
				if nextPos not in map.keys():
					nextPosX = min([x for (x,y) in map.keys() if y == posY])
					nextPos = (nextPosX,posY)
				if map[nextPos] == '#':
					return currentPos
				else:
					currentPos = nextPos
			return currentPos
		case Direction.WEST:
			for _ in range(steps):
				posX,posY = currentPos
				nextPos = (posX, posY - 1)
				if nextPos not in map.keys():
					nextPosY = max([y for (x,y) in map.keys() if x == posX])
					nextPos = (posX, nextPosY)
				if map[nextPos] == '#':
					return currentPos
				else:
					currentPos = nextPos
			return currentPos

def moveCube(steps,position,direction,map,cube):
	currentPos = position
	for _ in range(steps):
		match direction:
			case Direction.NORTH:
				side,posX,posY = currentPos
				newSide = side
				nextPosX,nextPosY = (posX - 1, posY)
				if nextPosX < 0:
					newSide,nextPosX,nextPosY,direction = north[side](posX,posY)
				if map[cube[newSide][(nextPosX,nextPosY)]] == '#':
					return side,posX,posY,Direction.NORTH
				else:
					currentPos = (newSide,nextPosX,nextPosY)
			case Direction.EAST:
				side,posX,posY = currentPos
				newSide = side
				nextPosX,nextPosY = (posX, posY + 1)
				if nextPosY > 49:
					newSide,nextPosX,nextPosY,direction = east[side](posX,posY)
				if map[cube[newSide][(nextPosX,nextPosY)]] == '#':
					return side,posX,posY,Direction.EAST
				else:
					currentPos = (newSide,nextPosX,nextPosY)
			case Direction.SOUTH:
				side,posX,posY = currentPos
				newSide = side
				nextPosX,nextPosY = (posX + 1, posY)
				if nextPosX > 49:
					newSide,nextPosX,nextPosY,direction = south[side](posX,posY)
				if map[cube[newSide][(nextPosX,nextPosY)]] == '#':
					return side,posX,posY,Direction.SOUTH
				else:
					currentPos = (newSide,nextPosX,nextPosY)
			case Direction.WEST:
				side,posX,posY = currentPos
				newSide = side
				nextPosX,nextPosY = (posX, posY - 1)
				if nextPosY < 0:
					newSide,nextPosX,nextPosY,direction = west[side](posX,posY)
				if map[cube[newSide][(nextPosX,nextPosY)]] == '#':
					return side,posX,posY,Direction.WEST
				else:
					currentPos = (newSide,nextPosX,nextPosY)
	side,x,y = currentPos
	return side,x,y,direction

def do():
	strInput = readInputFile(22)

	splitInput = strInput.split('\n\n')
	
	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day18.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re
from copy import deepcopy

def do1(splitInput):
	addition = splitInput[0]
	for line in splitInput[1:]:
		addition = '[' + addition + ',' + line + ']'

		addition = reduce(addition)

	magnitude = calculateMagnitude(addition)
	
	return magnitude

def do2(splitInput):
	magnitudes = []
	
	for i in splitInput:
		for j in splitInput:
			if i == j:
				continue
			addition = '[' + i + ',' + j + ']'
			addition = reduce(addition)
			magnitude = calculateMagnitude(addition)
			magnitudes.append(magnitude)	
	
	return max(magnitudes)

def reduce(addition):
	nestingLevel = 0
	lastPosition = -1
	newInput = deepcopy(addition)
	repeat = True
	while repeat:
		nestingLevel = 0
		lastPosition = -1
		addition = deepcopy(newInput)
		repeat = False
		for position,next in enumerate(addition):
			match next:
				case '[':
					nestingLevel += 1
					if nestingLevel > 4:
						left,right = findInner(addition[position:])
						length = len(str(left) + str(right) + ',') + 2
						nextNumberPos = findNextNumber(addition[position+length:])
						newInput = addition[0:position] + '0' + addition[position + length:]
						newInput = addToNextNumber(nextNumberPos, right, position, newInput)
						newInput = addToLastNumber(lastPosition, left, position, newInput)
						repeat = True
						break						
				case ']':
					nestingLevel -= 1
				case a if a.isnumeric():
					if not addition[position-1].isnumeric():	
						lastPosition = position
		# again for big numbers
		if not repeat:
			for position,next in enumerate(addition):
				match next:
					case a if a.isnumeric():
						if addition[position+1].isnumeric():
							number = int(addition[position:position + 2])
							splitLeft = number // 2
							splitRight = (number + 1) // 2
							newInput = addition[0:position] + '[' + str(splitLeft) + ',' + str(splitRight) + ']' + addition[position + 2:]
							repeat = True
							break

	return newInput

def addToNextNumber(nextNumberPos, right, position, newInput):
	if nextNumberPos == -1:
		return newInput
	number = ''
	nextNumberStart = position + nextNumberPos + 1
	currentPos = nextNumberStart
	while newInput[currentPos].isnumeric():
		number += newInput[currentPos]
		currentPos += 1
	
	length = len(number)
	number = int(number)

	
	newInput = newInput[0: nextNumberStart] + str(number + right) + newInput[nextNumberStart + length:]  

	return newInput

def addToLastNumber(lastNumberPos, left, position, newInput):
	if lastNumberPos == -1:
		return newInput
	number = ''
	currentPos = lastNumberPos
	while newInput[currentPos].isnumeric():
		number += newInput[currentPos]
		currentPos += 1
	
	length = len(number)
	number = int(number)

	newInput = newInput[0:lastNumberPos] + str(number + left) + newInput[lastNumberPos + length:]

	return newInput

def findInner(addition):
	left = ''
	right = ''
	isLeft = True
	lastOpened = 0
	for next in addition[1:]:
		match next:
			case '[':
				if isLeft:
					left += next
				else:
					right += next
				lastOpened += 1
			case ']':
				if lastOpened == 0:
					if left.isnumeric():
						left = int(left)
					if right.isnumeric():
						right = int(right)
					return left,right
				if isLeft:
					left += next
				else:
					right += next
				lastOpened -= 1
			case ',':
				if lastOpened == 0:
					isLeft = False
					continue
				else:
					if isLeft:
						left += next
					else:
						right += next
			case _:
				if isLeft:
					left += next
				else:
					right += next

def findNextNumber(input):
	for position,value in enumerate(input):
		if value.isnumeric():
			return position
	return -1

def calculateMagnitude(addition):
	if str(addition).isnumeric():
		return addition
	left,right = findInner(addition)
	
	return 3* calculateMagnitude(left) + 2* calculateMagnitude(right)

def do():
	strInput = readInputFile(18)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day17-2.py
from HelperFunctions import inputsplit
from copy import deepcopy

def do1(puzzleInput):
    points = prepareInput(puzzleInput, 3)

    points = changeState(points, 3)

    count = countActiveCubes(points)

    return count

def do2(puzzleInput):
    points = prepareInput(puzzleInput, 4)

    points = changeState(points, 4)

    count = countActiveCubes(points)

    return count

def changeState(points, dimension):
    newPoints = deepcopy(points)
    for _ in range(6):
        points = deepcopy(newPoints)
        neighbors = set()
        for point in points:
            directNeighbors = getNeighbors(point, points, dimension)
            neighbors = neighbors.union(directNeighbors)
            activeNeighbors = countActiveNeighbors(directNeighbors, points)
            if not (2 <= activeNeighbors <= 3):
                newPoints.remove(point)
        for neighbor in neighbors:
            if neighbor in points:
                continue
            activeNeighbors = countActiveNeighbors(getNeighbors(neighbor, points, dimension), points)
            if activeNeighbors == 3:
                newPoints.add(neighbor)
    return newPoints

def getNeighbors(point, points, dimension):
    neighbors = set()

    if dimension == 3:
        x,y,z = point
    elif dimension == 4:
        x,y,z,w = point

    step = [-1, 0, 1]
    for xStep in step:
        for yStep in step:
            for zStep in step:
                if dimension == 4:
                    for wStep in step:
                        if (xStep == 0 and yStep == 0 and zStep == 0 and wStep == 0):
                            continue
                        neighbors.add((x + xStep, y + yStep, z + zStep, w + wStep))
                elif dimension == 3:
                    if (xStep == 0 and yStep == 0 and zStep == 0):
                        continue
                    neighbors.add((x + xStep, y + yStep, z + zStep))

    return neighbors

def countActiveNeighbors(neighbors, points):
        
    activeNeighbors = [x for x in neighbors if x in points]
    
    return len(activeNeighbors)

def prepareInput(puzzleInput, dimension):
    points = set()

    for x,line in enumerate(puzzleInput):
        for y,cube in enumerate(line):
            if cube == '#':
                if dimension == 4:
                    points.add((x,y,0,0))
                elif dimension == 3:
                    points.add((x,y,0))

    return points

def countActiveCubes(space):
    return len(space)

def do():
    with open ('Input/day17.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2022/day6.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(strInput):
	windowSize = 4
	result = [y + windowSize for y,x in enumerate([strInput[i:i+windowSize] for i in range(len(strInput) - windowSize + 1)]) if len(set(x)) == windowSize][0]
	return result

def do2(strInput):
	windowSize = 14
	result = [y + windowSize for y,x in enumerate([strInput[i:i+windowSize] for i in range(len(strInput) - windowSize + 1)]) if len(set(x)) == windowSize][0]
	return result

def do():
	strInput = readInputFile(6)

	print(do1(strInput))
	print(do2(strInput))

	print('done')


do()<file_sep>/2020/day20.py
from HelperFunctions import inputsplit
import re

class Tile:
    def __init__(self, number=0, upper=[], lower=[], right=[], left=[], inner=[]):
        self.upper = upper.copy()
        self.lower = lower.copy()
        self.right = right.copy()
        self.left = left.copy()
        
        self.inner = inner

        self.number = number

        self.neighbors = set()

        self.leftNeighbor = 0
        self.rightNeighbor = 0
        self.upperNeighbor = 0
        self.lowerNeighbor = 0

        self.fixed = False

    def flip(self):
        if self.fixed:
            return
        tmp = self.upper.copy()
        self.upper = self.lower.copy()
        self.lower = tmp.copy()
        self.right.reverse()
        self.left.reverse()

        self.inner.reverse()     

    def rotate(self, angle):
        if self.fixed:
            return
        if angle == 0:
            return
        if angle == 90:
            tmp = self.upper
            self.upper = self.left.copy()
            self.upper.reverse()
            self.left = self.lower.copy()
            self.lower = self.right.copy()
            self.lower.reverse()
            self.right = tmp.copy()

            self.rotateInner()
        if angle == 180:
            self.rotate(90)
            self.rotate(90)
        if angle == 270:
            self.rotate(90)
            self.rotate(90)
            self.rotate(90)
    
    def rotateInner(self):
        newInner = []
        for x in range(len(self.inner)):
            column = []
            for y in range(len(self.inner)):
                column.append(self.inner[y][x])
            column.reverse()
            newInner.append(column)
        self.inner = newInner.copy()

    def checkForEqualSides(self, otherTile):
        if self.upper == otherTile.lower:
            if self.fixed:
                otherTile.fixed = True
                self.upperNeighbor = otherTile
                otherTile.lowerNeighbor = self
            return True
        if self.lower == otherTile.upper:
            if self.fixed:
                otherTile.fixed = True
                self.lowerNeighbor = otherTile
                otherTile.upperNeighbor = self
            return True
        if self.right == otherTile.left:
            if self.fixed:
                otherTile.fixed = True
                self.rightNeighbor = otherTile
                otherTile.leftNeighbor = self
            return True
        if self.left == otherTile.right:
            if self.fixed:
                otherTile.fixed = True
                self.leftNeighbor = otherTile
                otherTile.rightNeighbor = self
            return True
        return False

    def fixNeighbors(self):
        for neighbor in self.neighbors:            
            self.couldBeNeighbors(neighbor)

    def couldBeNeighbors(self, otherTile):
        flipped = False
        while True:
            for angle in [0, 90, 180, 270]:
                otherTile.rotate(angle)
                if self.checkForEqualSides(otherTile):
                    self.neighbors.add(otherTile)
                    return True
            otherTile.flip()
            if flipped:
                break
            flipped = True

        return False
            
def do1(puzzleInput):
    tiles = extractTiles(puzzleInput)

    neighbors = getNeighbors(tiles)

    multiplied = 1
    for key,neighbors in neighbors.items():
        if len(neighbors) == 2:
            multiplied *= key

    return multiplied

def do2(puzzleInput):
    tiles = extractTiles(puzzleInput)

    neighbors = getNeighbors(tiles)

    corners = [x for x in tiles if len(x.neighbors) == 2]
    
    arrange(tiles, neighbors, corners[0])

    corner1 = [x for x in corners if x.rightNeighbor != 0 and x.lowerNeighbor != 0][0]

    image = buildImage(tiles, corner1)
    
    notSeaMonsters = notSeaMonsterHashes(image)

    return notSeaMonsters

def notSeaMonsterHashes(image):
    imageTile = Tile(inner=image)
    
    numberOfHashes = 0    
    for line in imageTile.inner:
        numberOfHashes += line.count('#')

    middleLine = '#[\.\#]{4}##[\.\#]{4}##[\.\#]{4}###'
    upperLine = '[\.\#]{18}#[\.\#]{1}'
    lowerLine = '[\.\#]{1}#[\.\#]{2}#[\.\#]{2}#[\.\#]{2}#[\.\#]{2}#[\.\#]{2}#[\.\#]{3}'
    rotated = False
    while True:
        for rotationAngle in [0, 90, 180, 270]:
            seaMonsters = 0
            imageTile.rotate(rotationAngle)
            for index,line in enumerate(imageTile.inner):
                s = ''
                imageTile.inner[index] = s.join(line)

            for index,line in enumerate(imageTile.inner[0:-1]):
                matchMiddle = re.search(middleLine, line)
                if matchMiddle:
                    startPos = matchMiddle.start()
                    matchLower = re.fullmatch(lowerLine, imageTile.inner[index + 1][startPos:startPos + 20])
                    matchUpper = re.fullmatch(upperLine, imageTile.inner[index - 1][startPos:startPos + 20])
                    if matchLower and matchUpper:
                        seaMonsters += 1
            if seaMonsters:
                return numberOfHashes - seaMonsters * 15
        
        imageTile.flip()
        if rotated:
            break
        rotated = True

    return numberOfHashes - seaMonsters * 15

def arrange(tiles, neighbors, tile):
    tile.fixed = True
    tile.fixNeighbors()
    while any([not x.fixed for x in tiles]):
        for otherTile in [x for x in tiles if x.fixed]:
            otherTile.fixNeighbors()

def buildImage(tiles, corner1):
    image = []
    currentTile = corner1
    lowerNeighbor = currentTile.lowerNeighbor
    while lowerNeighbor:
        imageLine = currentTile.inner.copy()
        rightNeighbor = currentTile.rightNeighbor
        while rightNeighbor:
            for x,line in enumerate(imageLine):
                imageLine[x] = line + rightNeighbor.inner[x]
            rightNeighbor = rightNeighbor.rightNeighbor
        for line in imageLine:
            image.append(line)
        currentTile = lowerNeighbor
        lowerNeighbor = currentTile.lowerNeighbor
    imageLine = currentTile.inner.copy()
    rightNeighbor = currentTile.rightNeighbor
    while rightNeighbor:
        for x,line in enumerate(imageLine):
            imageLine[x] = line + rightNeighbor.inner[x]
        rightNeighbor = rightNeighbor.rightNeighbor
    for line in imageLine:
        image.append(line)

    return image

def extractTiles(puzzleInput):
    tiles = []

    for part in puzzleInput:
        lines = part.split('\n')
        number = int(lines[0][5:9])

        upper = list(lines[1])
        lower = list(lines[-1])

        left = []
        right = []
        for line in lines[1:]:
            left.append(line[0])
            right.append(line[-1])
        
        inner = []
        for line in lines[2:-1]:
            inner.append(list(line[1:-1]))

        tiles.append(Tile(number, upper, lower, right, left, inner))

    return tiles

def getNeighbors(tiles):
    neighbors = {}
    for tile in tiles:
        neighbors[tile.number] = []
        for otherTile in tiles:
            if tile == otherTile:
                continue
            if tile.couldBeNeighbors(otherTile):
                neighbors[tile.number].append(otherTile.number)

    return neighbors

def do():
    with open ('Input/day20.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n\n')
    
    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2021/day15.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from collections import defaultdict
from copy import deepcopy

def do1(splitInput):
	
	costs = getSums(splitInput)

	return costs[(len(splitInput[0]) - 1, len(splitInput) - 1)]

def do2(splitInput):
	newMap = generateBiggerMap(splitInput)

	costs = getSums(newMap)

	return costs[(len(newMap[0]) - 1, len(newMap) - 1)]

def generateBiggerMap(splitInput):
	newLines = []
	for line in splitInput:
		line = convertToInt(line)
		newPart = deepcopy(line)
		for i in range(4):
			newPart = [x + 1 if x < 9 else 1 for x in newPart]
			line += newPart
		newLines.append(line)

	newMap = deepcopy(newLines)
	for i in range(1, 5):
		for line in newLines:
			newMap.append([x + i if x + i < 10 else (x + i) - 9 for x in line])

	return newMap			

def getSums(splitInput):
	costs = defaultdict(lambda: 1000000000)
	costs[(0,0)] = 0	
	changed = True

	while(changed):
		changed = False
		for lineNumber,line in enumerate(splitInput):
			for position,risk in enumerate(line):
				if lineNumber == 0 and position == 0:
					continue
				left = (lineNumber, position - 1)
				right = (lineNumber, position + 1)
				up = (lineNumber - 1, position)
				down = (lineNumber + 1, position)

				minNeighborCost = 1000000000
				for neighbor in [left, right, up, down]:
					minNeighborCost = min(minNeighborCost, costs[neighbor])

				newCosts = int(risk) + minNeighborCost
				if newCosts < costs[(lineNumber, position)]:
					changed = True
					costs[(lineNumber, position)] = newCosts
	return costs

def do():
	strInput = readInputFile(15)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day10.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from collections import defaultdict

correspondingCharacters = {')':'(', ']':'[', '}':'{', '>':'<'}
correspondingCharacters_reverse = {'(':')', '[':']', '{':'}', '<':'>'}
points = {')': 3, ']': 57, '}': 1197, '>': 25137, None: 0}
points2 = {')': 1, ']': 2, '}': 3, '>': 4, None: 0}

def do1(splitInput):
	score = 0

	for line in splitInput:
		illegalCharacter,_ = findIllegalCharacter(line)
		score += points[illegalCharacter]
	
	return score

def do2(splitInput):
	scores = []

	for line in splitInput:
		illegalCharacter,remainingCloses = findIllegalCharacter(line)
		if not illegalCharacter:
			lineScore = 0
			while remainingCloses:
				lineScore = lineScore * 5
				lineScore += points2[correspondingCharacters_reverse[remainingCloses.pop()]]
			scores.append(lineScore)
	
	scores.sort()
	return scores[len(scores) // 2]

def findIllegalCharacter(line):
	lastOpened = []
	for character in line:
		match character:
			case '(' | '[' | '{' | '<':
				lastOpened.append(character)
			case ']' | ')' | '}' | '>' :
				correspondingCharacter = correspondingCharacters[character]
				if lastOpened[-1] != correspondingCharacter:
					return character,lastOpened
				else:
					lastOpened.pop()
	return None,lastOpened

def do():
	strInput = readInputFile(10)

	splitInput = strInput.split('\n')
	
	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day9.py
from HelperFunctions import inputsplit
from HelperFunctions import convertToInt
from itertools import islice

def do1(puzzleInput, preambelLength):
    
    for position in range(preambelLength, len(puzzleInput) - preambelLength):
        
        splitArray = puzzleInput[(position - preambelLength):position]

        possibleSums = [(x,y) for x in splitArray for y in splitArray if (x + y) == puzzleInput[position]]

        if len(possibleSums) == 0:
            return puzzleInput[position]

    return 'nothing found'

def do2(puzzleInput, invalidNumber):
    
    sliceSize = 2

    while True:
        for i in range(len(puzzleInput)):
            arraySlice = puzzleInput[slice(i, i + sliceSize, 1)]
            
            if (sum(arraySlice) == invalidNumber):
                return min(arraySlice) + max(arraySlice)
    
        sliceSize += 1
        
    return 'nothing found'

def do():
    with open ('Input/day9.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')
    intInput = convertToInt(splitInput)
    preambelLength = 25

    result1 = do1(intInput, preambelLength)
    print(result1)
    print(do2(intInput, result1))
    
do()<file_sep>/2020/day6.py
from HelperFunctions import inputsplit

def do1(puzzleInput):

    return getGroupCount(puzzleInput, union)

def do2(puzzleInput):
    
    return getGroupCount(puzzleInput, intersection)

def getGroupCount(puzzleInput, mergeFunction):
    groupCount = 0

    for group in puzzleInput:
        persons = group.split('\n')
        answers = set(persons[0])
        for otherPerson in persons[1:]:
            answer = set(otherPerson)
            answers = mergeFunction(answers, answer)        

        groupCount += len(answers)

    return groupCount    

def intersection(set1, set2):
    return set1.intersection(set2)

def union(set1, set2):
    return set1.union(set2)

def do():
    with open ('Input/day6.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2019/day10.py
import math

input =""".###.#...#.#.##.#.####..
.#....#####...#.######..
#.#.###.###.#.....#.####
##.###..##..####.#.####.
###########.#######.##.#
##########.#########.##.
.#.##.########.##...###.
###.#.##.#####.#.###.###
##.#####.##..###.#.##.#.
.#.#.#####.####.#..#####
.###.#####.#..#..##.#.##
########.##.#...########
.####..##..#.###.###.#.#
....######.##.#.######.#
###.####.######.#....###
############.#.#.##.####
##...##..####.####.#..##
.###.#########.###..#.##
#.##.#.#...##...#####..#
##.#..###############.##
##.###.#####.##.######..
##.#####.#.#.##..#######
...#######.######...####
#....#.#.#.####.#.#.#.##
"""


def do():
    grid = input.split()
    asteroids = getAsteroids(grid)
    counts = {}
    detectedAsteroids = {}

    for x,y in asteroids:
        count, seenAsteroids = detectAsteroids(asteroids, (x,y))
        counts[(x,y)] = count
        detectedAsteroids[(x,y)] = seenAsteroids
    return counts, detectedAsteroids

def do2(center, asteroids):
    angles = {}
    upperPoint = (center[0], 0)

    for asteroid in asteroids:
        angle = getAngle(upperPoint, center, asteroid)
        angles[asteroid] = angle
    
    return angles

def getAsteroids(grid):
    asteroids = []
    for y in range(len(grid)):
        line = grid[y]
        for x in range(len(line)):
            point = line[x]
            if point != '#':
                continue
            asteroids.append((x,y))
    return asteroids

def getAngle(a, b, c):
    ang = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0]))
    return ang + 360 if ang < 0 else ang

def detectAsteroids(asteroids, center):
    count = 0
    seenAsteroids = []
    for x,y in asteroids:
            if (x,y) == center:
                continue
            if canBeSeen(center, asteroids, (x,y)):
                count += 1
                seenAsteroids.append((x,y))
    return count, seenAsteroids

def canBeSeen(center, asteroids, endPoint):
    canBeSeen = True
    for x,y in asteroids:
        if (x,y) == center or (x,y) == endPoint:
            continue
        if isBetween(center, endPoint, (x,y)):
            canBeSeen = False
            break
    return canBeSeen

def isBetween(center, endPoint, point):
    crossProduct = (point[1] - center[1]) * (endPoint[0] - center[0]) - (point[0] - center[0]) * (endPoint[1] - center[1])
    if crossProduct != 0:
        return False
    dotProduct = (point[0] - center[0]) * (endPoint[0] - center[0]) + (point[1] - center[1])*(endPoint[1] - center[1])
    if dotProduct < 0:
        return False
    squaredLength = (endPoint[0] - center[0])*(endPoint[0] - center[0]) + (endPoint[1] - center[1])*(endPoint[1] - center[1])
    if dotProduct > squaredLength:
        return False
    return True

#part1
counts, asteroids = do()

maxKey = max(counts, key=counts.get)
maxValue = counts[maxKey]

print(maxValue)

#part2
angles = do2(maxKey, asteroids[maxKey])
sortedAngles = list((sorted(angles.items(), key=lambda item: item[1])))
print (sortedAngles[199][0][0] * 100 + sortedAngles[199][0][1])





<file_sep>/2020/day2.py
from HelperFunctions import inputsplit
import re

def do1(puzzleInput):
    numValidPasswords = 0
    
    for line in puzzleInput:
        match = re.match('([0-9]+)-([0-9]+) ([A-Za-z]): ([A-Za-z]+)', line)

        minCount, maxCount, letter, password = [int(x) if x.isnumeric() else x for x in match.groups()]

        numberOfOccurences = password.count(letter)

        if  minCount <= numberOfOccurences <= maxCount:
            numValidPasswords += 1

    return numValidPasswords

def do2(puzzleInput):
    numValidPasswords = 0
    
    for line in puzzleInput:
        match = re.match('([0-9]+)-([0-9]+) ([A-Za-z]): ([A-Za-z]+)', line)

        pos1, pos2, letter, password = [int(x) - 1 if x.isnumeric() else x for x in match.groups()]

        if (password[pos1] == letter and not password[pos2] == letter) or (password[pos2] == letter and not password[pos1] == letter):
            numValidPasswords += 1

    return numValidPasswords


def do():
    with open ('Input/day2.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2022/day1.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def calculateElfCalories(splitInput):
	elfCalories = []
	
	for elf in splitInput:
		calories = convertToInt(elf.split('\n'))
		elfCalories.append(sum(calories))	
	
	return elfCalories

def do1(splitInput):
	elfCalories = calculateElfCalories(splitInput)
	return max(elfCalories)

def do2(splitInput):
	elfCalories = calculateElfCalories(splitInput)
	elfCalories.sort(reverse=True)
	
	return sum(elfCalories[0:3])

def do():
	strInput = readInputFile(1)

	splitInput = strInput.split('\n\n')
	
	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2021/day8.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from collections import defaultdict

numberMapping = {1: ['c', 'f'], 2: ['a', 'c', 'd', 'e', 'g'], 3: ['a', 'c', 'd', 'f', 'g'], 4: ['b', 'c', 'd', 'f'], 5: ['a', 'b', 'd', 'f', 'g'], 6: ['a', 'b', 'd', 'e', 'f', 'g'], 7: ['a', 'c', 'f'], 8: ['a', 'b', 'c', 'd', 'e', 'f', 'g'], 9: ['a', 'b', 'c', 'd', 'f', 'g'], 0: ['a', 'b', 'c', 'e', 'f', 'g']}
allPossibleDigitsPerNumber = {2: ['c', 'f'], 3: ['a', 'c', 'f'], 4: ['b', 'c', 'd', 'f'], 7: ['a', 'b', 'c', 'd', 'e', 'f', 'g'], 5: ['a', 'b', 'c', 'd', 'e', 'f', 'g'], 6: ['a', 'b', 'c', 'd', 'e', 'f', 'g']}

def do1(splitInput):
	uniqueDigits = 0

	for line in splitInput:
		input,output = line.split('|')

		outputDigits = output.split(' ')

		for digit in outputDigits:
			if len(digit) in [2, 3, 4, 7]:
				uniqueDigits += 1
	
	return uniqueDigits

def do2(splitInput):
	sumOutputValues = 0

	for line in splitInput:
		input,output = line.split('|')

		inputValues = input.split(' ')
		outputValues = output.split(' ')

		mapping = getMapping(inputValues)
		outputValue = calculateOutputValues(outputValues, mapping)

		sumOutputValues += outputValue
	
	return sumOutputValues

def getMapping(inputValues):
	mapping = {'a': set(('a', 'b', 'c', 'd', 'e', 'f', 'g')), 'b': set(('a', 'b', 'c', 'd', 'e', 'f', 'g')), 'c': set(('a', 'b', 'c', 'd', 'e', 'f', 'g')), 'd': set(('a', 'b', 'c', 'd', 'e', 'f', 'g')), 'e': set(('a', 'b', 'c', 'd', 'e', 'f', 'g')), 'f': set(('a', 'b', 'c', 'd', 'e', 'f', 'g')), 'g': set(('a', 'b', 'c', 'd', 'e', 'f', 'g'))}

	inputPerLength = defaultdict(lambda: [])

	for inputValue in inputValues[0:-1]:
		length = len(inputValue)
		inputPerLength[length].append([x for x in inputValue])
		possibleValues = set(allPossibleDigitsPerNumber[length])
		for digit in inputValue:
			mapping[digit].intersection_update(possibleValues)

	# c & f (1)
	one1,one2 = [x for x in mapping.keys() if mapping[x] == {'c', 'f'}]
	sumOfOne = countOccurence(one1, inputValues)	
	
	if sumOfOne == 8:
		mapping[one1] = {'c'}
		removeFromMapping(one1, 'c', mapping)
		removeFromMapping(one2, 'f', mapping)
	else:
		mapping[one1] = {'f'}
		removeFromMapping(one1, 'f', mapping)
		removeFromMapping(one2, 'c', mapping)

	# a (7)
	seven = [x for x in mapping.keys() if mapping[x] == {'a'}][0]
	removeFromMapping(seven, 'a', mapping)

	# b & d (4)
	four1,four2 = [x for x in mapping.keys() if mapping[x] == {'b', 'd'}]
	sumOfFour = countOccurence(four1, inputValues)
	if sumOfFour == 6:
		mapping[four1] = {'b'}
		removeFromMapping(four1, 'b', mapping)
		removeFromMapping(four2, 'd', mapping)
	else:
		mapping[four1] = {'d'}
		removeFromMapping(four1, 'd', mapping)
		removeFromMapping(four2, 'b', mapping)

	# e & g
	other1,other2 = [x for x in mapping.keys() if mapping[x] == {'e', 'g'}]
	sumOfOthers = countOccurence(other1, inputValues)
	if sumOfOthers == 4:
		mapping[other1] = {'e'}
		removeFromMapping(other1, 'e', mapping)
	else:
		mapping[other1] = {'g'}
		removeFromMapping(other1, 'g', mapping)
	
	return mapping

def countOccurence(digit, inputValues):
	sumOfDigit = 0
	for input in inputValues:
		if digit in input:
			sumOfDigit += 1
	return sumOfDigit

def removeFromMapping(rightKey, digit, mapping):
	for key in mapping.keys():
			if key != rightKey:
				if digit in mapping[key]:
					mapping[key].remove(digit)

def calculateOutputValues(outputValues, mapping):
	result = ''
	for outputValue in outputValues:
		if outputValue == '':
			continue
		
		resultStr = []
		for digit in outputValue:
			resultStr.append(list(mapping[digit])[0])
		sortedResult = sorted(resultStr)

		resultDigit = str([x for x in numberMapping.keys() if sorted(numberMapping[x]) == sortedResult][0])
		result += resultDigit	
	
	return int(result)

def do():
	strInput = readInputFile(8)
	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2018/day9_2.py
from collections import deque

def do(players, marbles):

    player = 1
    
    marble_list = deque([0])
    scores = {}

    for marble in range(1, marbles + 1):
        if (marble % 23 == 0):
            points = marble

            marble_list.rotate(7)
            points += marble_list.popleft()

            if player not in scores:
                scores[player] = 0
            
            scores[player] += points

        else:
            marble_list.rotate(-2)
            marble_list.insert(0, marble)
        
        player = (player + 1) % players
    
    return max(scores.values())
    

print(do(477, 7085100))<file_sep>/2021/day19.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re
from collections import Counter

rotations = ['x,y,z', '-x,-y,-z', 'y,-x,z', '-y,x,-z', '-x,-y,z', 'x,y,-z', '-y,x,z', 'y,-x,-z', 'z,y,-x', '-z,-y,x', 'y,-z,-x',
'-y,z,x', '-z,-y,-x', 'z,y,x', '-y,z,-x', 'y,-z,x', 'z,-x,-y', '-z,x,y', '-x,-z,-y', 'x,z,y',
'-z,x,-y', 'z,-x,y', 'x,z,-y', '-x,-z,y', 'z,-y,x', '-z,y,-x', '-y,-z,x', 'y,z,-x', '-z,y,x', 'z,-y,-x',
'y,z,x', '-y,-z,-x', 'z,x,y', '-z,-x,-y', 'x,-z,y', '-x,z,-y', '-z,-x,y', 'z,x,-y',
'-x,z,y', 'x,-z,-y', '-x,y,-z', 'x,-y,z', 'y,x,-z', '-y,-x,z', 'x,-y,-z', '-x,y,z', '-y,-x,-z', 'y,x,z']

alreadyInScanner0 = []
scannerPositions = [(0,0,0)]

def do1(splitInput):
	scannerPoints = parseInput(splitInput)
	
	while len(alreadyInScanner0) < len(scannerPoints.keys()) - 1:
		scannerOrientations = findScannerOrientation(scannerPoints)

		addPointsToScanner(scannerOrientations, scannerPoints)
	
	return len(scannerPoints[0])

def do2():
	
	return getLargestScannerDistance()

def getLargestScannerDistance():
	distances = []
	for x1,y1,z1 in scannerPositions:
		for x2,y2,z2 in scannerPositions:
			distance = abs(x1-x2) + abs(y1-y2) + abs(z1-z2)
			distances.append(distance)
	return max(distances)

def getRotatedPoint(point, rotation):
	x,y,z = point
	
	match = re.match('([-]?[xyz]),([-]?[xyz]),([-]?[xyz])', rotation)

	newPoint = []
	for part in match.groups():
		negative = 1
		if len(part) > 1:
			negative = -1
			part = part[1]
		match part:
			case 'x':
				newPoint.append(negative * x)
			case 'y':
				newPoint.append(negative * y)
			case 'z':
				newPoint.append(negative * z)
	return (newPoint[0], newPoint[1], newPoint[2])

def addPointsToScanner(scannerOrientations, scannerPoints):
	for scannerNr,position,rotation in scannerOrientations:
		if scannerNr in alreadyInScanner0:
			continue
		xPos,yPos,zPos = position
		scannerPositions.append(position)

		firstScanner = set(scannerPoints[0])
		secondScanner = scannerPoints[scannerNr]

		for point in secondScanner:
			x,y,z = getRotatedPoint(point, rotation)
			newPoint = (xPos - x, yPos - y, zPos - z)
			firstScanner.add(newPoint)
		
		scannerPoints[0] = list(firstScanner)
		alreadyInScanner0.append(scannerNr)

def findScannerOrientation(scannerPoints):
	scannerOrientation = []
	scanner1 = scannerPoints[0]
	for secondScanner,scanner2 in scannerPoints.items():
		if secondScanner == 0 or secondScanner in alreadyInScanner0:
			continue
		for rotation in rotations:
			newPoints = Counter()
			for point1 in scanner1:
				x1,y1,z1 = point1
				for point2 in scanner2:
					x2,y2,z2 = getRotatedPoint(point2, rotation)

					newPoint = (x1 + x2, y1 + y2, z1 + z2)
					newPoints[newPoint] += 1
			
			result = [x for x in newPoints.keys() if newPoints[x] > 10]
			if result:
				scannerOrientation.append((secondScanner, result[0], rotation))

	return scannerOrientation

def parseInput(splitInput):
	scannerPoints = {}
	for scanner in splitInput:
		scanner = scanner.split('\n')
		match = re.match('--- scanner ([0-9]+) ---', scanner[0])
		scannerNumber = int(match.groups()[0])
		scannerPoints[scannerNumber] = []
		for line in scanner[1:]:
			x,y,z = line.split(',')
			x = int(x)
			y = int(y)
			z = int(z)
			scannerPoints[scannerNumber].append((x,y,z))

	return scannerPoints

def do():
	strInput = readInputFile(19)

	splitInput = strInput.split('\n\n')

	print(do1(splitInput))
	print(do2())

	print('done')


do()<file_sep>/2018/day14.py
input = 894501

def doOne():
    l = [3,7]

    elf1 = 0
    elf2 = 1

    while True:
        newRecipe = l[elf1] + l[elf2]

        numbers = [int(x) for x in str(newRecipe)]
        for number in numbers:
            l.append(number)

        elf1 = (elf1 + 1 + l[elf1]) % len(l)
        elf2 = (elf2 + 1 + l[elf2]) % len(l)

        if len(l) >= input + 10:
            return(l[input:])

def doTwo():
    l = [3,7]

    elf1 = 0
    elf2 = 1

    inputstr = [int(x) for x in str(input)]

    resultIndex = 2
    index = 0

    while True:
        
        newRecipe = l[elf1] + l[elf2]

        numbers = [int(x) for x in str(newRecipe)]
        for number in numbers:
            if number == inputstr[index]:
                resultIndex = len(l) - index
                index += 1
                if index == len(inputstr):
                    return resultIndex
            else:
                index = 0
                if number == inputstr[index]:
                    resultIndex = len(l) - index
                    index += 1
                    if index == len(inputstr):
                        return resultIndex
            l.append(number)

        elf1 = (elf1 + 1 + l[elf1]) % len(l)
        elf2 = (elf2 + 1 + l[elf2]) % len(l)        

   
print(doOne())
print(doTwo())<file_sep>/2020/day16.py
from HelperFunctions import inputsplit
from HelperFunctions import convertToInt
from copy import deepcopy
import re

def do1(puzzleInput):
    valid = puzzleInput[0].split('\n')

    nearbyTickets = puzzleInput[2].split('\n')[1:]

    validFields = extractValidFields(valid)

    invalidValues = checkNearbyTickets(nearbyTickets, validFields)

    return sum(invalidValues)

def do2(puzzleInput):
    valid = puzzleInput[0].split('\n')

    myTicket = puzzleInput[1].split('\n')[1]

    nearbyTickets = puzzleInput[2].split('\n')[1:]

    validFields = extractValidFields(valid)

    validTickets = getValidTickets(nearbyTickets, validFields)
    
    assignedFields = getActualFields(validTickets, validFields)

    result = multiplyDepartureValues(assignedFields, myTicket)

    return result

def extractValidFields(valid):
    validFields = {}
    for line in valid:
        match = re.match('([a-z ]+): ([0-9]+)-([0-9]+) or ([0-9]+)-([0-9]+)', line)
        name, x1, x2, y1, y2 = [int(x) if x.isnumeric() else x for x in match.groups()]

        validFields[name] = []
        for i in range(x1, x2 + 1):
            validFields[name].append(i)
        for i in range(y1, y2 + 1):
            validFields[name].append(i)

    return validFields

def checkNearbyTickets(tickets, validFields):
    invalidValues = []
    for ticket in tickets:
        strfields = ticket.split(',')
        fields = convertToInt(strfields)
        for field in fields:
            valid = False
            for value in validFields.values():
                if field in value:
                    valid = True
            if not valid:
                invalidValues.append(field)

    return invalidValues

def getValidTickets(tickets, validFields):
    validIntTickets = []
    for ticket in tickets:
        ticketValid = True
        strfields = ticket.split(',')
        fields = convertToInt(strfields)
        for field in fields:
            valid = False
            for value in validFields.values():
                if field in value:
                    valid = True
            if not valid:
                ticketValid = False
                break
        if ticketValid:
            validIntTickets.append(fields)
    
    return validIntTickets

def getActualFields(validTickets, validFields):
    possibleFields = {}
    for position in range(0, len(validTickets[0])):
        possibleFields[position] = []
        for key,value in validFields.items():
            possibleFields[position].append(key)
            
    for ticket in validTickets:
        for position,field in enumerate(ticket):
            for key in possibleFields[position]:
                if not (field in validFields[key]):
                    possibleFields[position].remove(key)

    solution = {}    
    while (len(solution.keys()) != len(validFields.keys())):
        for key,value in possibleFields.items():
            if len(value) == 1:
                solution[key] = value[0]
                for otherValues in possibleFields.values():
                    if solution[key] in otherValues:
                        otherValues.remove(solution[key])

    return solution

def multiplyDepartureValues(assignedFields, myTicket):
    myTicket = [int(x) for x in myTicket.split(',')]

    result = 1
    for key,value in assignedFields.items():
        if re.match('departure', value):
            result *= myTicket[key]
    
    return result

def do():
    with open ('Input/day16.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2022/create.py
import os
import sys
from pathlib import Path

def createFiles(filepath, filepathInput, filepathExampleInput, day):
    if not Path(filepath).exists():
        with open(filepath, 'w') as f:
            f.writelines(['from HelperFunctions import readInputFile\n', 'from HelperFunctions import readExampleInput\n', 'from HelperFunctions import convertToInt\n\n', 'def do1(splitInput):\n', 
            '\treturn \'done\'\n\n', 'def do2(splitInput):\n', '\treturn \'done\'\n\n', 'def do():\n', f'\tstrInput = readInputFile({day})\n', f'\tstrInput = readExampleInput({day})\n\n',
            '\tprint(do1(strInput))\n', '\tprint(do2(strInput))\n\n', '\tprint(\'done\')\n\n\n', 'do()'])
    if not Path(filepathInput).exists():
        open(filepathInput, 'a').close()
    if not Path(filepathExampleInput).exists():
        open(filepathExampleInput, 'a').close()

if __name__ == '__main__':
    if len(sys.argv) > 1:
        day = sys.argv[1]
    else:
        files = [Path(f).stem for f in os.listdir() if Path(f).is_file()]
        day = max([int(f.replace('day', '')) for f in files if f.startswith('day')], default=0) + 1
        
    filepath = os.path.join(f'day{day}.py')
    filepathInput = os.path.join('Input', f'day{day}.txt')
    filepathExampleInput = os.path.join('Input', f'day{day}_example.txt')
    createFiles(filepath, filepathInput, filepathExampleInput, day)      <file_sep>/2018/day7.py
input = """Step Y must be finished before step A can begin.
Step O must be finished before step C can begin.
Step P must be finished before step A can begin.
Step D must be finished before step N can begin.
Step T must be finished before step G can begin.
Step L must be finished before step M can begin.
Step X must be finished before step V can begin.
Step C must be finished before step R can begin.
Step G must be finished before step E can begin.
Step H must be finished before step N can begin.
Step Q must be finished before step B can begin.
Step S must be finished before step R can begin.
Step M must be finished before step F can begin.
Step N must be finished before step Z can begin.
Step E must be finished before step I can begin.
Step A must be finished before step R can begin.
Step Z must be finished before step F can begin.
Step K must be finished before step V can begin.
Step I must be finished before step J can begin.
Step R must be finished before step W can begin.
Step B must be finished before step J can begin.
Step W must be finished before step V can begin.
Step V must be finished before step F can begin.
Step U must be finished before step F can begin.
Step F must be finished before step J can begin.
Step X must be finished before step C can begin.
Step T must be finished before step Q can begin.
Step B must be finished before step F can begin.
Step Y must be finished before step L can begin.
Step P must be finished before step E can begin.
Step A must be finished before step J can begin.
Step S must be finished before step I can begin.
Step S must be finished before step A can begin.
Step K must be finished before step R can begin.
Step D must be finished before step C can begin.
Step R must be finished before step U can begin.
Step K must be finished before step U can begin.
Step D must be finished before step K can begin.
Step S must be finished before step M can begin.
Step D must be finished before step E can begin.
Step A must be finished before step K can begin.
Step G must be finished before step I can begin.
Step O must be finished before step M can begin.
Step U must be finished before step J can begin.
Step T must be finished before step S can begin.
Step C must be finished before step M can begin.
Step S must be finished before step J can begin.
Step N must be finished before step V can begin.
Step P must be finished before step N can begin.
Step D must be finished before step M can begin.
Step A must be finished before step B can begin.
Step Z must be finished before step R can begin.
Step T must be finished before step N can begin.
Step K must be finished before step J can begin.
Step N must be finished before step A can begin.
Step M must be finished before step R can begin.
Step E must be finished before step A can begin.
Step Y must be finished before step O can begin.
Step O must be finished before step B can begin.
Step O must be finished before step A can begin.
Step I must be finished before step V can begin.
Step M must be finished before step Z can begin.
Step D must be finished before step U can begin.
Step O must be finished before step S can begin.
Step Z must be finished before step W can begin.
Step M must be finished before step A can begin.
Step N must be finished before step E can begin.
Step M must be finished before step U can begin.
Step R must be finished before step J can begin.
Step W must be finished before step F can begin.
Step I must be finished before step U can begin.
Step E must be finished before step U can begin.
Step Y must be finished before step R can begin.
Step Z must be finished before step K can begin.
Step C must be finished before step F can begin.
Step B must be finished before step V can begin.
Step G must be finished before step B can begin.
Step O must be finished before step G can begin.
Step E must be finished before step Z can begin.
Step A must be finished before step V can begin.
Step Y must be finished before step Q can begin.
Step P must be finished before step D can begin.
Step X must be finished before step G can begin.
Step I must be finished before step W can begin.
Step M must be finished before step V can begin.
Step T must be finished before step M can begin.
Step G must be finished before step J can begin.
Step T must be finished before step I can begin.
Step H must be finished before step B can begin.
Step C must be finished before step E can begin.
Step Q must be finished before step V can begin.
Step H must be finished before step U can begin.
Step X must be finished before step K can begin.
Step D must be finished before step T can begin.
Step X must be finished before step W can begin.
Step P must be finished before step Z can begin.
Step C must be finished before step U can begin.
Step Y must be finished before step Z can begin.
Step L must be finished before step F can begin.
Step C must be finished before step J can begin.
Step T must be finished before step W can begin."""

result = []

import re
import string
def prepareData():
    splitInput = input.split('\n')

    dic = {}
    for condition in splitInput:
        match = re.search('\s([A-Z])\smust be finished before step ([A-Z])', condition)
        letters = match.groups()

        if letters[0] not in dic:
            dic[letters[0]] = []
        if letters[1] not in dic:
            dic[letters[1]] = []
        dic[letters[1]].append(letters[0])

    return dic

def work(inWork, result):
    for entry in inWork.copy():
        inWork[entry] -= 1
        if inWork[entry] == 0:
            result.append(entry)
            inWork.pop(entry)

    return inWork

def doOne():

    dic = prepareData()
    ready = []
    result = []

    while (len(dic) > 0):
        for key in dic.copy():
            isReady = True
            conditions = dic[key]

            for condition in conditions:
                if condition not in result:
                    isReady = False
                    break
            
            if isReady:
                ready.append(key)
                dic.pop(key)

        ready.sort()
        ready.reverse()
        result.append(ready.pop())


    return result

def doTwo():
    dic = prepareData()

    matching = {}
    count = 61
    for x in string.ascii_uppercase:
        matching[x] = count
        count += 1

    result = []
    ready = []
    inWork = {}
    time = 0

    while (True):
        time += 1
        for key in dic.copy():
            isReady = True
            conditions = dic[key]

            for condition in conditions:
                if condition not in result:
                    isReady = False
                    break
            
            if isReady:
                ready.append(key)
                dic.pop(key)

        ready.sort()
        ready.reverse()
        while len(inWork) < 5 and len(ready) > 0:
                letter = ready.pop()
                inWork[letter] = matching[letter]
            
        inWork = work(inWork, result)

        if len(inWork) == 0 and len(dic) == 0:
            return time



result = doTwo()
print(result)<file_sep>/2020/day17.py
from HelperFunctions import inputsplit
from copy import deepcopy

def do1(puzzleInput):
    space = prepareInput(puzzleInput, 3)

    newSpace = changeState(space, 3)

    return countActiveCubes(newSpace, 3)

def do2(puzzleInput):
    space = prepareInput(puzzleInput, 4)

    newSpace = changeState(space, 4)

    return countActiveCubes(newSpace, 4)

def changeState(space, dimension):
    newSpace = deepcopy(space)

    for _ in range(6):
        space = deepcopy(newSpace)
        for x in range(1, len(space) - 1):
            for y in range(1, len(space[x]) - 1):
                for z in range(1, len(space[x][y]) - 1):
                    if dimension == 4:
                        for w in range(1, len(space[x][y][z]) - 1):
                            activeNeighbors = numberOfActiveNeighbors((x,y,z,w), space, dimension)
                            if space[x][y][z][w] == '#' and not (2 <= activeNeighbors <= 3):
                                newSpace[x][y][z][w] = '.'
                            elif space[x][y][z][w] == '.' and activeNeighbors == 3:
                                newSpace[x][y][z][w] = '#'
                    else:
                        activeNeighbors = numberOfActiveNeighbors((x,y,z), space, dimension)
                        if space[x][y][z] == '#' and not (2 <= activeNeighbors <= 3):
                            newSpace[x][y][z] = '.'
                        elif space[x][y][z] == '.' and activeNeighbors == 3:
                            newSpace[x][y][z] = '#'
        
    return newSpace

def numberOfActiveNeighbors(position, space, dimension):
    if dimension == 3:
        x,y,z = position
    else:
        x,y,z,w = position
    numberOfActiveNeighbors = 0
    step = [-1, 0, 1]
    for xStep in step:
        for yStep in step:
            for zStep in step:
                if dimension == 4:
                    for wStep in step:
                        if xStep == 0 and yStep == 0 and zStep == 0 and wStep == 0:
                            continue
                        if space[x + xStep][y + yStep][z + zStep][w + wStep] == '#':
                            numberOfActiveNeighbors += 1    
                else:
                    if xStep == 0 and yStep == 0 and zStep == 0:
                        continue
                    if space[x + xStep][y + yStep][z + zStep] == '#':
                        numberOfActiveNeighbors += 1
        
    return numberOfActiveNeighbors

def prepareInput(puzzleInput, dimension):
    size = 31
    if dimension == 3:
        space = [[['.' for z in range(size)] for y in range(size)] for x in range(size)]
    elif dimension == 4:
        space = [[[['.' for w in range(size)] for z in range(size)] for y in range(size)] for x in range(size)]
        w = int(size / 2)

    z = int(size / 2)
    x = int(size / 2 - int(len(puzzleInput) / 2))
    

    for a in range(len(puzzleInput)):
        y = int(size / 2 - int(len(puzzleInput[0]) / 2))
        for b in range(len(puzzleInput[0])):
            if dimension == 4:
                space[x][y][z][w] = puzzleInput[a][b]
            elif dimension == 3:   
                space[x][y][z] = puzzleInput[a][b]
            y += 1
        x += 1

    return space

def countActiveCubes(space, dimension):
    count = 0
    for x in range(len(space)):
        for y in range(len(space[x])):
            if dimension == 4:
                for z in range(len(space[x][y])):
                    count += space[x][y][z].count('#')
            elif dimension == 3:
                count += space[x][y].count('#')

    return count

def do():
    with open ('Input/day17.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2022/day21.py
from collections import namedtuple
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

NumberMonkey = namedtuple('NumberMonkey', ['name', 'number'])
OperationMonkey = namedtuple('OperationMonkey', ['name', 'operation', 'first', 'second'])

def add(first,second):
	return first + second
def substract(first,second):
	return first - second
def multiply(first,second):
	return first * second
def divide(first,second):
	return first / second

operations = {'+': add, '-': substract, '*': multiply, '/': divide}

def do1(splitInput):
	monkeys = extractMonkeyInformation(splitInput)
		
	return getNumber('root', monkeys)

def do2(splitInput):
	monkeys = extractMonkeyInformation(splitInput)

	i1,i2 = [0, 1000000000000]

	monkeys['humn'] = NumberMonkey('humn', i1)
	first1 = getNumber(monkeys['root'].first, monkeys)

	monkeys['humn'] = NumberMonkey('humn', i2)
	first2 = getNumber(monkeys['root'].first, monkeys)

	second = getNumber(monkeys['root'].second, monkeys)

	firstDiff = first1-first2
	secondDiff = abs(second - first2)

	missingDiff = secondDiff / firstDiff
	return int(missingDiff * i2 + i2 + 1)

def extractMonkeyInformation(splitInput):
	monkeys = {}
	for line in splitInput:
		match line.split(' '):
			case [monkey, number]:
				monkey = monkey[0:-1]
				number = int(number)
				monkeys[monkey] = NumberMonkey(monkey, number)
			case [monkey, first, operation, second]:
				monkey = monkey[0:-1]
				monkeys[monkey] = OperationMonkey(monkey,operations[operation],first,second)
	return monkeys	

def getNumber(monkeyName, monkeys):
	monkey = monkeys[monkeyName]
	if type(monkey) is NumberMonkey:
		return monkey.number
	
	return monkey.operation(getNumber(monkey.first, monkeys), getNumber(monkey.second, monkeys))

def do():
	strInput = readInputFile(21)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2022/day3.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	prioritySum = 0
	for rucksack in splitInput:
		firstCompartment = rucksack[0:int(len(rucksack)/2)]
		secondCompartment = rucksack[int(len(rucksack)/2):]

		sameType = [x for x in firstCompartment if x in secondCompartment][0]
		prioritySum += calculatePriorityValue(sameType)
	return prioritySum

def do2(splitInput):
	prioritySum = 0

	groups = [splitInput[i:i+3] for i in range(0, len(splitInput), 3)]
	for elf1,elf2,elf3 in groups:
		sameType = [x for x in elf1 if x in elf2 and x in elf3][0]
		prioritySum += calculatePriorityValue(sameType)
	return prioritySum

def calculatePriorityValue(item):
	if item.islower():
		return ord(item) - ord('a') + 1
	elif item.isupper():
		return ord(item) - ord('A') + 27

def do():
	strInput = readInputFile(3)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2019/day4.py
rangeLow = 134792
rangeHigh = 675810

def do1():

    result = []

    for i in range(rangeLow, rangeHigh + 1):
        if hasDouble(i) and doesNotDecrease(i):
            result.append(i) 

    return result

def do2():

    result = []

    for i in range(rangeLow, rangeHigh + 1):
        if hasOnlyOneDouble(i) and doesNotDecrease(i):
            result.append(i) 

    return result

def hasOnlyOneDouble(i):
    numbers = [int(x) for x in str(i)]

    dic = {}

    for number in numbers:
        dic[number] = dic.get(number, 0) + 1

    if 2 in dic.values():
        return True
    
    return False

def hasDouble(i):
    numbers = [int(x) for x in str(i)]
    
    for j in range(len(numbers) - 1):
        if numbers[j] == numbers[j + 1]:
            return True

    return False

def doesNotDecrease(i):
    numbers = [int(x) for x in str(i)]

    for j in range(len(numbers) - 1):
        if numbers[j+1] < numbers[j]:
            return False
    return True

#part1
print(len(do1()))

#part2
print(len(do2()))<file_sep>/2021/day11.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(splitInput):
	octopuses = prepareInput(splitInput)
	steps = 100
	sumOfFlashes = 0
	for _ in range(steps):
		octopuses,flashes = flashOctopuses(octopuses)
		sumOfFlashes += flashes

	return sumOfFlashes

def do2(splitInput):
	octopuses = prepareInput(splitInput)
	steps = 0
	flashes = 0
	while flashes < len(splitInput) * len(splitInput[0]):
		steps += 1
		octopuses,flashes = flashOctopuses(octopuses)

	return steps

def flashOctopuses(octopuses):
	#increase energy level
	energyOctopuses = []
	for x in range(len(octopuses)):
		energyOctopuses.append([y + 1 if y != -1 else -1 for y in octopuses[x] ])
	
	flashes = 0
	newFlashes = 1
	flashed = []
	while newFlashes != 0:
		newFlashes = 0
		for lineNumber,line in enumerate(energyOctopuses):
			for position,octopus in enumerate(line):
				if octopus == -1:
					continue
				elif octopus > 9:
					flash(lineNumber, position, energyOctopuses, flashed)
					newFlashes += 1
		flashes += newFlashes

	return energyOctopuses,flashes

def flash(line, position, octopuses, flashed):
	if octopuses[line][position] < 10:
		print('Why are we here?')
		return
	
	octopuses[line][position] = 0
	flashed.append((line, position))

	for lineDiff in [-1, 0, 1]:
		for positionDiff in [-1, 0, 1]:
			if lineDiff == 0 and positionDiff == 0:
				continue
			if octopuses[line + lineDiff][position + positionDiff] != -1 and (line + lineDiff, position + positionDiff) not in flashed:
				octopuses[line + lineDiff][position + positionDiff] += 1

def prepareInput(splitInput):
	octopuses = []

	octopuses.append([-1] + [-1 for _ in range(len(splitInput[0]))] + [-1])

	for line in splitInput:
		octoLine = [-1] + convertToInt(line) + [-1]
		octopuses.append(octoLine)

	octopuses.append([-1 for _ in range(len(octopuses[0]))])
	
	return octopuses

def do():
	strInput = readInputFile(11)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2022/day25.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

add = {'=':'-', '-':'0','0':'1','1':'2','2':'3'}
divide = {3:'=', 4:'-'}

def do1(splitInput):
	sumOfNumbers = 0

	for number in splitInput:
		sumOfNumbers += convertToDecimal(number)

	return convertToSnafu(sumOfNumbers)

def do2(splitInput):
	return 'nothing to do'

def convertToDecimal(number):
	decimal = 0
	number = number[::-1]
	for i in range(0,len(number)):
		match number[i]:
			case '=':
				decimal -= 2*pow(5,i)
			case '-':
				decimal -= pow(5,i)
			case num:
				decimal += pow(5,i) * int(num)
	return decimal

def convertToSnafu(number):
	i = 0
	while True:
		if number < pow(5,i):
			i = i-1
			break
		i += 1

	result = ''
	remaining = number
	while remaining:
		divided = int(remaining / (pow(5,i)))
		if divided > 2:
			if result:
				result = result[0:-1] + add[result[-1]] + divide[divided]
				result = updateResult(result)
			else:
				result = '1' + divide[divided]
		else:
			result = result + str(divided)
		remaining = remaining % (pow(5,i)) 
		i -= 1
	
	for _ in range(i,-1,-1):
		result += '0'

	return result

def updateResult(result):
	if '3' in result:
		position = result.index('3')
		if position == 0:
			return '1=' + result[1:]
		else:
			result = result[0:position-1] + add[result[position-1]] + '=' + result[position+1:]
			result = updateResult(result)
	return result 


def do():
	strInput = readInputFile(25)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2020/day14.py
from HelperFunctions import inputsplit
import re

def do1(puzzleInput):

    memory = fillMemory(puzzleInput, updateValue)
    
    return sum([x for x in memory.values()])

def do2(puzzleInput):
    
    memory = fillMemory(puzzleInput, updateMemoryValue)
    
    return sum([x for x in memory.values()])

def fillMemory(puzzleInput, updateFunction):
    memory = {}

    bitmask = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
    for line in puzzleInput:
        match = re.match('mask = (.+)', line)
        if match:
            bitmask = match.groups()[0]
        else:
            match = re.match('mem\[([0-9]+)\] = ([0-9]+)', line)
            if match:
                position = int(match.groups()[0])
                value = int(match.groups()[1])
                updateFunction(bitmask, position, value, memory)
            else:
                print('could not match')
    return memory

def updateMemoryValue(bitmask, position, value, memory):
    memoryPositions = []
    
    positionBinary = format(position, '036b')
    memoryPositions.append(positionBinary)

    for bit in range(len(bitmask)):
        if bitmask[bit] == '1':
            for position in range(len(memoryPositions)):
                memoryPositions[position] = memoryPositions[position][0:bit] + '1' + memoryPositions[position][bit+1:]
        elif bitmask[bit] == 'X':
            for position in range(len(memoryPositions)):
                memoryPositions[position] = memoryPositions[position][0:bit] + '0' + memoryPositions[position][bit+1:]
                memoryPosition2 = memoryPositions[position][0:bit] + '1' + memoryPositions[position][bit+1:]
                memoryPositions.append(memoryPosition2)

    for memoryPosition in memoryPositions:
        intMemoryPosition = int(memoryPosition, 2)
        memory[intMemoryPosition] = value

def updateValue(bitmask, position, value, memory):
    valueBinary = format(value, '036b')

    for bit in range(len(bitmask)):
        if bitmask[bit] == '1':
            valueBinary = valueBinary[0:bit] + '1' + valueBinary[bit+1:]
        elif bitmask[bit] == '0':
            valueBinary = valueBinary[0:bit] + '0' + valueBinary[bit+1:]
    
    intValue = int(valueBinary, 2)

    memory[position] = intValue        

def do():
    with open ('Input/day14.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2018/day12.py
start = "#.##.##.##.##.......###..####..#....#...#.##...##.#.####...#..##..###...##.#..#.##.#.#.#.#..####..#"

transition = """..### => .
##..# => #
#..## => .
.#..# => .
#.##. => .
#.... => .
##... => #
#...# => .
###.# => #
##.## => .
....# => .
..##. => #
..#.. => .
##.#. => .
.##.# => #
#..#. => #
.##.. => #
###.. => #
.###. => #
##### => #
####. => .
.#.#. => .
...#. => #
#.### => .
.#... => #
.#### => .
#.#.# => #
...## => .
..... => .
.#.## => #
..#.# => #
#.#.. => #"""

addition = 600

import re

def prepareTransitions():
    dic = {}

    splitTransitions = transition.split('\n')

    for entry in splitTransitions:
        match = re.match('(.*) => (.)', entry)
        pattern, result = match.groups()
        dic[pattern] = result

    return dic

def calculateSum(result):
    totalSum = 0
    for i in range(len(result)):
        if result[i] == '#':
            totalSum += i - addition

    return totalSum

def do():
    dic = prepareTransitions()
    
    points = ''
    for i in range(addition):
        points += '.'

    input = points + start + points
    for i in range(20):
        result = '..'
        for index in range(2, len(input) - 2):
            sub = input[index - 2: index + 3]

            result += dic[sub]
        input = result + '..'

        sum = calculateSum(result)


    return sum

print(do())


print(6900 * (50000000000 / 100 - 2) + 16068)<file_sep>/2020/day25.py
from HelperFunctions import inputsplit

def do1(puzzleInput):
    cardPublic = int(puzzleInput[0])
    doorPublic = int(puzzleInput[1])

    loopSizeCard = getLoopSize(cardPublic, 7)
    
    return calculateEncryptionKey(loopSizeCard, doorPublic)

def do2(puzzleInput):
    return 'done'

def getLoopSize(publicKey, subjectNumber):
    value = 1
    loop = 0
    while value != publicKey:
        loop += 1
        value = value * subjectNumber
        value = value % 20201227

    return loop

def calculateEncryptionKey(loopSize, subjectNumber):
    value = 1
    for _ in range(loopSize):
        value = value * subjectNumber
        value = value % 20201227
    
    return value

def do():
    with open ('Input/day25.txt') as f:
        strInput = f.read()

    puzzleInput = strInput.split('\n')

    print(do1(puzzleInput))
    print(do2(puzzleInput))
    
do()<file_sep>/2021/HelperFunctions.py

def readInputFile(day):
    with open (f'Input/day{day}.txt') as f:
        strInput = f.read()
    return strInput

def readExampleInput(day):
    with open(f'Input/day{day}_example.txt') as f:
        strInput = f.read()
    return strInput

def convertToInt(input):
    numbers = []
    for stringNumber in input:
        numbers.append(int(stringNumber))

    return numbers<file_sep>/2020/day4.py
from HelperFunctions import inputsplit
import re

def do1(puzzleInput):
        
    passportKeys = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid']

    passportData = extractPassportData(puzzleInput)

    numberOfValidPassports = 0
    for passport in passportData:
        if all (x in passport.keys() for x in passportKeys):
            numberOfValidPassports += 1

    return numberOfValidPassports

def do2(puzzleInput):
    
    passportData = extractPassportData(puzzleInput)

    passportKeys = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid']
    numberOfValidPassports = 0

    for passport in passportData:
        if all (x in passport.keys() for x in passportKeys):
            if (checkBirthYear(passport) and checkIssueYear(passport) and checkExpirationYear(passport) and checkHeight(passport) and checkHairColor(passport) and checkPassportID(passport) and checkEyeColor(passport)):
                numberOfValidPassports += 1

    return numberOfValidPassports

def checkBirthYear(passport):
    if passport['byr'].isnumeric and 1920 <= int(passport['byr']) <= 2002:
        return True  

    return False

def checkIssueYear(passport):
    if passport['iyr'].isnumeric and 2010 <= int(passport['iyr']) <= 2020:
        return True  

    return False

def checkExpirationYear(passport):
    if passport['eyr'].isnumeric and 2020 <= int(passport['eyr']) <= 2030:
        return True  

    return False

def checkHeight(passport):
    match = re.fullmatch('([0-9]+)(\D+)', passport['hgt'])
    if match and match.groups()[1] == 'cm' and 150 <= int(match.groups()[0]) <= 193:
        return True
    if match and match.groups()[1] == 'in' and 59 <= int(match.groups()[0]) <= 76:
        return True
    
    return False

def checkHairColor(passport):
    match = re.fullmatch('\#[0-9|a-f]{6}', passport['hcl'])
    return match

def checkPassportID(passport):
    match = re.fullmatch('[0-9]{9}', passport['pid'])
    return match

def checkEyeColor(passport):
    validEyeColors = ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']

    return passport['ecl'] in validEyeColors

def extractPassportData(puzzleInput):

    resultList = []

    for passportData in puzzleInput:
        passport = {}
        match = re.findall('([a-z]+):([\#a-zA-Z0-9]+)[\s]?', passportData)

        for entries in match:
            passport[entries[0]] = entries[1]

        resultList.append(passport)

    return resultList

def do():
    with open ('Input/day4.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2021/day7.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(crabs):
	fuelSum = 0
	minFuelSum = 10000000

	for i in range(min(crabs), max(crabs) + 1):
		fuelSum = 0
		for crab in crabs:
			fuel = abs(i - crab)
			fuelSum += fuel
		minFuelSum = min(minFuelSum, fuelSum)
	
	return minFuelSum

def do2(crabs):
	maxCrabs = max(crabs) + 1
	crabRange = range(min(crabs), maxCrabs)
	steps = [i for i in range(1, maxCrabs)]
	fuelNeeded = [sum(steps[0:i]) for i in range(1, maxCrabs)]
	minFuelSum = 10000000000

	for i in crabRange:
		fuelSum = 0
		for crab in crabs:
			stepsNeeded = abs(i - crab)
			fuel = fuelNeeded[stepsNeeded - 1]
			fuelSum += fuel
		minFuelSum = min(minFuelSum, fuelSum)
	
	return minFuelSum
	
def do():
	strInput = readInputFile(7)

	splitInput = strInput.split(',')
	intInput = convertToInt(splitInput)

	print(do1(intInput))
	print(do2(intInput))

	print('done')


do()<file_sep>/2018/day5.py

original="""<KEY>"""

def do(input):
    characters = 'abcdefghijklmnopqrstuvwxyz'
    dic = {}
    for character in characters:
        input = original 
    
        changed = True
        input = input.replace(character, '')
        input = input.replace(character.upper(), '')
        while(changed):
            changed = False
            i = 0
            while(i < len(input) - 2):

                chr1 = input[i]
                chr2 = input[i + 1]

                if chr1.islower() and chr2.isupper():
                    if chr1.upper() == chr2:
                        input = input[:i] + input[i+2:]
                        changed = True
                        if i > 0:
                            i -= 1

                elif chr1.isupper() and chr2.islower():
                    if chr1.lower() == chr2:
                        input = input[:i] + input[i+2:]
                        changed = True
                        if i > 0:
                            i -= 1
                i += 1

        dic[character] = len(input)

    return dic


result = do(input)
print(min(result.values()))
<file_sep>/2021/day5.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re
from collections import defaultdict

def do1(splitInput):
	points = defaultdict(lambda: 0)

	parsedLines = parseLines(splitInput)
	
	for line in parsedLines:
		x1,x2,y1,y2 = line
		addPoints(x1, x2, y1, y2, points, False)

	multiples = findMultiples(points)
	return len(multiples)

def do2(splitInput):
	points = defaultdict(lambda: 0)

	parsedLines = parseLines(splitInput)
	
	for line in parsedLines:
		x1,x2,y1,y2 = line
		addPoints(x1, x2, y1, y2, points, True)

	multiples = findMultiples(points)
	return len(multiples)

def parseLines(splitInput):
	parsedLines = []
	for line in splitInput:
		match = re.fullmatch('(?P<x1>[0-9]+),(?P<y1>[0-9]+) -> (?P<x2>[0-9]+),(?P<y2>[0-9]+)', line)
		if match:
			x1 = int(match.group('x1'))
			x2 = int(match.group('x2'))
			y1 = int(match.group('y1'))
			y2 = int(match.group('y2'))

			parsedLines.append((x1,x2,y1,y2))
	
	return parsedLines

def addPoints(x1,x2,y1,y2, points, diagonalsAllowed):
	x = sorted([x1,x2])
	y = sorted([y1,y2])
	
	if x1 == x2:
		for i in range(y[0], y[1] + 1):
			points[(x1, i)] += 1
	elif y1 == y2:
		for i in range(x[0], x[1] + 1):
			points[(i, y1)] += 1
	else:
		if not diagonalsAllowed:
			return
		else:
			factorX = 1
			factorY = 1
			if x1 > x2:
				factorX = -1
			if y1 > y2:
				factorY = -1

			for i in range(x[1] - x[0] + 1):
				points[(x1 + factorX * i, y1 + factorY * i)] += 1

def findMultiples(points):
	multiples = [x for x in points.keys() if points[x] > 1]

	return multiples

def do():
	strInput = readInputFile(5)

	splitInput = strInput.split('\n')

	print(do1(splitInput))
	print(do2(splitInput))

	print('done')


do()<file_sep>/2018/day4.py
input = """[1518-03-25 00:01] Guard #743 begins shift
[1518-09-15 00:34] falls asleep
[1518-10-11 00:27] wakes up
[1518-04-30 00:56] falls asleep
[1518-05-27 00:33] falls asleep
[1518-11-07 00:52] wakes up
[1518-09-04 00:47] wakes up
[1518-05-29 00:44] wakes up
[1518-06-10 00:41] falls asleep
[1518-09-03 00:21] wakes up
[1518-06-16 00:59] wakes up
[1518-03-04 00:52] wakes up
[1518-07-13 00:58] wakes up
[1518-07-31 00:05] falls asleep
[1518-10-15 00:55] falls asleep
[1518-06-15 23:46] Guard #2113 begins shift
[1518-08-07 00:00] Guard #1439 begins shift
[1518-10-28 00:27] falls asleep
[1518-08-17 00:53] wakes up
[1518-05-20 00:07] falls asleep
[1518-06-23 00:30] falls asleep
[1518-09-08 00:43] wakes up
[1518-08-30 00:00] Guard #463 begins shift
[1518-05-27 00:18] falls asleep
[1518-10-26 00:06] falls asleep
[1518-11-16 00:54] wakes up
[1518-04-15 00:17] wakes up
[1518-04-10 23:53] Guard #463 begins shift
[1518-11-23 00:46] wakes up
[1518-03-19 00:57] wakes up
[1518-08-19 00:48] falls asleep
[1518-03-05 00:44] wakes up
[1518-06-30 00:03] falls asleep
[1518-05-19 00:49] wakes up
[1518-10-30 00:31] falls asleep
[1518-02-25 00:28] wakes up
[1518-04-05 00:48] falls asleep
[1518-04-06 23:56] Guard #151 begins shift
[1518-09-24 00:27] falls asleep
[1518-10-12 00:19] falls asleep
[1518-07-22 00:08] wakes up
[1518-08-28 00:03] Guard #3041 begins shift
[1518-08-09 00:03] falls asleep
[1518-04-25 00:11] falls asleep
[1518-05-21 23:57] Guard #907 begins shift
[1518-11-04 00:04] falls asleep
[1518-08-08 23:48] Guard #151 begins shift
[1518-10-06 00:27] falls asleep
[1518-10-31 00:48] wakes up
[1518-09-08 00:53] falls asleep
[1518-10-25 00:02] Guard #643 begins shift
[1518-06-12 00:58] wakes up
[1518-03-26 23:57] Guard #1439 begins shift
[1518-06-07 00:16] falls asleep
[1518-08-18 00:34] wakes up
[1518-06-06 00:50] wakes up
[1518-10-16 00:04] falls asleep
[1518-03-26 00:01] wakes up
[1518-08-20 00:51] falls asleep
[1518-10-15 00:24] falls asleep
[1518-08-30 00:54] wakes up
[1518-09-23 23:56] Guard #251 begins shift
[1518-05-06 00:00] Guard #487 begins shift
[1518-08-06 00:22] wakes up
[1518-06-17 00:58] wakes up
[1518-03-12 00:41] wakes up
[1518-10-10 23:47] Guard #643 begins shift
[1518-06-24 00:19] falls asleep
[1518-06-24 00:39] falls asleep
[1518-08-07 00:45] wakes up
[1518-06-26 00:15] falls asleep
[1518-06-18 00:40] falls asleep
[1518-11-16 23:57] Guard #3323 begins shift
[1518-11-10 00:22] wakes up
[1518-10-27 00:01] Guard #1297 begins shift
[1518-04-01 00:43] falls asleep
[1518-08-05 23:59] Guard #251 begins shift
[1518-07-10 00:26] falls asleep
[1518-09-26 00:45] falls asleep
[1518-10-30 00:44] wakes up
[1518-10-20 00:01] Guard #3209 begins shift
[1518-04-21 00:54] wakes up
[1518-05-28 23:50] Guard #1297 begins shift
[1518-08-11 00:48] wakes up
[1518-06-16 00:29] wakes up
[1518-05-14 00:37] falls asleep
[1518-03-12 23:57] Guard #463 begins shift
[1518-04-24 00:45] wakes up
[1518-07-17 00:34] falls asleep
[1518-06-01 00:52] falls asleep
[1518-08-26 00:01] Guard #1297 begins shift
[1518-10-10 00:50] falls asleep
[1518-09-15 00:29] wakes up
[1518-07-23 23:58] Guard #463 begins shift
[1518-11-21 00:02] Guard #3041 begins shift
[1518-07-02 00:44] falls asleep
[1518-09-13 00:31] falls asleep
[1518-07-12 00:50] wakes up
[1518-04-09 00:53] wakes up
[1518-11-12 00:08] wakes up
[1518-04-11 00:00] falls asleep
[1518-03-17 00:46] wakes up
[1518-10-09 23:57] Guard #1439 begins shift
[1518-05-25 23:58] Guard #151 begins shift
[1518-04-23 00:03] Guard #263 begins shift
[1518-05-13 00:00] Guard #1297 begins shift
[1518-05-01 00:31] wakes up
[1518-04-02 00:27] wakes up
[1518-11-13 00:47] wakes up
[1518-02-28 23:56] Guard #3323 begins shift
[1518-08-16 00:45] wakes up
[1518-07-11 00:54] wakes up
[1518-07-26 00:17] wakes up
[1518-09-30 00:52] falls asleep
[1518-05-13 23:57] Guard #151 begins shift
[1518-05-05 00:52] wakes up
[1518-07-01 00:29] falls asleep
[1518-09-08 00:17] falls asleep
[1518-04-28 23:56] Guard #487 begins shift
[1518-04-25 00:03] Guard #263 begins shift
[1518-06-06 00:03] Guard #1439 begins shift
[1518-06-25 00:33] wakes up
[1518-07-05 00:32] wakes up
[1518-05-12 00:00] falls asleep
[1518-08-13 23:47] Guard #487 begins shift
[1518-08-22 00:29] falls asleep
[1518-03-23 23:57] Guard #1439 begins shift
[1518-08-09 23:48] Guard #3517 begins shift
[1518-08-31 00:40] wakes up
[1518-11-14 00:03] Guard #487 begins shift
[1518-05-12 00:33] wakes up
[1518-11-19 00:00] Guard #1019 begins shift
[1518-05-04 00:59] wakes up
[1518-06-12 00:47] falls asleep
[1518-03-23 00:00] Guard #263 begins shift
[1518-11-04 00:23] falls asleep
[1518-06-13 00:01] falls asleep
[1518-07-15 00:04] Guard #971 begins shift
[1518-07-19 00:25] falls asleep
[1518-04-26 00:48] falls asleep
[1518-06-30 00:29] wakes up
[1518-08-21 00:52] wakes up
[1518-09-09 23:59] Guard #3517 begins shift
[1518-03-22 00:00] Guard #3323 begins shift
[1518-08-27 00:04] Guard #251 begins shift
[1518-09-04 00:52] falls asleep
[1518-08-27 00:09] falls asleep
[1518-07-27 00:00] Guard #1439 begins shift
[1518-09-20 00:55] wakes up
[1518-09-14 00:37] wakes up
[1518-03-07 23:57] Guard #1439 begins shift
[1518-04-10 00:27] falls asleep
[1518-07-02 00:59] wakes up
[1518-04-21 00:51] falls asleep
[1518-04-12 00:23] falls asleep
[1518-08-17 00:06] falls asleep
[1518-02-22 00:48] wakes up
[1518-10-01 00:50] wakes up
[1518-02-21 00:00] Guard #1439 begins shift
[1518-10-30 00:03] Guard #509 begins shift
[1518-08-08 00:21] falls asleep
[1518-10-24 00:01] Guard #1297 begins shift
[1518-04-21 00:04] falls asleep
[1518-05-10 00:39] wakes up
[1518-05-10 00:00] Guard #3323 begins shift
[1518-03-10 00:50] wakes up
[1518-07-22 00:06] falls asleep
[1518-07-10 00:54] wakes up
[1518-11-06 00:22] falls asleep
[1518-04-05 00:54] wakes up
[1518-05-14 00:52] falls asleep
[1518-09-13 00:46] wakes up
[1518-07-15 23:59] Guard #151 begins shift
[1518-06-01 00:41] falls asleep
[1518-04-24 00:38] falls asleep
[1518-07-20 00:57] wakes up
[1518-03-30 00:59] wakes up
[1518-08-04 00:20] wakes up
[1518-09-26 00:10] falls asleep
[1518-03-30 00:02] Guard #3469 begins shift
[1518-07-09 00:52] wakes up
[1518-04-23 00:21] falls asleep
[1518-05-01 00:44] wakes up
[1518-04-04 23:58] Guard #3323 begins shift
[1518-08-07 00:25] falls asleep
[1518-06-09 23:58] Guard #3209 begins shift
[1518-07-09 00:48] falls asleep
[1518-08-11 00:47] falls asleep
[1518-03-09 00:07] falls asleep
[1518-06-29 00:41] wakes up
[1518-05-27 23:58] Guard #743 begins shift
[1518-05-19 00:43] falls asleep
[1518-03-17 00:33] falls asleep
[1518-07-12 00:49] falls asleep
[1518-11-03 00:15] wakes up
[1518-06-05 00:57] wakes up
[1518-11-07 00:24] falls asleep
[1518-07-06 00:12] falls asleep
[1518-05-26 23:59] Guard #907 begins shift
[1518-06-01 00:28] wakes up
[1518-11-09 00:04] falls asleep
[1518-06-27 00:49] wakes up
[1518-03-29 00:42] wakes up
[1518-05-21 00:47] falls asleep
[1518-08-04 00:47] wakes up
[1518-07-18 00:23] wakes up
[1518-09-07 23:56] Guard #463 begins shift
[1518-09-10 23:51] Guard #1019 begins shift
[1518-09-29 00:49] wakes up
[1518-06-15 00:57] wakes up
[1518-04-04 00:31] falls asleep
[1518-08-31 00:49] wakes up
[1518-10-23 00:59] wakes up
[1518-05-21 00:02] falls asleep
[1518-07-02 00:36] falls asleep
[1518-06-29 23:51] Guard #3517 begins shift
[1518-07-25 00:47] wakes up
[1518-11-15 00:39] wakes up
[1518-11-13 00:57] falls asleep
[1518-09-26 23:59] Guard #463 begins shift
[1518-03-10 00:22] wakes up
[1518-08-10 00:56] wakes up
[1518-07-28 00:31] falls asleep
[1518-10-12 00:43] wakes up
[1518-05-27 00:44] wakes up
[1518-07-28 00:32] wakes up
[1518-04-27 00:54] wakes up
[1518-08-12 00:39] falls asleep
[1518-04-03 00:38] wakes up
[1518-04-03 00:11] falls asleep
[1518-08-24 00:57] wakes up
[1518-05-15 00:52] wakes up
[1518-10-22 00:56] wakes up
[1518-04-24 00:00] Guard #509 begins shift
[1518-03-26 00:00] falls asleep
[1518-09-30 23:58] Guard #1297 begins shift
[1518-07-16 00:53] wakes up
[1518-05-23 00:15] falls asleep
[1518-11-13 00:59] wakes up
[1518-02-27 00:53] wakes up
[1518-08-19 00:42] wakes up
[1518-04-19 00:03] Guard #3209 begins shift
[1518-11-03 00:14] falls asleep
[1518-09-16 00:44] falls asleep
[1518-03-21 00:11] falls asleep
[1518-08-14 00:17] wakes up
[1518-09-04 00:35] falls asleep
[1518-10-14 00:41] wakes up
[1518-06-17 00:36] falls asleep
[1518-08-04 00:16] falls asleep
[1518-06-13 00:52] wakes up
[1518-03-07 00:02] Guard #251 begins shift
[1518-05-10 00:09] falls asleep
[1518-03-14 00:04] Guard #1439 begins shift
[1518-07-24 23:56] Guard #463 begins shift
[1518-11-01 00:25] falls asleep
[1518-06-23 00:44] wakes up
[1518-11-17 00:12] wakes up
[1518-06-13 00:22] falls asleep
[1518-08-01 00:47] falls asleep
[1518-04-17 00:11] falls asleep
[1518-09-12 00:01] falls asleep
[1518-07-05 23:57] Guard #3323 begins shift
[1518-03-16 00:57] falls asleep
[1518-05-26 00:08] falls asleep
[1518-04-09 00:57] falls asleep
[1518-11-14 00:09] falls asleep
[1518-11-10 00:00] Guard #1019 begins shift
[1518-09-08 00:41] falls asleep
[1518-03-30 00:41] falls asleep
[1518-10-22 00:43] wakes up
[1518-06-17 00:56] falls asleep
[1518-08-19 23:56] Guard #907 begins shift
[1518-03-01 00:39] wakes up
[1518-06-16 00:01] falls asleep
[1518-07-07 00:48] wakes up
[1518-07-29 23:50] Guard #907 begins shift
[1518-06-28 00:56] wakes up
[1518-11-22 00:44] wakes up
[1518-09-26 00:54] wakes up
[1518-04-08 00:01] Guard #1307 begins shift
[1518-02-23 00:58] wakes up
[1518-06-02 00:08] falls asleep
[1518-10-17 00:30] wakes up
[1518-11-02 00:56] wakes up
[1518-06-24 00:23] wakes up
[1518-05-03 00:43] wakes up
[1518-05-03 00:25] falls asleep
[1518-03-03 00:30] falls asleep
[1518-10-27 00:33] falls asleep
[1518-10-29 00:30] falls asleep
[1518-11-06 00:51] wakes up
[1518-04-21 00:28] wakes up
[1518-04-23 00:43] wakes up
[1518-09-04 00:00] Guard #1307 begins shift
[1518-06-22 00:45] wakes up
[1518-05-17 00:58] wakes up
[1518-05-05 00:44] wakes up
[1518-07-25 00:22] falls asleep
[1518-11-11 00:11] falls asleep
[1518-04-17 00:03] Guard #947 begins shift
[1518-11-19 00:08] falls asleep
[1518-09-03 00:43] wakes up
[1518-08-26 00:31] falls asleep
[1518-05-05 00:03] falls asleep
[1518-08-19 00:58] wakes up
[1518-02-28 00:11] falls asleep
[1518-08-27 00:48] falls asleep
[1518-09-08 00:56] wakes up
[1518-11-14 00:56] wakes up
[1518-11-12 23:56] Guard #1307 begins shift
[1518-04-01 00:51] falls asleep
[1518-09-11 00:19] falls asleep
[1518-08-15 00:13] falls asleep
[1518-08-03 23:57] Guard #3209 begins shift
[1518-11-11 00:04] Guard #947 begins shift
[1518-10-21 23:54] Guard #1033 begins shift
[1518-04-01 00:03] Guard #251 begins shift
[1518-11-08 23:51] Guard #3323 begins shift
[1518-06-11 23:56] Guard #3469 begins shift
[1518-10-12 23:56] Guard #1307 begins shift
[1518-05-04 00:28] falls asleep
[1518-08-03 00:18] wakes up
[1518-08-14 00:25] falls asleep
[1518-11-13 00:34] falls asleep
[1518-03-18 00:20] falls asleep
[1518-11-03 00:44] falls asleep
[1518-10-03 23:57] Guard #1033 begins shift
[1518-09-03 00:07] falls asleep
[1518-10-11 00:05] falls asleep
[1518-11-17 00:17] falls asleep
[1518-07-16 00:15] falls asleep
[1518-03-22 00:37] falls asleep
[1518-11-05 23:50] Guard #3517 begins shift
[1518-08-05 00:58] wakes up
[1518-11-05 00:55] wakes up
[1518-04-13 00:57] wakes up
[1518-07-23 00:09] falls asleep
[1518-09-12 00:51] wakes up
[1518-09-10 00:58] wakes up
[1518-07-19 00:57] wakes up
[1518-07-11 00:13] falls asleep
[1518-09-21 23:57] Guard #971 begins shift
[1518-04-08 00:43] falls asleep
[1518-08-22 00:39] wakes up
[1518-02-21 00:26] falls asleep
[1518-05-07 00:55] wakes up
[1518-11-16 00:03] Guard #509 begins shift
[1518-10-09 00:03] Guard #1439 begins shift
[1518-05-20 23:51] Guard #743 begins shift
[1518-06-05 00:45] falls asleep
[1518-04-18 00:01] falls asleep
[1518-04-08 00:20] falls asleep
[1518-08-08 00:03] Guard #3517 begins shift
[1518-09-03 00:31] falls asleep
[1518-10-15 00:59] wakes up
[1518-09-14 00:03] Guard #643 begins shift
[1518-08-18 00:21] falls asleep
[1518-09-05 00:43] wakes up
[1518-02-25 00:04] Guard #487 begins shift
[1518-04-04 00:51] wakes up
[1518-03-02 00:23] falls asleep
[1518-11-13 00:52] falls asleep
[1518-04-14 00:00] Guard #743 begins shift
[1518-05-16 00:43] wakes up
[1518-10-14 00:01] Guard #1297 begins shift
[1518-05-21 00:57] falls asleep
[1518-10-02 23:56] Guard #1019 begins shift
[1518-02-24 00:39] wakes up
[1518-11-11 00:56] wakes up
[1518-08-24 00:53] falls asleep
[1518-04-25 23:53] Guard #643 begins shift
[1518-09-09 00:27] wakes up
[1518-05-24 00:00] Guard #1019 begins shift
[1518-03-29 00:40] falls asleep
[1518-07-03 00:58] wakes up
[1518-05-30 00:53] wakes up
[1518-05-01 00:41] falls asleep
[1518-07-02 00:41] wakes up
[1518-09-05 00:02] Guard #1439 begins shift
[1518-06-20 00:29] falls asleep
[1518-09-12 00:34] wakes up
[1518-09-27 00:53] wakes up
[1518-08-10 00:34] falls asleep
[1518-07-04 00:00] Guard #643 begins shift
[1518-02-22 00:03] Guard #3517 begins shift
[1518-06-20 00:45] wakes up
[1518-11-01 23:50] Guard #947 begins shift
[1518-05-09 00:22] wakes up
[1518-04-13 00:56] falls asleep
[1518-08-11 00:16] falls asleep
[1518-07-02 00:57] falls asleep
[1518-07-02 00:45] wakes up
[1518-03-23 00:45] falls asleep
[1518-10-16 00:47] wakes up
[1518-04-26 00:05] falls asleep
[1518-08-14 23:56] Guard #3469 begins shift
[1518-09-16 23:59] Guard #509 begins shift
[1518-08-29 00:09] falls asleep
[1518-11-10 00:58] wakes up
[1518-09-30 00:55] wakes up
[1518-09-15 00:10] falls asleep
[1518-10-06 00:57] wakes up
[1518-04-12 00:43] wakes up
[1518-07-22 00:50] wakes up
[1518-05-29 23:50] Guard #263 begins shift
[1518-06-08 00:58] wakes up
[1518-05-02 00:44] wakes up
[1518-05-23 00:40] wakes up
[1518-04-14 23:58] Guard #3517 begins shift
[1518-11-08 00:57] falls asleep
[1518-09-10 00:51] falls asleep
[1518-09-26 00:03] Guard #151 begins shift
[1518-08-25 00:02] Guard #1307 begins shift
[1518-11-09 00:26] wakes up
[1518-03-25 00:52] wakes up
[1518-03-06 00:56] wakes up
[1518-06-09 00:48] falls asleep
[1518-04-14 00:53] wakes up
[1518-09-16 00:48] wakes up
[1518-09-07 00:53] wakes up
[1518-09-25 00:47] falls asleep
[1518-09-11 23:51] Guard #3323 begins shift
[1518-11-15 00:24] wakes up
[1518-05-02 00:20] falls asleep
[1518-03-23 00:57] wakes up
[1518-06-11 00:08] falls asleep
[1518-03-11 00:03] falls asleep
[1518-04-12 00:56] wakes up
[1518-05-11 00:56] wakes up
[1518-08-21 00:02] Guard #151 begins shift
[1518-03-12 00:04] Guard #509 begins shift
[1518-07-24 00:21] wakes up
[1518-04-03 00:02] Guard #3209 begins shift
[1518-05-24 23:57] Guard #487 begins shift
[1518-04-10 00:04] falls asleep
[1518-04-18 00:48] falls asleep
[1518-05-17 00:00] Guard #1297 begins shift
[1518-07-29 00:14] falls asleep
[1518-07-09 00:04] Guard #2113 begins shift
[1518-11-15 00:01] Guard #1297 begins shift
[1518-03-02 00:55] wakes up
[1518-06-17 00:00] Guard #1307 begins shift
[1518-06-28 00:50] falls asleep
[1518-07-03 00:50] falls asleep
[1518-03-27 00:56] wakes up
[1518-08-23 00:00] falls asleep
[1518-08-27 00:44] wakes up
[1518-03-18 00:57] wakes up
[1518-09-24 00:52] wakes up
[1518-09-27 00:09] falls asleep
[1518-05-26 00:49] wakes up
[1518-10-07 00:33] falls asleep
[1518-08-14 00:00] falls asleep
[1518-07-26 00:08] falls asleep
[1518-07-14 00:15] falls asleep
[1518-09-19 00:53] wakes up
[1518-10-26 00:40] wakes up
[1518-03-26 00:29] falls asleep
[1518-10-28 23:56] Guard #487 begins shift
[1518-09-21 00:58] wakes up
[1518-07-01 00:57] wakes up
[1518-09-04 00:55] wakes up
[1518-02-21 00:27] wakes up
[1518-02-25 00:58] wakes up
[1518-03-28 00:44] falls asleep
[1518-08-24 00:10] wakes up
[1518-09-02 00:57] wakes up
[1518-06-13 00:06] wakes up
[1518-04-16 00:00] Guard #971 begins shift
[1518-09-07 00:17] falls asleep
[1518-11-14 00:44] falls asleep
[1518-06-13 23:58] Guard #3041 begins shift
[1518-03-30 23:59] Guard #643 begins shift
[1518-11-10 00:07] falls asleep
[1518-08-01 00:57] wakes up
[1518-09-06 00:45] wakes up
[1518-07-01 00:41] falls asleep
[1518-04-23 00:57] falls asleep
[1518-10-19 00:15] falls asleep
[1518-07-24 00:11] falls asleep
[1518-09-15 23:59] Guard #487 begins shift
[1518-09-01 00:55] wakes up
[1518-11-20 00:14] falls asleep
[1518-09-12 23:56] Guard #509 begins shift
[1518-03-06 00:19] falls asleep
[1518-07-01 00:02] Guard #463 begins shift
[1518-10-15 00:47] wakes up
[1518-11-18 00:50] wakes up
[1518-09-30 00:15] falls asleep
[1518-06-19 00:39] wakes up
[1518-06-05 00:07] falls asleep
[1518-08-02 00:00] Guard #3517 begins shift
[1518-06-18 23:59] Guard #1297 begins shift
[1518-09-11 00:04] falls asleep
[1518-10-06 00:00] Guard #487 begins shift
[1518-04-09 00:58] wakes up
[1518-05-28 00:07] falls asleep
[1518-05-27 00:30] wakes up
[1518-11-07 00:03] Guard #643 begins shift
[1518-11-09 00:59] wakes up
[1518-08-31 00:35] falls asleep
[1518-04-29 00:09] falls asleep
[1518-03-10 00:37] falls asleep
[1518-09-25 00:54] wakes up
[1518-10-05 00:26] wakes up
[1518-06-27 00:25] falls asleep
[1518-07-08 00:00] Guard #251 begins shift
[1518-08-16 00:00] Guard #1439 begins shift
[1518-11-19 00:48] wakes up
[1518-05-22 00:21] falls asleep
[1518-11-21 23:58] Guard #509 begins shift
[1518-11-22 23:46] Guard #1297 begins shift
[1518-11-08 00:51] wakes up
[1518-04-20 23:50] Guard #1033 begins shift
[1518-03-19 00:54] falls asleep
[1518-08-02 00:39] falls asleep
[1518-08-21 00:18] falls asleep
[1518-05-31 23:57] Guard #509 begins shift
[1518-09-22 23:48] Guard #907 begins shift
[1518-10-20 23:56] Guard #947 begins shift
[1518-08-25 00:28] falls asleep
[1518-05-26 00:20] wakes up
[1518-11-08 00:45] falls asleep
[1518-10-03 00:40] wakes up
[1518-10-21 00:36] falls asleep
[1518-04-27 23:58] Guard #3041 begins shift
[1518-09-28 00:21] falls asleep
[1518-09-17 00:21] falls asleep
[1518-11-20 00:50] wakes up
[1518-05-10 00:28] falls asleep
[1518-08-05 00:32] falls asleep
[1518-10-02 00:00] Guard #263 begins shift
[1518-09-18 00:41] wakes up
[1518-06-05 00:03] Guard #263 begins shift
[1518-02-25 00:10] falls asleep
[1518-10-21 00:53] falls asleep
[1518-10-14 00:06] falls asleep
[1518-03-21 00:58] wakes up
[1518-03-05 00:18] falls asleep
[1518-03-15 00:57] wakes up
[1518-06-06 00:41] falls asleep
[1518-03-16 00:35] wakes up
[1518-10-22 00:54] falls asleep
[1518-07-04 00:25] falls asleep
[1518-09-23 00:27] wakes up
[1518-02-22 00:25] falls asleep
[1518-11-18 00:22] falls asleep
[1518-11-11 23:48] Guard #743 begins shift
[1518-04-04 00:01] Guard #643 begins shift
[1518-08-14 00:46] wakes up
[1518-08-02 00:51] wakes up
[1518-11-16 00:10] falls asleep
[1518-04-13 00:19] falls asleep
[1518-04-11 00:08] wakes up
[1518-06-21 00:08] falls asleep
[1518-11-22 00:55] wakes up
[1518-03-26 00:54] wakes up
[1518-09-18 00:59] wakes up
[1518-03-07 00:15] falls asleep
[1518-08-01 00:55] falls asleep
[1518-11-03 00:02] Guard #1307 begins shift
[1518-05-03 00:00] Guard #251 begins shift
[1518-04-02 00:00] Guard #251 begins shift
[1518-10-21 00:55] wakes up
[1518-06-03 23:47] Guard #1019 begins shift
[1518-05-08 00:23] falls asleep
[1518-02-23 00:42] falls asleep
[1518-06-09 00:59] wakes up
[1518-05-08 23:52] Guard #947 begins shift
[1518-09-18 00:21] falls asleep
[1518-03-15 23:56] Guard #3323 begins shift
[1518-05-25 00:39] falls asleep
[1518-06-30 00:32] falls asleep
[1518-06-08 00:43] wakes up
[1518-07-01 00:49] wakes up
[1518-10-03 00:18] falls asleep
[1518-10-15 00:04] Guard #151 begins shift
[1518-07-18 00:09] falls asleep
[1518-05-04 23:50] Guard #263 begins shift
[1518-09-20 23:56] Guard #3517 begins shift
[1518-07-11 00:01] Guard #643 begins shift
[1518-09-12 00:13] wakes up
[1518-03-22 00:44] wakes up
[1518-10-01 00:31] falls asleep
[1518-03-16 00:44] falls asleep
[1518-04-23 00:29] wakes up
[1518-07-09 00:45] wakes up
[1518-06-30 00:44] wakes up
[1518-10-17 00:56] wakes up
[1518-05-13 00:37] falls asleep
[1518-03-08 23:58] Guard #251 begins shift
[1518-04-02 00:26] falls asleep
[1518-10-20 00:53] wakes up
[1518-03-15 00:00] Guard #3323 begins shift
[1518-09-29 00:47] falls asleep
[1518-09-21 00:41] wakes up
[1518-10-15 23:50] Guard #947 begins shift
[1518-05-01 23:59] Guard #1297 begins shift
[1518-09-17 00:17] wakes up
[1518-07-16 00:16] wakes up
[1518-11-04 00:35] wakes up
[1518-03-31 00:52] wakes up
[1518-03-03 00:43] wakes up
[1518-09-15 00:00] Guard #2113 begins shift
[1518-10-19 00:35] wakes up
[1518-08-21 00:49] falls asleep
[1518-10-27 00:38] wakes up
[1518-04-08 00:48] wakes up
[1518-07-12 23:58] Guard #251 begins shift
[1518-02-25 00:56] falls asleep
[1518-04-01 00:24] falls asleep
[1518-08-29 00:51] wakes up
[1518-04-10 00:13] wakes up
[1518-05-12 00:58] wakes up
[1518-03-01 00:10] falls asleep
[1518-06-05 00:36] wakes up
[1518-11-05 00:34] falls asleep
[1518-09-26 00:36] wakes up
[1518-06-16 00:54] falls asleep
[1518-11-22 00:50] falls asleep
[1518-02-26 23:47] Guard #1439 begins shift
[1518-03-17 00:00] Guard #3517 begins shift
[1518-07-01 00:37] wakes up
[1518-05-11 00:05] falls asleep
[1518-08-10 23:59] Guard #251 begins shift
[1518-06-13 00:30] wakes up
[1518-03-15 00:15] falls asleep
[1518-08-22 00:47] falls asleep
[1518-08-03 00:17] falls asleep
[1518-05-04 00:09] falls asleep
[1518-10-29 00:50] wakes up
[1518-02-24 00:00] Guard #1297 begins shift
[1518-09-29 00:37] falls asleep
[1518-06-11 00:02] Guard #263 begins shift
[1518-05-25 00:46] wakes up
[1518-11-05 00:36] wakes up
[1518-05-15 23:57] Guard #1033 begins shift
[1518-06-08 23:58] Guard #3469 begins shift
[1518-04-06 00:59] wakes up
[1518-06-26 00:39] falls asleep
[1518-05-23 00:03] Guard #947 begins shift
[1518-11-10 00:40] falls asleep
[1518-05-05 00:49] falls asleep
[1518-10-02 00:06] falls asleep
[1518-09-27 23:59] Guard #3517 begins shift
[1518-03-07 00:59] wakes up
[1518-05-17 00:37] falls asleep
[1518-09-30 00:32] falls asleep
[1518-07-29 00:56] wakes up
[1518-10-24 00:53] wakes up
[1518-11-22 00:21] falls asleep
[1518-03-22 00:57] falls asleep
[1518-09-29 23:59] Guard #487 begins shift
[1518-02-28 00:02] Guard #1439 begins shift
[1518-05-20 00:33] wakes up
[1518-09-13 00:57] wakes up
[1518-08-11 00:42] wakes up
[1518-07-14 00:45] wakes up
[1518-06-26 00:55] wakes up
[1518-06-01 00:09] falls asleep
[1518-07-22 00:00] Guard #3517 begins shift
[1518-06-02 23:47] Guard #2113 begins shift
[1518-09-24 23:52] Guard #2113 begins shift
[1518-11-03 00:56] wakes up
[1518-06-22 00:28] falls asleep
[1518-10-28 00:01] Guard #3209 begins shift
[1518-06-21 00:56] wakes up
[1518-06-08 00:36] wakes up
[1518-05-12 00:03] wakes up
[1518-08-09 00:54] wakes up
[1518-07-06 00:54] wakes up
[1518-05-28 00:46] falls asleep
[1518-07-30 00:45] wakes up
[1518-06-06 23:56] Guard #3517 begins shift
[1518-03-12 00:17] falls asleep
[1518-09-19 00:12] falls asleep
[1518-05-13 00:32] wakes up
[1518-05-13 00:15] falls asleep
[1518-10-17 00:35] falls asleep
[1518-08-01 00:05] falls asleep
[1518-10-31 00:00] Guard #3517 begins shift
[1518-03-31 00:42] falls asleep
[1518-05-04 00:46] falls asleep
[1518-08-22 00:00] Guard #3517 begins shift
[1518-11-06 00:12] wakes up
[1518-08-18 23:56] Guard #151 begins shift
[1518-09-02 00:36] falls asleep
[1518-05-22 00:47] wakes up
[1518-07-09 23:50] Guard #3323 begins shift
[1518-06-01 00:45] wakes up
[1518-08-08 00:42] wakes up
[1518-07-04 00:33] wakes up
[1518-08-05 00:01] Guard #1297 begins shift
[1518-03-10 23:48] Guard #1297 begins shift
[1518-10-29 00:06] falls asleep
[1518-11-05 00:47] falls asleep
[1518-05-01 00:03] Guard #907 begins shift
[1518-10-13 00:54] wakes up
[1518-09-29 00:44] wakes up
[1518-10-07 00:46] wakes up
[1518-10-10 00:21] falls asleep
[1518-08-31 00:00] Guard #1297 begins shift
[1518-03-02 00:36] wakes up
[1518-09-17 00:49] wakes up
[1518-07-16 00:46] falls asleep
[1518-06-27 00:02] Guard #907 begins shift
[1518-10-25 23:56] Guard #463 begins shift
[1518-10-08 00:52] wakes up
[1518-06-11 00:14] wakes up
[1518-11-02 00:04] falls asleep
[1518-05-06 00:45] wakes up
[1518-04-01 00:46] wakes up
[1518-09-06 00:59] wakes up
[1518-08-19 00:31] falls asleep
[1518-04-11 00:39] falls asleep
[1518-06-17 00:51] wakes up
[1518-06-08 00:54] falls asleep
[1518-09-11 00:12] wakes up
[1518-07-01 23:57] Guard #1297 begins shift
[1518-04-20 00:19] falls asleep
[1518-11-01 00:49] wakes up
[1518-11-14 00:27] wakes up
[1518-10-24 00:29] wakes up
[1518-10-20 00:20] falls asleep
[1518-05-18 00:00] falls asleep
[1518-04-06 00:01] Guard #151 begins shift
[1518-07-01 00:56] falls asleep
[1518-07-23 00:30] wakes up
[1518-06-20 00:01] Guard #1033 begins shift
[1518-07-04 23:46] Guard #251 begins shift
[1518-04-12 00:00] Guard #487 begins shift
[1518-09-29 00:00] Guard #947 begins shift
[1518-07-08 00:41] wakes up
[1518-05-14 00:53] wakes up
[1518-03-08 00:41] falls asleep
[1518-06-07 00:43] wakes up
[1518-03-13 00:39] falls asleep
[1518-04-05 00:35] wakes up
[1518-04-08 00:27] wakes up
[1518-08-10 00:00] falls asleep
[1518-05-21 00:06] wakes up
[1518-06-03 00:30] wakes up
[1518-08-06 00:48] wakes up
[1518-08-01 00:42] wakes up
[1518-06-22 00:00] Guard #3469 begins shift
[1518-08-27 00:59] wakes up
[1518-07-04 00:58] wakes up
[1518-09-05 00:20] falls asleep
[1518-07-31 00:59] wakes up
[1518-04-14 00:48] falls asleep
[1518-04-22 00:55] wakes up
[1518-05-31 00:00] Guard #907 begins shift
[1518-11-05 00:00] Guard #509 begins shift
[1518-03-09 23:54] Guard #907 begins shift
[1518-11-15 00:37] falls asleep
[1518-08-03 00:04] Guard #509 begins shift
[1518-05-26 00:33] falls asleep
[1518-09-21 00:34] falls asleep
[1518-07-30 00:04] falls asleep
[1518-05-06 00:56] falls asleep
[1518-03-25 00:18] falls asleep
[1518-09-19 00:00] Guard #1439 begins shift
[1518-08-12 23:48] Guard #1439 begins shift
[1518-03-15 00:26] wakes up
[1518-10-10 00:52] wakes up
[1518-07-14 00:02] Guard #1297 begins shift
[1518-04-13 00:51] wakes up
[1518-06-18 00:01] Guard #3469 begins shift
[1518-09-21 00:51] falls asleep
[1518-08-20 00:55] wakes up
[1518-03-19 00:05] falls asleep
[1518-10-14 00:12] wakes up
[1518-06-24 00:41] wakes up
[1518-06-12 00:52] wakes up
[1518-06-03 00:29] falls asleep
[1518-11-07 00:32] wakes up
[1518-10-08 00:34] falls asleep
[1518-03-24 00:18] falls asleep
[1518-06-02 00:29] wakes up
[1518-10-30 00:17] falls asleep
[1518-08-24 00:01] falls asleep
[1518-06-24 23:53] Guard #3323 begins shift
[1518-11-15 00:18] falls asleep
[1518-03-28 00:55] wakes up
[1518-04-30 00:57] wakes up
[1518-10-04 00:50] wakes up
[1518-08-07 00:42] falls asleep
[1518-07-27 00:50] wakes up
[1518-06-12 23:54] Guard #3469 begins shift
[1518-05-06 23:57] Guard #151 begins shift
[1518-05-04 00:32] wakes up
[1518-04-11 00:31] wakes up
[1518-04-25 00:49] wakes up
[1518-09-11 00:30] wakes up
[1518-03-04 00:38] falls asleep
[1518-10-09 00:26] falls asleep
[1518-03-02 23:58] Guard #1019 begins shift
[1518-05-28 00:25] wakes up
[1518-10-22 00:00] falls asleep
[1518-04-07 00:40] wakes up
[1518-05-17 23:52] Guard #3323 begins shift
[1518-09-07 00:00] Guard #509 begins shift
[1518-07-23 00:01] Guard #1297 begins shift
[1518-04-20 00:20] wakes up
[1518-04-22 00:03] Guard #151 begins shift
[1518-05-21 00:54] wakes up
[1518-07-30 00:44] falls asleep
[1518-09-15 00:26] falls asleep
[1518-07-04 00:44] wakes up
[1518-08-15 00:55] wakes up
[1518-11-04 00:07] wakes up
[1518-05-04 00:03] Guard #947 begins shift
[1518-09-05 23:59] Guard #463 begins shift
[1518-04-23 00:36] falls asleep
[1518-11-17 00:52] wakes up
[1518-10-24 00:27] falls asleep
[1518-11-12 00:03] falls asleep
[1518-08-22 23:47] Guard #151 begins shift
[1518-08-13 00:02] falls asleep
[1518-08-23 00:47] wakes up
[1518-04-26 23:58] Guard #1019 begins shift
[1518-05-06 00:08] falls asleep
[1518-10-31 00:07] falls asleep
[1518-05-15 00:02] Guard #1439 begins shift
[1518-07-07 00:21] falls asleep
[1518-07-10 00:02] falls asleep
[1518-05-09 00:00] falls asleep
[1518-11-08 00:59] wakes up
[1518-03-27 00:38] falls asleep
[1518-07-29 00:01] Guard #263 begins shift
[1518-06-08 00:48] falls asleep
[1518-04-09 23:49] Guard #3469 begins shift
[1518-04-24 00:54] wakes up
[1518-02-23 00:01] Guard #463 begins shift
[1518-07-19 00:03] Guard #643 begins shift
[1518-06-12 00:57] falls asleep
[1518-10-10 00:44] wakes up
[1518-07-13 00:16] falls asleep
[1518-10-13 00:48] falls asleep
[1518-04-23 00:58] wakes up
[1518-11-09 00:31] falls asleep
[1518-06-01 00:55] wakes up
[1518-06-26 00:34] wakes up
[1518-09-25 00:37] wakes up
[1518-06-04 00:00] falls asleep
[1518-10-28 00:57] falls asleep
[1518-04-19 00:54] wakes up
[1518-06-08 00:42] falls asleep
[1518-03-28 23:59] Guard #3209 begins shift
[1518-03-10 00:01] falls asleep
[1518-11-20 00:04] Guard #643 begins shift
[1518-10-29 00:24] wakes up
[1518-05-19 23:58] Guard #3209 begins shift
[1518-05-11 23:49] Guard #251 begins shift
[1518-11-01 00:00] Guard #947 begins shift
[1518-05-24 00:07] falls asleep
[1518-09-15 00:19] wakes up
[1518-09-10 00:34] wakes up
[1518-04-01 00:35] wakes up
[1518-07-08 00:27] falls asleep
[1518-05-31 00:08] falls asleep
[1518-06-15 00:04] Guard #1439 begins shift
[1518-08-17 00:00] Guard #1033 begins shift
[1518-07-12 00:00] Guard #907 begins shift
[1518-05-10 00:14] wakes up
[1518-06-08 00:04] Guard #947 begins shift
[1518-07-22 00:29] falls asleep
[1518-04-20 00:03] Guard #463 begins shift
[1518-10-21 00:47] wakes up
[1518-06-25 00:00] falls asleep
[1518-07-10 00:12] wakes up
[1518-05-31 00:47] wakes up
[1518-03-25 23:46] Guard #509 begins shift
[1518-09-18 00:46] falls asleep
[1518-07-30 00:32] wakes up
[1518-09-10 00:27] falls asleep
[1518-08-21 00:44] wakes up
[1518-09-30 00:38] wakes up
[1518-10-25 00:50] falls asleep
[1518-05-24 00:35] wakes up
[1518-03-16 00:19] falls asleep
[1518-03-16 00:54] wakes up
[1518-06-25 23:58] Guard #743 begins shift
[1518-11-13 00:54] wakes up
[1518-06-20 23:57] Guard #2113 begins shift
[1518-06-04 00:51] wakes up
[1518-08-07 00:32] wakes up
[1518-04-10 00:46] wakes up
[1518-05-14 00:47] wakes up
[1518-04-17 23:47] Guard #3323 begins shift
[1518-07-12 00:41] falls asleep
[1518-09-01 23:59] Guard #643 begins shift
[1518-05-21 00:59] wakes up
[1518-09-01 00:03] Guard #151 begins shift
[1518-05-12 00:47] falls asleep
[1518-09-23 00:03] falls asleep
[1518-09-15 00:58] wakes up
[1518-05-07 23:59] Guard #743 begins shift
[1518-04-22 00:48] falls asleep
[1518-09-18 00:01] Guard #1439 begins shift
[1518-05-16 00:39] falls asleep
[1518-06-18 00:51] wakes up
[1518-02-28 00:51] wakes up
[1518-10-02 00:10] wakes up
[1518-04-07 00:15] falls asleep
[1518-09-03 00:03] Guard #947 begins shift
[1518-04-19 00:16] falls asleep
[1518-03-26 00:25] wakes up
[1518-04-13 00:00] Guard #1307 begins shift
[1518-03-26 00:14] falls asleep
[1518-08-22 00:53] wakes up
[1518-06-18 00:27] wakes up
[1518-09-19 23:56] Guard #1033 begins shift
[1518-11-03 23:52] Guard #907 begins shift
[1518-11-07 23:57] Guard #1439 begins shift
[1518-10-04 00:41] falls asleep
[1518-09-12 00:49] falls asleep
[1518-04-24 00:34] wakes up
[1518-07-30 23:47] Guard #463 begins shift
[1518-05-10 23:53] Guard #487 begins shift
[1518-06-02 00:04] Guard #251 begins shift
[1518-05-08 00:36] wakes up
[1518-05-07 00:29] falls asleep
[1518-10-22 23:59] Guard #3469 begins shift
[1518-11-07 00:51] falls asleep
[1518-04-05 00:31] falls asleep
[1518-10-04 00:27] wakes up
[1518-11-17 23:56] Guard #463 begins shift
[1518-08-13 00:05] wakes up
[1518-03-14 00:48] wakes up
[1518-07-05 00:04] falls asleep
[1518-08-25 00:48] wakes up
[1518-04-11 00:26] falls asleep
[1518-07-17 00:03] Guard #743 begins shift
[1518-08-04 00:40] falls asleep
[1518-09-06 00:29] falls asleep
[1518-05-06 00:59] wakes up
[1518-05-17 00:53] falls asleep
[1518-05-18 00:07] wakes up
[1518-10-08 00:04] Guard #3517 begins shift
[1518-10-06 00:08] falls asleep
[1518-06-10 00:51] wakes up
[1518-10-30 00:26] wakes up
[1518-08-23 23:48] Guard #1019 begins shift
[1518-06-03 00:01] falls asleep
[1518-07-28 00:04] Guard #947 begins shift
[1518-10-28 00:52] wakes up
[1518-02-27 00:03] falls asleep
[1518-06-22 23:56] Guard #1297 begins shift
[1518-05-01 00:07] falls asleep
[1518-03-18 00:00] Guard #643 begins shift
[1518-07-20 00:09] falls asleep
[1518-03-18 23:50] Guard #463 begins shift
[1518-05-30 00:03] falls asleep
[1518-10-19 00:00] Guard #151 begins shift
[1518-09-25 00:03] falls asleep
[1518-09-08 00:38] wakes up
[1518-07-08 00:28] wakes up
[1518-08-12 00:57] wakes up
[1518-03-28 00:04] Guard #1307 begins shift
[1518-04-26 00:49] wakes up
[1518-06-15 00:40] falls asleep
[1518-08-30 00:24] falls asleep
[1518-04-01 00:53] wakes up
[1518-03-22 00:58] wakes up
[1518-08-06 00:38] falls asleep
[1518-04-06 00:26] falls asleep
[1518-09-20 00:29] falls asleep
[1518-09-12 00:27] falls asleep
[1518-10-24 00:36] falls asleep
[1518-03-24 00:51] wakes up
[1518-04-11 00:50] wakes up
[1518-04-24 00:22] falls asleep
[1518-07-04 00:49] falls asleep
[1518-09-06 00:52] falls asleep
[1518-04-24 00:51] falls asleep
[1518-06-08 00:07] falls asleep
[1518-05-18 23:57] Guard #3469 begins shift
[1518-03-15 00:49] falls asleep
[1518-05-18 00:14] falls asleep
[1518-05-28 00:48] wakes up
[1518-07-12 00:46] wakes up
[1518-08-26 00:44] wakes up
[1518-05-18 00:41] wakes up
[1518-06-28 00:04] Guard #3323 begins shift
[1518-10-05 00:03] Guard #251 begins shift
[1518-02-26 00:00] Guard #971 begins shift
[1518-09-01 00:35] falls asleep
[1518-04-18 00:50] wakes up
[1518-10-06 00:22] wakes up
[1518-08-17 23:57] Guard #643 begins shift
[1518-03-08 00:52] wakes up
[1518-11-23 00:05] falls asleep
[1518-03-20 00:03] Guard #2801 begins shift
[1518-04-17 00:38] wakes up
[1518-07-20 00:54] falls asleep
[1518-09-14 00:27] falls asleep
[1518-05-15 00:13] falls asleep
[1518-04-08 23:57] Guard #947 begins shift
[1518-08-31 00:43] falls asleep
[1518-03-13 00:59] wakes up
[1518-02-24 00:34] falls asleep
[1518-04-27 00:42] falls asleep
[1518-08-11 23:58] Guard #1307 begins shift
[1518-11-06 00:01] falls asleep
[1518-06-29 00:33] falls asleep
[1518-06-08 00:51] wakes up
[1518-03-02 00:50] falls asleep
[1518-03-11 00:51] wakes up
[1518-07-19 23:58] Guard #1307 begins shift
[1518-04-12 00:53] falls asleep
[1518-10-25 00:53] wakes up
[1518-04-29 00:50] wakes up
[1518-04-26 00:39] wakes up
[1518-06-24 00:50] falls asleep
[1518-07-26 00:01] Guard #947 begins shift
[1518-10-11 23:57] Guard #3469 begins shift
[1518-09-17 00:08] falls asleep
[1518-03-03 23:59] Guard #947 begins shift
[1518-07-27 00:10] falls asleep
[1518-09-28 00:41] wakes up
[1518-09-30 00:27] wakes up
[1518-08-06 00:13] falls asleep
[1518-06-29 00:00] Guard #1439 begins shift
[1518-10-05 00:08] falls asleep
[1518-10-14 00:40] falls asleep
[1518-06-03 00:06] wakes up
[1518-07-17 00:46] wakes up
[1518-06-18 00:18] falls asleep
[1518-09-09 00:22] falls asleep
[1518-07-08 00:38] falls asleep
[1518-08-10 00:27] wakes up
[1518-07-09 00:34] falls asleep
[1518-08-01 00:52] wakes up
[1518-10-09 00:56] wakes up
[1518-10-17 00:02] Guard #509 begins shift
[1518-07-20 00:19] wakes up
[1518-07-21 00:00] Guard #971 begins shift
[1518-03-16 00:58] wakes up
[1518-10-04 00:18] falls asleep
[1518-07-04 00:43] falls asleep
[1518-04-15 00:15] falls asleep
[1518-05-29 00:03] falls asleep
[1518-04-09 00:45] falls asleep
[1518-03-04 23:59] Guard #463 begins shift
[1518-04-18 00:38] wakes up
[1518-07-02 23:57] Guard #263 begins shift
[1518-05-17 00:42] wakes up
[1518-04-29 23:59] Guard #463 begins shift
[1518-05-13 00:44] wakes up
[1518-03-05 23:58] Guard #947 begins shift
[1518-07-07 00:02] Guard #151 begins shift
[1518-05-04 00:20] wakes up
[1518-03-14 00:29] falls asleep
[1518-08-28 23:59] Guard #263 begins shift
[1518-10-18 00:03] Guard #3041 begins shift
[1518-03-09 00:37] wakes up
[1518-07-17 23:57] Guard #1307 begins shift
[1518-09-13 00:55] falls asleep
[1518-03-20 23:57] Guard #1297 begins shift
[1518-10-17 00:21] falls asleep
[1518-06-24 00:56] wakes up
[1518-10-28 00:59] wakes up
[1518-06-19 00:31] falls asleep
[1518-05-12 00:18] falls asleep
[1518-10-23 00:28] falls asleep
[1518-07-31 23:48] Guard #509 begins shift
[1518-08-16 00:39] falls asleep
[1518-03-19 00:23] wakes up
[1518-09-08 23:58] Guard #251 begins shift
[1518-06-24 00:00] Guard #263 begins shift
[1518-11-17 00:08] falls asleep
[1518-06-13 00:45] falls asleep
[1518-10-06 23:56] Guard #151 begins shift
[1518-03-02 00:02] Guard #743 begins shift"""


from enum import Enum
import re

class Action(Enum):
    GUARDID = 1
    ASLEEP = 2
    WAKE = 3 

def inputSplit(input):
    return input.split('\n')

def sortingDate(entry):
    return entry[7]

def do():
    splitInput = inputSplit(input)
    splitInput.sort()

    guards = {}

    count = Action.GUARDID
    guardID = 0
    asleep = -1
    for entry in splitInput:
        entry = entry.replace('[', '')
        entry = entry.replace(']', '')
        values = entry.split()

        date = values[0]
        time = values[1]

        if count == Action.GUARDID and len(values) == 4:
            count = Action.ASLEEP
        if count == Action.ASLEEP and len(values) > 4:
            count = Action.GUARDID
        
        if count == Action.GUARDID:
            guardID = int(re.findall('[0-9]+', values[3])[0])
            if guardID not in guards:
                guards[guardID] = {}
            count = Action.ASLEEP
            continue

        if count == Action.ASLEEP:
            if date not in guards[guardID]:
                guards[guardID][date] = [0 for x in range(60)]
            asleep = int(time[3:])
            count = Action.WAKE
            continue
        
        if count == Action.WAKE:
            wake = int(time[3:])
            
            for i in range(asleep, wake):
                guards[guardID][date][i] = 1

            count = Action.GUARDID 

    minutes = {}

    maxTime = -1
    sleepingID = -1
    for guard in guards.keys():
        minutes[guard] = 0
        for day in guards[guard].keys():
            minutes[guard] += sum(guards[guard][day])
            if minutes[guard] > maxTime:
                maxTime = minutes[guard]
                sleepingID = guard
            

    maxMinute = {}
    
    maxMinuteGuardID = -1
    maxMinuteSum = -1

    for guard in guards.keys():
        maxMinute[guard] = []        

        for i in range(60):
            totalMinute = sum([x[i] for x in guards[guard].values()])
            maxMinute[guard].append(totalMinute)
            if totalMinute > maxMinuteSum:
                maxMinuteSum = totalMinute
                maxMinuteGuardID = guard
        
    print(sleepingID, max(maxMinute[sleepingID]))
    print(maxMinuteSum, maxMinuteGuardID)
    

do()<file_sep>/2022/day20.py
from collections import defaultdict
from copy import deepcopy
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt

def do1(intInput):
	intInput = [(seq,x) for seq,x in enumerate(intInput)]
	workingList = mix(intInput, 1)
	length = len(intInput)

	zeroSeq = [y for (y,x) in intInput if x == 0][0]	
	zeroIndex = workingList.index((zeroSeq,0))
	
	return workingList[(zeroIndex + 1000) % length][1] + workingList[(zeroIndex + 2000) % length][1] + workingList[(zeroIndex + 3000) % length][1]

def do2(intInput):
	key = 811589153
	intInput = [(seq, x * key) for seq,x in enumerate(intInput)]
	length = len(intInput)
	workingList = mix(intInput, 10)

	zeroSeq = [y for (y,x) in intInput if x == 0][0]	
	zeroIndex = workingList.index((zeroSeq,0))
	
	return workingList[(zeroIndex + 1000) % length][1] + workingList[(zeroIndex + 2000) % length][1] + workingList[(zeroIndex + 3000) % length][1]

def mix(intInput, times):
	workingList = deepcopy(intInput)
	length = len(intInput)
	for _ in range(times):
		for seq,number in intInput:
			currentIndex = workingList.index((seq,number))
			if number == 0:
				continue
			newIndex = (currentIndex + number) % (length - 1)
			workingList.pop(currentIndex)
			workingList.insert(newIndex, (seq,number))
	
	return workingList

def do():
	strInput = readInputFile(20)

	intInput = convertToInt(strInput.split('\n'))

	print(do1(intInput))
	print(do2(intInput))

	print('done')


do()<file_sep>/2018/day10.py
input = """position=< 50200,  10144> velocity=<-5, -1>
position=< -9855,  -9873> velocity=< 1,  1>
position=<-29840,  30163> velocity=< 3, -3>
position=< 50213,  30162> velocity=<-5, -3>
position=< 20168,  20161> velocity=<-2, -2>
position=< 20147,  10144> velocity=<-2, -1>
position=< 30166, -39894> velocity=<-3,  4>
position=< -9863,  20157> velocity=< 1, -2>
position=< 20176,  50185> velocity=<-2, -5>
position=< 40210,  -9867> velocity=<-4,  1>
position=< 40178, -29887> velocity=<-4,  3>
position=< -9840,  40171> velocity=< 1, -4>
position=<-29893,  -9868> velocity=< 3,  1>
position=< 20149, -39901> velocity=<-2,  4>
position=< 30185,  40179> velocity=<-3, -4>
position=< 50171,  10147> velocity=<-5, -1>
position=< 50232, -29885> velocity=<-5,  3>
position=< 10151,  10150> velocity=<-1, -1>
position=< 30205,  30167> velocity=<-3, -3>
position=<-49871,  20158> velocity=< 5, -2>
position=< -9859,  -9865> velocity=< 1,  1>
position=< 10151, -19882> velocity=<-1,  2>
position=< -9843,  10144> velocity=< 1, -1>
position=< -9825,  -9865> velocity=< 1,  1>
position=< 10170,  20162> velocity=<-1, -2>
position=<-49917,  40171> velocity=< 5, -4>
position=< 40164,  40171> velocity=<-4, -4>
position=< 30198,  40171> velocity=<-3, -4>
position=< 50179, -49909> velocity=<-5,  5>
position=< 40199,  -9865> velocity=<-4,  1>
position=< 10193, -39901> velocity=<-1,  4>
position=<-29880, -29886> velocity=< 3,  3>
position=< 30193, -29890> velocity=<-3,  3>
position=< -9857,  30168> velocity=< 1, -3>
position=<-29893, -29887> velocity=< 3,  3>
position=< -9843,  20159> velocity=< 1, -2>
position=< 10176,  50180> velocity=<-1, -5>
position=< 50172, -19883> velocity=<-5,  2>
position=< 40218, -29884> velocity=<-4,  3>
position=<-49911,  -9870> velocity=< 5,  1>
position=<-19852,  40180> velocity=< 2, -4>
position=< -9883, -19876> velocity=< 1,  2>
position=<-29901,  30166> velocity=< 3, -3>
position=< 20160,  30171> velocity=<-2, -3>
position=< 50171, -19880> velocity=<-5,  2>
position=< 10148,  -9866> velocity=<-1,  1>
position=< 20197, -49901> velocity=<-2,  5>
position=<-49895, -49902> velocity=< 5,  5>
position=< 50211,  30166> velocity=<-5, -3>
position=< 30211,  10144> velocity=<-3, -1>
position=<-19868, -39895> velocity=< 2,  4>
position=<-39867,  -9870> velocity=< 4,  1>
position=<-49911,  30168> velocity=< 5, -3>
position=< 50179,  50187> velocity=<-5, -5>
position=< 50219, -29887> velocity=<-5,  3>
position=<-49895,  -9874> velocity=< 5,  1>
position=< 20145, -29888> velocity=<-2,  3>
position=< 10156,  30163> velocity=<-1, -3>
position=< 20176, -49910> velocity=<-2,  5>
position=<-49863, -49902> velocity=< 5,  5>
position=<-39850,  30170> velocity=< 4, -3>
position=< 50214, -19879> velocity=<-5,  2>
position=<-19882,  30162> velocity=< 2, -3>
position=< 10160, -19878> velocity=<-1,  2>
position=< 20168,  40180> velocity=<-2, -4>
position=< 50195,  50185> velocity=<-5, -5>
position=< -9858,  -9870> velocity=< 1,  1>
position=< 50187,  10153> velocity=<-5, -1>
position=<-49919, -19877> velocity=< 5,  2>
position=< 30209,  10151> velocity=<-3, -1>
position=<-49879,  20159> velocity=< 5, -2>
position=<-39902,  30171> velocity=< 4, -3>
position=< 30166,  50182> velocity=<-3, -5>
position=< -9855,  50188> velocity=< 1, -5>
position=<-39849,  50185> velocity=< 4, -5>
position=<-19884, -19880> velocity=< 2,  2>
position=<-39902, -49902> velocity=< 4,  5>
position=< 50171, -29892> velocity=<-5,  3>
position=< -9883, -39892> velocity=< 1,  4>
position=<-19850,  50184> velocity=< 2, -5>
position=<-19892, -19878> velocity=< 2,  2>
position=<-39870, -39894> velocity=< 4,  4>
position=<-39870,  40174> velocity=< 4, -4>
position=< 30196,  50189> velocity=<-3, -5>
position=<-49874, -29883> velocity=< 5,  3>
position=<-19888,  50180> velocity=< 2, -5>
position=<-49858,  10152> velocity=< 5, -1>
position=< 50192, -49905> velocity=<-5,  5>
position=<-49907,  50184> velocity=< 5, -5>
position=< 50184,  20160> velocity=<-5, -2>
position=< -9830, -19876> velocity=< 1,  2>
position=< 10159,  40172> velocity=<-1, -4>
position=< 20205,  -9867> velocity=<-2,  1>
position=< 40211, -19878> velocity=<-4,  2>
position=< 20185,  10144> velocity=<-2, -1>
position=<-49875,  -9865> velocity=< 5,  1>
position=< 10176,  30166> velocity=<-1, -3>
position=<-19836,  10150> velocity=< 2, -1>
position=<-19879, -29889> velocity=< 2,  3>
position=< 10183, -49905> velocity=<-1,  5>
position=< 20165,  10148> velocity=<-2, -1>
position=< 50171, -49909> velocity=<-5,  5>
position=< 30185,  20158> velocity=<-3, -2>
position=<-49915,  10148> velocity=< 5, -1>
position=<-39859,  10144> velocity=< 4, -1>
position=< 50195, -49904> velocity=<-5,  5>
position=< 40218, -39899> velocity=<-4,  4>
position=< 50183,  -9874> velocity=<-5,  1>
position=< 20204, -39901> velocity=<-2,  4>
position=< 50195, -29891> velocity=<-5,  3>
position=<-39902,  20162> velocity=< 4, -2>
position=< 20152,  30162> velocity=<-2, -3>
position=<-39894, -39895> velocity=< 4,  4>
position=<-19841, -19878> velocity=< 2,  2>
position=<-19848,  30171> velocity=< 2, -3>
position=< -9870,  30168> velocity=< 1, -3>
position=< 40179, -19879> velocity=<-4,  2>
position=<-49910, -39892> velocity=< 5,  4>
position=< 10146,  -9870> velocity=<-1,  1>
position=< 20197, -49902> velocity=<-2,  5>
position=<-19839,  40179> velocity=< 2, -4>
position=<-49898, -29883> velocity=< 5,  3>
position=< 20147,  20157> velocity=<-2, -2>
position=< 20176, -49905> velocity=<-2,  5>
position=< 10148, -19881> velocity=<-1,  2>
position=< 20152,  40173> velocity=<-2, -4>
position=< 20144,  20155> velocity=<-2, -2>
position=<-49858,  10151> velocity=< 5, -1>
position=< -9842,  20157> velocity=< 1, -2>
position=< 50227,  50185> velocity=<-5, -5>
position=<-29877,  50181> velocity=< 3, -5>
position=< 50203,  50189> velocity=<-5, -5>
position=< -9870,  10145> velocity=< 1, -1>
position=< -9872,  20157> velocity=< 1, -2>
position=< 20200,  40176> velocity=<-2, -4>
position=< 50227,  50182> velocity=<-5, -5>
position=< -9862,  50187> velocity=< 1, -5>
position=<-29857,  40171> velocity=< 3, -4>
position=< 30201,  40174> velocity=<-3, -4>
position=<-29900, -39897> velocity=< 3,  4>
position=<-39868,  -9870> velocity=< 4,  1>
position=<-39854, -19882> velocity=< 4,  2>
position=<-29896,  10144> velocity=< 3, -1>
position=< 20168,  50183> velocity=<-2, -5>
position=< 20184, -19875> velocity=<-2,  2>
position=< -9882,  -9874> velocity=< 1,  1>
position=<-29885, -39894> velocity=< 3,  4>
position=< 20184, -49901> velocity=<-2,  5>
position=<-39910,  10150> velocity=< 4, -1>
position=<-29842,  -9865> velocity=< 3,  1>
position=< 10195,  40171> velocity=<-1, -4>
position=< 50187,  40174> velocity=<-5, -4>
position=< 20192,  -9865> velocity=<-2,  1>
position=< -9839, -29883> velocity=< 1,  3>
position=< 10194,  20158> velocity=<-1, -2>
position=< -9827,  20160> velocity=< 1, -2>
position=<-49914, -29892> velocity=< 5,  3>
position=< 10170,  20162> velocity=<-1, -2>
position=< 10151,  40172> velocity=<-1, -4>
position=< -9846, -39892> velocity=< 1,  4>
position=< 20176,  40173> velocity=<-2, -4>
position=<-29885,  50182> velocity=< 3, -5>
position=< 10193,  30162> velocity=<-1, -3>
position=< 20160, -29884> velocity=<-2,  3>
position=<-19874, -49906> velocity=< 2,  5>
position=< -9830,  50188> velocity=< 1, -5>
position=< 20176,  -9868> velocity=<-2,  1>
position=< 50211,  40176> velocity=<-5, -4>
position=<-29869, -29891> velocity=< 3,  3>
position=<-29861,  30168> velocity=< 3, -3>
position=< 50195,  50188> velocity=<-5, -5>
position=<-49903, -19882> velocity=< 5,  2>
position=<-49916,  -9870> velocity=< 5,  1>
position=< 30201, -29889> velocity=<-3,  3>
position=< -9875,  50181> velocity=< 1, -5>
position=<-39910,  30170> velocity=< 4, -3>
position=< 50211, -29892> velocity=<-5,  3>
position=< 50219,  50183> velocity=<-5, -5>
position=< -9873,  40175> velocity=< 1, -4>
position=< -9855, -29891> velocity=< 1,  3>
position=<-29861,  20160> velocity=< 3, -2>
position=<-39894,  20157> velocity=< 4, -2>
position=< 30153, -29886> velocity=<-3,  3>
position=< 20171,  -9867> velocity=<-2,  1>
position=< 20176,  -9867> velocity=<-2,  1>
position=<-39870, -39899> velocity=< 4,  4>
position=< 30198, -29892> velocity=<-3,  3>
position=< -9854, -49901> velocity=< 1,  5>
position=< 10139, -49910> velocity=<-1,  5>
position=< -9830, -19880> velocity=< 1,  2>
position=< -9830, -39894> velocity=< 1,  4>
position=<-29880,  30162> velocity=< 3, -3>
position=< -9875, -19876> velocity=< 1,  2>
position=< 10195, -19875> velocity=<-1,  2>
position=<-29892,  40171> velocity=< 3, -4>
position=<-29893, -19883> velocity=< 3,  2>
position=< 20176, -19875> velocity=<-2,  2>
position=<-29844, -19883> velocity=< 3,  2>
position=<-29859,  10144> velocity=< 3, -1>
position=< 40211, -29887> velocity=<-4,  3>
position=<-49871,  10151> velocity=< 5, -1>
position=< 20157, -39894> velocity=<-2,  4>
position=< 30185,  -9865> velocity=<-3,  1>
position=< 30196, -29892> velocity=<-3,  3>
position=< 20197,  40175> velocity=<-2, -4>
position=<-19850,  20162> velocity=< 2, -2>
position=< 30153,  -9874> velocity=<-3,  1>
position=< 30153,  10148> velocity=<-3, -1>
position=<-39862, -49902> velocity=< 4,  5>
position=< 50203, -19879> velocity=<-5,  2>
position=<-39883, -39899> velocity=< 4,  4>
position=< -9862, -19880> velocity=< 1,  2>
position=< 20204,  50180> velocity=<-2, -5>
position=< 30195, -49906> velocity=<-3,  5>
position=< 10167,  10150> velocity=<-1, -1>
position=<-29865, -49901> velocity=< 3,  5>
position=< 30164, -39892> velocity=<-3,  4>
position=< -9835, -49908> velocity=< 1,  5>
position=<-19871, -19882> velocity=< 2,  2>
position=<-29853,  30168> velocity=< 3, -3>
position=<-19868,  20157> velocity=< 2, -2>
position=< 50195, -19881> velocity=<-5,  2>
position=< 40170, -49904> velocity=<-4,  5>
position=<-19851, -49910> velocity=< 2,  5>
position=< -9862,  30164> velocity=< 1, -3>
position=< 50171,  -9872> velocity=<-5,  1>
position=<-39869, -19874> velocity=< 4,  2>
position=< 30180,  20155> velocity=<-3, -2>
position=< 10188,  20157> velocity=<-1, -2>
position=< 10191,  -9867> velocity=<-1,  1>
position=<-29845,  10152> velocity=< 3, -1>
position=<-19889, -39901> velocity=< 2,  4>
position=< 40170,  20153> velocity=<-4, -2>
position=< 30177,  10150> velocity=<-3, -1>
position=< 30185,  20157> velocity=<-3, -2>
position=< 40206,  10144> velocity=<-4, -1>
position=<-39894,  50180> velocity=< 4, -5>
position=<-19892,  10146> velocity=< 2, -1>
position=<-39854,  10150> velocity=< 4, -1>
position=<-39889,  10151> velocity=< 4, -1>
position=< 10188, -39895> velocity=<-1,  4>
position=< 30196,  20162> velocity=<-3, -2>
position=< 10178, -29892> velocity=<-1,  3>
position=< 20184,  40178> velocity=<-2, -4>
position=< 20153, -49901> velocity=<-2,  5>
position=< 30165,  10153> velocity=<-3, -1>
position=<-49861,  30171> velocity=< 5, -3>
position=< 40186,  10149> velocity=<-4, -1>
position=<-49903,  20156> velocity=< 5, -2>
position=< 40179,  10148> velocity=<-4, -1>
position=< -9859, -19879> velocity=< 1,  2>
position=< -9827, -19880> velocity=< 1,  2>
position=<-39894,  10146> velocity=< 4, -1>
position=< 40178,  10146> velocity=<-4, -1>
position=<-19842,  10149> velocity=< 2, -1>
position=< 20192, -29884> velocity=<-2,  3>
position=<-19884, -39897> velocity=< 2,  4>
position=< 40162,  30163> velocity=<-4, -3>
position=< 50192,  40173> velocity=<-5, -4>
position=< 50173, -49906> velocity=<-5,  5>
position=< 40178, -49906> velocity=<-4,  5>
position=< 20205, -29887> velocity=<-2,  3>
position=< 30193,  10149> velocity=<-3, -1>
position=<-49871, -29886> velocity=< 5,  3>
position=<-39910,  20156> velocity=< 4, -2>
position=< -9862,  -9867> velocity=< 1,  1>
position=<-19860, -49904> velocity=< 2,  5>
position=< 20176, -19883> velocity=<-2,  2>
position=< -9862,  50189> velocity=< 1, -5>
position=<-49895,  30166> velocity=< 5, -3>
position=< -9875, -29885> velocity=< 1,  3>
position=< 20184,  -9873> velocity=<-2,  1>
position=<-49919,  10144> velocity=< 5, -1>
position=< -9870,  40172> velocity=< 1, -4>
position=<-49866,  30166> velocity=< 5, -3>
position=< 30165, -29888> velocity=<-3,  3>
position=<-19864,  -9866> velocity=< 2,  1>
position=< 20187,  20162> velocity=<-2, -2>
position=< 20172, -29884> velocity=<-2,  3>
position=<-19876, -19879> velocity=< 2,  2>
position=< 30197, -49910> velocity=<-3,  5>
position=< 10168, -29883> velocity=<-1,  3>
position=< 10160, -19878> velocity=<-1,  2>
position=<-29893, -39892> velocity=< 3,  4>
position=<-19883, -19879> velocity=< 2,  2>
position=<-29842,  20153> velocity=< 3, -2>
position=<-39878,  30165> velocity=< 4, -3>
position=< 40223, -19874> velocity=<-4,  2>
position=<-49911,  20155> velocity=< 5, -2>
position=<-49859, -19878> velocity=< 5,  2>
position=< 50200,  10153> velocity=<-5, -1>
position=< 10145, -49910> velocity=<-1,  5>
position=< 20197,  30168> velocity=<-2, -3>
position=<-19892, -29887> velocity=< 2,  3>
position=< 10167,  30166> velocity=<-1, -3>
position=<-49903,  30168> velocity=< 5, -3>
position=< -9864,  -9870> velocity=< 1,  1>
position=<-19833,  40180> velocity=< 2, -4>
position=< 50219,  50189> velocity=<-5, -5>
position=< 20197,  10153> velocity=<-2, -1>
position=<-39858,  50185> velocity=< 4, -5>
position=< 50204, -39892> velocity=<-5,  4>
position=< 40215, -49905> velocity=<-4,  5>
position=< 20168,  50180> velocity=<-2, -5>
position=<-29880,  40173> velocity=< 3, -4>
position=< -9864,  40175> velocity=< 1, -4>
position=<-39862,  10153> velocity=< 4, -1>
position=< -9854,  -9865> velocity=< 1,  1>
position=<-29880, -49907> velocity=< 3,  5>
position=< -9879, -19879> velocity=< 1,  2>
position=< 50228,  10153> velocity=<-5, -1>
position=< 50187,  50183> velocity=<-5, -5>
position=< -9843, -19874> velocity=< 1,  2>
position=< 30206,  40178> velocity=<-3, -4>
position=<-29867, -49901> velocity=< 3,  5>
position=< 40165, -19879> velocity=<-4,  2>
position=< 20200,  20157> velocity=<-2, -2>
position=< -9859,  10151> velocity=< 1, -1>
position=< 20155, -39897> velocity=<-2,  4>
position=< 30154, -39901> velocity=<-3,  4>
position=< 50207, -49901> velocity=<-5,  5>
position=<-29841, -49902> velocity=< 3,  5>
position=<-39889,  20158> velocity=< 4, -2>
position=< 40173,  30162> velocity=<-4, -3>
position=< 30177,  50187> velocity=<-3, -5>
position=< 40183,  40179> velocity=<-4, -4>
position=< 40219, -29883> velocity=<-4,  3>
position=< 40182,  -9870> velocity=<-4,  1>
position=< -9843,  40179> velocity=< 1, -4>
position=<-39866,  30166> velocity=< 4, -3>
position=< -9867, -49910> velocity=< 1,  5>
position=<-39877,  50189> velocity=< 4, -5>
position=<-49879,  -9870> velocity=< 5,  1>
position=< 50224, -29890> velocity=<-5,  3>
position=< 40172, -49901> velocity=<-4,  5>
position=< 10151, -39893> velocity=<-1,  4>
position=< 20193,  10145> velocity=<-2, -1>
position=< 40223,  -9868> velocity=<-4,  1>
position=<-49911, -19875> velocity=< 5,  2>
position=< 30174,  10144> velocity=<-3, -1>
position=< 20154, -29883> velocity=<-2,  3>
position=<-19844,  30168> velocity=< 2, -3>
position=<-19865, -49908> velocity=< 2,  5>
position=<-19843, -49909> velocity=< 2,  5>
position=< 50171, -49909> velocity=<-5,  5>
position=< 30210,  40180> velocity=<-3, -4>
position=< -9880,  50180> velocity=< 1, -5>
position=<-39870, -19875> velocity=< 4,  2>
position=< -9835,  10148> velocity=< 1, -1>
position=<-39862, -29888> velocity=< 4,  3>
position=< -9833,  30162> velocity=< 1, -3>
position=<-39852, -19874> velocity=< 4,  2>
position=<-39909, -19879> velocity=< 4,  2>
position=<-49903,  40178> velocity=< 5, -4>
position=< -9848,  50189> velocity=< 1, -5>
position=< -9831, -29891> velocity=< 1,  3>
position=<-19880, -39892> velocity=< 2,  4>
position=< 50216, -49910> velocity=<-5,  5>
position=< 50197, -39898> velocity=<-5,  4>
position=<-39897,  50185> velocity=< 4, -5>
position=< -9867, -49902> velocity=< 1,  5>
position=< 30162, -19874> velocity=<-3,  2>
position=<-19875,  40175> velocity=< 2, -4>
position=< 10156, -19878> velocity=<-1,  2>
position=< -9871, -49906> velocity=< 1,  5>
position=<-19880,  30162> velocity=< 2, -3>"""

import re

def updatePosition(coordinates):
    positionX, positionY, velocityX, velocityY = coordinates

    return [positionX + velocityX, positionY + velocityY, velocityX, velocityY]

def isMessage(l):
    negativeCounter = 0
    for star in l:
        hasNeighbour = False
        positionX, positionY, velocityX, velocityY = star  
        for neighbour in l:
            positionXN, positionYN, velocityXN, velocityYN = neighbour
            if (abs(positionX - positionXN) == 1 and positionY == positionYN) or (abs(positionY - positionYN) == 1 and positionX == positionXN):
                hasNeighbour = True
                break
        if not hasNeighbour:
            negativeCounter += 1
    if float(negativeCounter) / len(l) < 0.2:
        return True 
    else:
        return False
            
def printStars(l):
    minX = min([x[0] for x in l])
    maxX = max([x[0] for x in l])
    minY = min([x[1] for x in l])
    maxY = max([x[1] for x in l])

    result = [[' ' for x in range(maxX + 1)] for y in range(maxY + 1)]

    for star in l:
        starX = star[0] - minX
        starY = star[1] - minY
        result[starY][starX] = '.'

    return result

def do():
    splitInput = input.split('\n')

    l = []

    for star in splitInput:

        match = re.match('.*<(.*),(.*)>.*<(.*),(.*)>', star)

        positionX, positionY, velocityX, velocityY = [int(x) for x in match.groups()]

        l.append([positionX, positionY, velocityX, velocityY])

    seconds = 0
    while(True):
        seconds += 1
        l = [[x[0] + x[2], x[1] + x[3], x[2], x[3]] for x in l]

        if isMessage(l):
            return seconds
            return printStars(l)

print(do())

for line in result:
    s = ''
    for chr in line:
        s += chr
    print(s)


<file_sep>/2020/day18.py
from HelperFunctions import inputsplit
import re

def do1(puzzleInput):
    sum = 0
    for line in puzzleInput:
        sum += calculate(line, sumUp)

    return sum

def do2(puzzleInput):
    sum = 0
    for line in puzzleInput:
        sum += calculate(line, sumWithLineBeforeDot)

    return sum

def calculate(line, sumFunction):
    matches = re.findall('\([0-9 \+\*]+\)', line)
    while matches:
        match = matches[0]
        result = sumFunction(match[1:-1])
        line = line.replace(match, str(result), 1)
        matches = re.findall('\([0-9 \+\*]+\)', line)
    return sumFunction(line)

def sumWithLineBeforeDot(line):
    matches = re.findall('[\( ]?([0-9]+ \+ [0-9]+)[ \)]?', line)
    while matches:
        match = matches[0]
        result = sumUp(match)
        line = line.replace(match, str(result), 1)
        matches = re.findall('[0-9]+ \+ [0-9]+', line)
    return sumUp(line)

def sumUp(line):
    result = 0
    operation = add
    for symbol in line.split(' '):
        if symbol.isnumeric():
            symbol = int(symbol)
            result = operation(result, symbol)
        elif symbol == '+':
            operation = add
        elif symbol == '*':
            operation = multiply
    return result

def multiply(result, symbol):
    return result * symbol

def add(result, symbol):
    return result + symbol

def do():
    with open ('Input/day18.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2020/day11.py
from HelperFunctions import inputsplit
import copy


def do1(puzzleInput):
    seatPlan = prepareInput(puzzleInput)

    newSeatPlan = updateSeatPlan(seatPlan, False, 3)
                
    return countOccupiedSeats(newSeatPlan)

def do2(puzzleInput):
    seatPlan = prepareInput(puzzleInput)

    newSeatPlan = updateSeatPlan(seatPlan, True, 4)
                
    return countOccupiedSeats(newSeatPlan)

def updateSeatPlan(seatPlan, wholeLine, maxAdjacentSeats):
    newSeatPlan = copy.deepcopy(seatPlan)

    seatsChanged = True
    while seatsChanged:
        seatPlan = copy.deepcopy(newSeatPlan)
        seatsChanged = False
        for row in range(1, len(seatPlan) - 1):
            for column in range(1, len(seatPlan[0]) - 1):
                changed = newSeatState((row, column), newSeatPlan, seatPlan, wholeLine, maxAdjacentSeats)
                seatsChanged = seatsChanged or changed
    
    return newSeatPlan

def prepareInput(puzzleInput):
    seatPlan = [[] for x in puzzleInput]
    for i in range(len(puzzleInput)):
        for j in range(len(puzzleInput[0])):
            seatPlan[i].append(puzzleInput[i][j])
        seatPlan[i] = ['.'] + seatPlan[i] + ['.']
        
    floor = ['.'] + ['.' for x in puzzleInput[0]] + ['.']

    seatPlan.insert(0, floor)
    seatPlan.append(floor)   
    
    return seatPlan

def countOccupiedSeats(seatPlan):
    count = 0
    for row in seatPlan:
        count += row.count('#')

    return count

def newSeatState(seatPosition, newSeatPlan, seatPlan, wholeLine, maxAdjacentSeats):
    row, column = seatPosition
    seatState = seatPlan[row][column]
    occupiedAdjacentSeats = occupiedSeats(seatPosition, seatPlan, wholeLine)
    if  seatState == 'L' and occupiedAdjacentSeats == 0:
        newSeatPlan[row][column] = '#'
        return True
    elif seatState == '#' and occupiedAdjacentSeats > maxAdjacentSeats:
        newSeatPlan[row][column] = 'L'
        return True

    return False

def occupiedSeats(seatPosition, seatPlan, wholeLine):
    numberOfOccupiedSeats = 0
    
    for stepX in [-1, 0, 1]:
        for stepY in [-1, 0, 1]:
            if stepX == 0 and stepY == 0:
                continue
            if lookForOccupiedSeats(seatPlan, seatPosition, stepX, stepY, wholeLine):
                numberOfOccupiedSeats += 1
    
    return numberOfOccupiedSeats

def lookForOccupiedSeats(seatPlan, seatPosition, stepX, stepY, wholeLine):
    row, column = seatPosition
    posX = row + stepX
    posY = column + stepY
    
    if wholeLine:
        xEndLow = 0
        yEndLow = 0
        xEndHigh = len(seatPlan)
        yEndHigh = len(seatPlan[0])
    else:
        xEndLow =  row - 1
        xEndHigh = row + 2
        yEndLow = column - 1
        yEndHigh = column + 2

    while xEndLow <= posX < xEndHigh and yEndLow <= posY < yEndHigh:
        if seatPlan[posX][posY] == 'L':
            return False
        if seatPlan[posX][posY] == '#':
            return True
        posX = posX + stepX
        posY = posY + stepY
    return False

def do():
    with open ('Input/day11.txt') as f:
        strInput = f.read()

    splitInput = inputsplit(strInput, '\n')

    print(do1(splitInput))
    print(do2(splitInput))
    
do()<file_sep>/2021/day13.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
import re
from copy import deepcopy

def do1(dots, foldInstructions):
	points,instructions = getPointsAndInstructions(dots, foldInstructions)

	firstInstruction = instructions[0]

	points = fold(points, [firstInstruction])				

	return len(points)

def do2(dots, foldInstructions):
	points,instructions = getPointsAndInstructions(dots, foldInstructions)

	points = fold(points, instructions)		

	showPoints(points)

	return len(points)

def fold(points, instructions):
	for instruction in instructions:
		newPoints = set()
		match instruction:
			case ('x', value):
				for x,y in points:
					if x > value:
						newPoints.add((value - (x - value), y))
					else:
						newPoints.add((x,y))
			case ('y', value):
				for x,y in points:
					if y > value:
						newPoints.add((x, value - (y - value)))
					else:
						newPoints.add((x,y))
		points = deepcopy(newPoints)
	
	return points

def showPoints(points):
	maxX = max([x for x,y in points])
	maxY = max([y for x,y in points])

	grid = [['.' for i in range(maxX + 1)] for j in range(maxY + 1)]
	
	for x,y in points:
		grid[y][x] = '#'

	for line in grid:
		print(line)

def getPointsAndInstructions(dots, foldInstructions):
	points = set()
	instructions = []

	for dot in dots:
		x,y = convertToInt(dot.split(','))
		points.add((x,y))

	#foldInstructions
	for line in foldInstructions:
		match = re.fullmatch('fold along ([x,y])=([0-9]+)', line)
		if match:
			coordinate = match.groups()[0]
			value = int(match.groups()[1])
			instructions.append((coordinate,value))
	
	return points,instructions

def do():
	strInput = readInputFile(13)

	dots,foldInstructions = strInput.split('\n\n')
	dots = dots.split('\n')
	foldInstructions = foldInstructions.split('\n')

	print(do1(dots, foldInstructions))
	print(do2(dots, foldInstructions))

	print('done')


do()<file_sep>/2021/day3.py
from HelperFunctions import readInputFile
from HelperFunctions import readExampleInput
from HelperFunctions import convertToInt
from collections import defaultdict
from copy import deepcopy
import operator

def do1(splitInput):
    frequency = getFrequency(splitInput)
    
    gamma = ''
    epsilon = ''
    for position in sorted(frequency.keys()):
        if frequency[position][0] > frequency[position][1]:
            gamma += '0'
            epsilon += '1'
        else:
            gamma += '1'
            epsilon += '0'

    return int(gamma, 2) * int(epsilon, 2)

def do2(splitInput):
    oxygen = filterByFrequency(splitInput, operator.gt)

    scrubber = filterByFrequency(splitInput, operator.le)

    return scrubber * oxygen

def getFrequency(splitInput):
    frequency = defaultdict(lambda: {0: 0, 1: 0})
    
    for line in splitInput:
        for position,bit in enumerate(line):
            frequency[position][int(bit)] += 1
    
    return frequency

def filterByFrequency(currentInput, compareOperator=operator.gt):
    maxBit = len(currentInput[0])

    for i in range(maxBit):
        frequency = getFrequency(currentInput)
        if compareOperator(frequency[i][0], frequency[i][1]):
            currentInput = [x for x in currentInput if x[i] == '0']
        else:
            currentInput = [x for x in currentInput if x[i] == '1']    
        if len(currentInput) == 1:
            break
    
    return int(currentInput[0],2)

def do():
    strInput = readInputFile(3)
    
    splitInput = strInput.split('\n')

    print(do1(splitInput))
    print(do2(splitInput))

    print('done')


do()<file_sep>/2018/day9.py
input = "477 players; last marble is worth 70851 points"

def do(players, marble):

    result = {}
    l = [0, 1]
    position = 1
    player = 2
    for turn in range(2, marble + 1):
        if (turn % 23) == 0:
            if player not in result:
                result[player] = 0
            removePosition = (position - 7 + len(l)) % len(l)
            score = turn + l[removePosition]
            l.remove(l[removePosition])
            result[player] += score

            position = removePosition % len(l)
        else:
            index = (position + 2) % len(l)
            l.insert(index, turn)
            position = index

        player = (player + 1) % players

    return max(result.values())

result = do(477, 70851)
print(result)