├── 2022 ├── day-01.py ├── day-02.py ├── day-03.py ├── day-04.py ├── day-05.py ├── day-06.py ├── day-07.py ├── day-08.py ├── day-09.py ├── day-10.py ├── day-11.py ├── day-12.py ├── day-14.py ├── one-line-solutions.py └── the-beast.py ├── 2023 ├── day-01.py ├── day-02.py ├── day-03.py ├── day-04.py ├── day-05.py ├── day-06.py ├── day-07.py ├── day-08.py ├── day-09.py ├── day-10.py ├── day-11.py ├── day-12.py ├── day-13.py ├── day-14.py ├── day-15.py ├── day-16.py └── the-basilisk.py ├── .gitignore ├── README.md ├── images ├── 2022-day-07-meme.png ├── 2022-day-10-beast-length.png ├── 2023-day-03-regex-meme.png ├── 2023-day-05-walrus-meme.png ├── 2023-day-06-the-basilisk-viz.png ├── 2023-day-07-the-basilisk-viz.png ├── 2023-day-08-the-basilisk-viz.png ├── 2023-day-09-the-basilisk-viz.png ├── 2023-day-16-the-basilisk-viz.png └── why-use-long-code-meme.jpg ├── requirements.txt └── tools ├── create-blank-solution.py ├── create-rainbow-line-svg.py └── import-input.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore input files but not requirements 2 | *.txt 3 | !requirements.txt 4 | 5 | # Ignore personal working files 6 | */scratchpad.py 7 | *.ai 8 | 9 | # Ignore virtual environment files 10 | .env 11 | .venv 12 | env/ 13 | venv/ -------------------------------------------------------------------------------- /2022/day-01.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-01.txt') as file: 2 | groups = file.read().split('\n\n') 3 | 4 | groups = [group.split('\n') for group in groups] 5 | totals = [sum([int(x) for x in g]) for g in groups] 6 | totals.sort(reverse=True) 7 | 8 | # Part 1 9 | print('Day 01 Part 1:', totals[0]) 10 | 11 | # Part 2 12 | print('Day 01 Part 2:', sum(totals[:3])) 13 | 14 | # One-line Solutions 15 | print('Day 01 Part 1:', max([sum([int(x) for x in g]) for g in [group.split('\n') for group in open('inputs/day-01.txt').read().split('\n\n')]])) 16 | print('Day 01 Part 2:', sum(sorted([sum([int(x) for x in g]) for g in [group.split('\n') for group in open('inputs/day-01.txt').read().split('\n\n')]], reverse=True)[0:3])) 17 | -------------------------------------------------------------------------------- /2022/day-02.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-02.txt') as file: 2 | rounds = file.read().split('\n') 3 | 4 | # Part 1 5 | outcomeP1 = { 6 | 'A X': 3+1, 7 | 'A Y': 6+2, 8 | 'A Z': 0+3, 9 | 'B X': 0+1, 10 | 'B Y': 3+2, 11 | 'B Z': 6+3, 12 | 'C X': 6+1, 13 | 'C Y': 0+2, 14 | 'C Z': 3+3, 15 | } 16 | resultP1 = sum([outcomeP1[x] for x in rounds]) 17 | print('Day 02 Part 1:', resultP1) 18 | 19 | # Part 2 20 | outcomeP2 = { 21 | 'A X': 0+3, 22 | 'A Y': 3+1, 23 | 'A Z': 6+2, 24 | 'B X': 0+1, 25 | 'B Y': 3+2, 26 | 'B Z': 6+3, 27 | 'C X': 0+2, 28 | 'C Y': 3+3, 29 | 'C Z': 6+1, 30 | } 31 | resultP2 = sum([outcomeP2[x] for x in rounds]) 32 | print('Day 02 Part 2:', resultP2) 33 | 34 | # One-line Solutions 35 | print('Day 02 Part 1:', sum([{'A X':3+1,'A Y':6+2,'A Z':0+3,'B X':0+1,'B Y':3+2,'B Z':6+3,'C X':6+1,'C Y':0+2,'C Z':3+3}[x] for x in open('inputs/day-02.txt').read().split('\n')])) 36 | print('Day 02 Part 2:', sum([{'A X':0+3,'A Y':3+1,'A Z':6+2,'B X':0+1,'B Y':3+2,'B Z':6+3,'C X':0+2,'C Y':3+3,'C Z':6+1}[x] for x in open('inputs/day-02.txt').read().split('\n')])) 37 | -------------------------------------------------------------------------------- /2022/day-03.py: -------------------------------------------------------------------------------- 1 | def findPriority(item): 2 | if item.islower(): 3 | return ord(item)-96 4 | else: 5 | return ord(item)-38 6 | 7 | with open('inputs/day-03.txt') as file: 8 | rucksacks = file.read().split('\n') 9 | 10 | # Part 1 11 | splitRucksacks = [[i[:len(i)//2], i[len(i)//2:]] for i in rucksacks] 12 | sharedItems = [set(x).intersection(y).pop() for x, y in splitRucksacks] 13 | priorityTotal = sum([findPriority(x) for x in sharedItems]) 14 | print('Day 03 Part 1:', priorityTotal) 15 | 16 | # Part 2 17 | priorityTotal = 0 18 | for i in range(0,len(rucksacks),3): 19 | priorityTotal += findPriority(set(rucksacks[i]).intersection(rucksacks[i+1]).intersection(rucksacks[i+2]).pop()) 20 | print('Day 03 Part 2:', priorityTotal) 21 | 22 | # One-line Solutions 23 | print('Day 03 Part 1:', sum([ord(x)-96 if x.islower() else ord(x)-38 for x in [set(x).intersection(y).pop() for x, y in [[i[:len(i)//2], i[len(i)//2:]] for i in open('inputs/day-03.txt').read().split('\n')]]])) 24 | print('Day 03 Part 2:', sum([ord(x)-96 if x.islower() else ord(x)-38 for x in [set(open('inputs/day-03.txt').read().split('\n')[i]).intersection(open('inputs/day-03.txt').read().split('\n')[i+1]).intersection(open('inputs/day-03.txt').read().split('\n')[i+2]).pop() for i in range(0,len(open('inputs/day-03.txt').read().split('\n')),3)]])) 25 | -------------------------------------------------------------------------------- /2022/day-04.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-04.txt') as file: 2 | assignments = file.read().split('\n') 3 | 4 | sections = [x.split(',') for x in assignments] 5 | sections = [[[int(x) for x in a.split('-')], [int(y) for y in b.split('-')]] for a, b in sections] 6 | 7 | # Part 1 8 | subsets = [(x[0][0] >= x[1][0] and x[0][1] <= x[1][1]) or (x[0][0] <= x[1][0] and x[0][1] >= x[1][1]) for x in sections] 9 | print('Day 04 Part 1:', sum(subsets)) 10 | 11 | # Part 2 12 | overlaps = [x[0][0] <= x[1][1] and x[0][1] >= x[1][0] for x in sections] 13 | print('Day 04 Part 2:', sum(overlaps)) 14 | 15 | # One-line Solutions 16 | print('Day 04 Part 1:', sum([(n[0][0] >= n[1][0] and n[0][1] <= n[1][1]) or (n[0][0] <= n[1][0] and n[0][1] >= n[1][1]) for n in [[[int(x) for x in a.split('-')], [int(y) for y in b.split('-')]] for a, b in [x.split(',') for x in open('inputs/day-04.txt').read().split('\n')]]])) 17 | print('Day 04 Part 2:', sum([n[0][0] <= n[1][1] and n[0][1] >= n[1][0] for n in [[[int(x) for x in a.split('-')], [int(y) for y in b.split('-')]] for a, b in [x.split(',') for x in open('inputs/day-04.txt').read().split('\n')]]])) 18 | -------------------------------------------------------------------------------- /2022/day-05.py: -------------------------------------------------------------------------------- 1 | def getCrates(input): 2 | crates = [[] for i in range(9)] 3 | for line in input[:8]: 4 | for i in range(1,len(line),4): 5 | if line[i].isalpha(): 6 | crates[i//4].append(line[i]) 7 | return crates 8 | 9 | with open('inputs/day-05.txt') as file: 10 | input = file.read().split('\n') 11 | 12 | moves = [y.split(' ') for y in input[10:]] 13 | moves = [[int(x[1]), int(x[3]), int(x[5])] for x in moves] 14 | 15 | # Part 1 16 | crates = getCrates(input) 17 | for move in moves: 18 | for n in range(move[0]): 19 | item = crates[move[1]-1].pop(0) 20 | crates[move[2]-1].insert(0, item) 21 | print('Day 05 Part 1:', ''.join([c[0] for c in crates])) 22 | 23 | # Part 2 24 | crates = getCrates(input) 25 | for move in moves: 26 | items = [] 27 | for n in range(move[0]): 28 | items.insert(0, crates[move[1]-1].pop(0)) 29 | for i in items: 30 | crates[move[2]-1].insert(0, i) 31 | print('Day 05 Part 2:', ''.join([c[0] for c in crates])) 32 | 33 | # One-line Solutions 34 | print('Day 05 Part 1:', ''.join([c[0] for c in crates] if not (input := open('inputs/day-05.txt').read().split('\n')) or not (moves := [[int(x[1]), int(x[3]), int(x[5])] for x in [y.split(' ') for y in input[10:]]]) or not (crates := [[] for i in range(9)]) or not [crates[j//4].append(line[j]) for line in input[:8] for j in range(1,len(line),4) if line[j].isalpha()] or [crates[move[2]-1].insert(0, crates[move[1]-1].pop(0)) for move in moves for n in range(move[0])] else '')) 35 | print('Day 05 Part 2:', ''.join([c[0] for c in crates] if not (input := open('inputs/day-05.txt').read().split('\n')) or not (moves := [[int(x[1]), int(x[3]), int(x[5])] for x in [y.split(' ') for y in input[10:]]]) or not (crates := [[] for i in range(9)]) or not [crates[j//4].append(line[j]) for line in input[:8] for j in range(1,len(line),4) if line[j].isalpha()] or [crates[move[2]-1].insert(0, item) for move in moves for item in reversed([crates[move[1]-1].pop(0) for n in range(move[0])])] else '')) 36 | -------------------------------------------------------------------------------- /2022/day-06.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-06.txt') as file: 2 | input = file.read() 3 | 4 | # Part 1 5 | print('Day 06 Part 1:', [i+1 for i in range(3,len(input)) if len(set(input[i-3:i+1])) == 4][0]) 6 | 7 | # Part 2 8 | print('Day 06 Part 2:', [i+1 for i in range(13,len(input)) if len(set(input[i-13:i+1])) == 14][0]) 9 | 10 | # One-line Solutions 11 | print('Day 06 Part 1:', [i+1 for x in [open('inputs/day-06.txt').read()] for i in range(3,len(x)) if len(set(x[i-3:i+1])) == 4][0]) 12 | print('Day 06 Part 2:', [i+1 for x in [open('inputs/day-06.txt').read()] for i in range(13,len(x)) if len(set(x[i-13:i+1])) == 14][0]) 13 | -------------------------------------------------------------------------------- /2022/day-07.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-07.txt') as file: 2 | commands = file.read().split('\n') 3 | 4 | lines = [x.split(' ') for x in commands] 5 | dirs = {} 6 | curDirs = [] 7 | for l in lines: 8 | if l[0] == '$' and l[1] == 'cd': 9 | if l[2] == '/': 10 | curDirs = ['//'] 11 | dirs['//'] = 0 12 | elif l[2] == '..': 13 | curDirs.pop() 14 | else: 15 | curDir = '/'.join(curDirs) + '/' + l[2] 16 | curDirs.append(curDir) 17 | if not dirs.get(curDir): 18 | dirs[curDir] = 0 19 | elif l[0].isdigit(): 20 | for d in curDirs: 21 | dirs[d] += int(l[0]) 22 | 23 | # Part 1 24 | largeFiles = [x for x in dirs.values() if x <= 100000] 25 | print('Day 07 Part 1:', sum(largeFiles)) 26 | 27 | # Part 2 28 | spaceNeeded = dirs['//']-40000000 29 | deletionCandidates = [x for x in dirs.values() if x > spaceNeeded] 30 | print('Day 07 Part 2:', min(deletionCandidates)) 31 | 32 | # One-line Solutions 33 | print('Day 07 Part 1:', sum([x for x in dirs.values() if x <= 100000] if not (dirs := {}) and not (curDirs := []) and [((l[0] == '$' and l[1] == 'cd') and (((l[2] == '/') and (curDirs := ['//']) and not (dirs.update({'//':0}))) or (l[2] == '..' and curDirs.pop()) or ((curDir := '/'.join(curDirs) + '/' + l[2]) and not curDirs.append(curDir) and (not dirs.get(curDir) and not dirs.update({curDir:0}))))) or (l[0].isdigit() and [dirs.update({d: dirs[d] + int(l[0])}) for d in curDirs]) for l in [c.split(' ') for c in open('inputs/day-07.txt').read().split('\n')]] else '')) 34 | print('Day 07 Part 2:', min([x for x in dirs.values() if x > dirs['//']-40000000]) if not (dirs := {}) and not (curDirs := []) and [((l[0] == '$' and l[1] == 'cd') and (((l[2] == '/') and (curDirs := ['//']) and not (dirs.update({'//':0}))) or (l[2] == '..' and curDirs.pop()) or ((curDir := '/'.join(curDirs) + '/' + l[2]) and not curDirs.append(curDir) and (not dirs.get(curDir) and not dirs.update({curDir:0}))))) or (l[0].isdigit() and [dirs.update({d: dirs[d] + int(l[0])}) for d in curDirs]) for l in [c.split(' ') for c in open('inputs/day-07.txt').read().split('\n')]] else '') 35 | -------------------------------------------------------------------------------- /2022/day-08.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-08.txt') as file: 2 | t = file.read().split('\n') 3 | 4 | t = [[int(y) for y in x] for x in t] 5 | 6 | # Part 1 7 | count = 0 8 | for r in range(len(t)): 9 | for c in range(len(t[r])): 10 | treesLeft = [x for x in t[r][:c] if x >= t[r][c]] 11 | treesRight = [x for x in t[r][c+1:] if x >= t[r][c]] 12 | treesUp = [x[c] for i, x in enumerate(t) if x[c] >= t[r][c] and i < r] 13 | treesDown = [x[c] for i, x in enumerate(t) if x[c] >= t[r][c] and i > r] 14 | count += not (treesLeft and treesRight and treesUp and treesDown) 15 | print('Day 08 Part 1:', count) 16 | 17 | # Part 2 18 | maxScore = 0 19 | for r in range(len(t)): 20 | for c in range(len(t[r])): 21 | treesLeft = sum([(x < t[r][c]) or (found:=True) for x in t[r][:c][::-1] if not found] if not (found:=False) else '') 22 | treesRight = sum([(x < t[r][c]) or (found:=True) for x in t[r][c+1:] if not found] if not (found:=False) else '') 23 | treesUp = sum([(x[c] < t[r][c]) or (found:=True) for i, x in reversed(list(enumerate(t))) if not found and i < r] if not (found:=False) else '') 24 | treesDown = sum([(x[c] < t[r][c]) or (found:=True) for i, x in enumerate(t) if not found and i > r] if not (found:=False) else '') 25 | scenicScore = treesLeft * treesRight * treesUp * treesDown 26 | if scenicScore > maxScore: 27 | maxScore = scenicScore 28 | print('Day 08 Part 2:', maxScore) 29 | 30 | # One-line Solutions 31 | print('Day 08 Part 1:', sum([not bool([x for x in t[r][:c] if x >= t[r][c]] and [x for x in t[r][c+1:] if x >= t[r][c]] and [x[c] for i, x in enumerate(t) if x[c] >= t[r][c] and i < r] and [x[c] for i, x in enumerate(t) if x[c] >= t[r][c] and i > r]) for t in [[[int(y) for y in x] for x in open('inputs/day-08.txt').read().split('\n')]] for r in range(len(t)) for c in range(len(t[r]))])) 32 | print('Day 08 Part 2:', max([sum([(x < t[r][c]) or (found:=True) for x in t[r][:c][::-1] if not found] if not (found:=False) else '') * sum([(x < t[r][c]) or (found:=True) for x in t[r][c+1:] if not found] if not (found:=False) else '') * sum([(x[c] < t[r][c]) or (found:=True) for i, x in reversed(list(enumerate(t))) if not found and i < r] if not (found:=False) else '') * sum([(x[c] < t[r][c]) or (found:=True) for i, x in enumerate(t) if not found and i > r] if not (found:=False) else '') for t in [[[int(y) for y in x] for x in open('inputs/day-08.txt').read().split('\n')]] for r in range(len(t)) for c in range(len(t[r]))])) 33 | -------------------------------------------------------------------------------- /2022/day-09.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-09.txt') as file: 2 | moves = file.read().split('\n') 3 | 4 | moves = [x.split(' ') for x in moves] 5 | 6 | def moveNext(h, t): 7 | if t[0] < h[0]-1: 8 | if t[1] == h[1]: 9 | t[0] += 1 10 | elif t[1] > h[1]: 11 | t[0] += 1 12 | t[1] -= 1 13 | elif t[1] < h[1]: 14 | t[0] += 1 15 | t[1] += 1 16 | elif t[0] > h[0]+1: 17 | if t[1] == h[1]: 18 | t[0] -= 1 19 | elif t[1] > h[1]: 20 | t[0] -= 1 21 | t[1] -= 1 22 | elif t[1] < h[1]: 23 | t[0] -= 1 24 | t[1] += 1 25 | elif t[1] < h[1]-1: 26 | if t[0] == h[0]: 27 | t[1] += 1 28 | elif t[0] < h[0]: 29 | t[0] += 1 30 | t[1] += 1 31 | elif t[0] > h[0]: 32 | t[0] -= 1 33 | t[1] += 1 34 | elif t[1] > h[1]+1: 35 | if t[0] == h[0]: 36 | t[1] -= 1 37 | elif t[0] < h[0]: 38 | t[0] += 1 39 | t[1] -= 1 40 | elif t[0] > h[0]: 41 | t[0] -= 1 42 | t[1] -= 1 43 | 44 | def moveHead(d, h): 45 | if d == 'R': 46 | h[0] += 1 47 | if d == 'L': 48 | h[0] -= 1 49 | elif d == 'U': 50 | h[1] += 1 51 | elif d == 'D': 52 | h[1] -= 1 53 | 54 | # Part 1 55 | visited = set() 56 | h, t = [0,0], [0,0] 57 | for d, n in moves: 58 | for _ in range(int(n)): 59 | visited.add(tuple(t)) 60 | moveHead(d, h) 61 | moveNext(h, t) 62 | print('Day 09 Part 1:', len(visited)) 63 | 64 | # Part 2 65 | visited = set() 66 | s = [[0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0]] 67 | for d, n in moves: 68 | for _ in range(int(n)): 69 | moveHead(d, s[0]) 70 | for i in range(1,10): 71 | moveNext(s[i-1], s[i]) 72 | visited.add(tuple(s[9])) 73 | print('Day 09 Part 2:', len(visited)) 74 | 75 | # One-line Solutions 76 | print('Day 09 Part 1:', len(visited) if (visited := {(0,0)}) and (h := [0,0]) and (t := [0,0]) and [((d == 'R' and ((t[1] == h[1] and t[0] == h[0]-1 and (t.insert(0, t.pop(0)+1))) or (t[1] > h[1] and t[0] == h[0]-1 and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)-1))) or (t[1] < h[1] and t[0] == h[0]-1 and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)+1))) or 1) and not h.insert(0, h.pop(0)+1)) or (d == 'L' and ((t[1] == h[1] and t[0] == h[0]+1 and (t.insert(0, t.pop(0)-1))) or (t[1] > h[1] and t[0] == h[0]+1 and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)-1))) or (t[1] < h[1] and t[0] == h[0]+1 and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)+1))) or 1) and not h.insert(0, h.pop(0)-1)) or (d == 'U' and ((t[1] == h[1]-1 and t[0] == h[0] and (t.insert(1, t.pop(1)+1))) or (t[1] == h[1]-1 and t[0] < h[0] and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)+1))) or (t[1] == h[1]-1 and t[0] > h[0] and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)+1))) or 1) and h.insert(1, h.pop(1)+1)) or (d == 'D' and ((t[1] == h[1]+1 and t[0] == h[0] and (t.insert(1, t.pop(1)-1))) or (t[1] == h[1]+1 and t[0] < h[0] and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)-1))) or (t[1] == h[1]+1 and t[0] > h[0] and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)-1))) or 1) and not h.insert(1, h.pop(1)-1)) or 1) and (visited.add(tuple(t))) for d, n in (x.split(' ') for x in open('inputs/day-09.txt').read().split('\n')) for _ in range(int(n))] else '') 77 | print('Day 09 Part 2:', len(visited) if (visited := {(0,0)}) and (s := [[0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0]]) and [not ((d == 'R' and s[0].insert(0, s[0].pop(0)+1)) or (d == 'L' and s[0].insert(0, s[0].pop(0)-1)) or (d == 'U' and s[0].insert(1, s[0].pop(1)+1)) or (d == 'D' and s[0].insert(1, s[0].pop(1)-1))) and [(s[i][0] < s[i-1][0]-1 and ((s[i][1] == s[i-1][1] and (s[i].insert(0, s[i].pop(0)+1))) or (s[i][1] > s[i-1][1] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)-1))) or (s[i][1] < s[i-1][1] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)+1))))) or (s[i][0] > s[i-1][0]+1 and ((s[i][1] == s[i-1][1] and (s[i].insert(0, s[i].pop(0)-1))) or (s[i][1] > s[i-1][1] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)-1))) or (s[i][1] < s[i-1][1] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)+1))))) or (s[i][1] < s[i-1][1]-1 and ((s[i][0] == s[i-1][0] and (s[i].insert(1, s[i].pop(1)+1))) or (s[i][0] < s[i-1][0] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)+1))) or (s[i][0] > s[i-1][0] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)+1))))) or (s[i][1] > s[i-1][1]+1 and ((s[i][0] == s[i-1][0] and (s[i].insert(1, s[i].pop(1)-1))) or (s[i][0] < s[i-1][0] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)-1))) or (s[i][0] > s[i-1][0] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)-1))))) for i in range(1,10)] and (visited.add(tuple(s[9]))) for d, n in (x.split(' ') for x in open('inputs/day-09.txt').read().split('\n')) for _ in range(int(n))] else '') -------------------------------------------------------------------------------- /2022/day-10.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-10.txt') as file: 2 | cmds = file.read().split('\n') 3 | 4 | cmds = [y.split(' ') for y in cmds] 5 | 6 | # Part 1 7 | def increaseCycle(cycle, n): 8 | for _ in range(n): 9 | cycle += 1 10 | if (cycle+20) % 40 == 0: 11 | signalStrengths.append(cycle*x) 12 | return cycle 13 | 14 | x, cycle = 1, 0 15 | signalStrengths = [] 16 | for c in cmds: 17 | if c[0] == 'addx': 18 | cycle = increaseCycle(cycle, 2) 19 | x += int(c[1]) 20 | elif c[0] == 'noop': 21 | cycle = increaseCycle(cycle, 1) 22 | print('Day 10 Part 1:', sum(signalStrengths)) 23 | 24 | 25 | # Part 2 26 | def moveSprite(x): 27 | sprite = ['.'] * 40 28 | for i in range(x-1,x+2): 29 | if i < 40 and i >= 0: 30 | sprite[i] = '#' 31 | return sprite 32 | 33 | def nextCycle(): 34 | if sprite[cycle-((cycle//40)*40)-1] == '#': 35 | nextPixel = '#' 36 | else: 37 | nextPixel = '.' 38 | crt.append(nextPixel) 39 | 40 | x, cycle = 1, 0 41 | sprite = ['#'] * 3 + ['.'] * 37 42 | crt = [] 43 | for c in cmds: 44 | if c[0] == 'addx': 45 | for _ in range(2): 46 | cycle += 1 47 | nextCycle() 48 | x += int(c[1]) 49 | sprite = moveSprite(x) 50 | elif c[0] == 'noop': 51 | cycle += 1 52 | nextCycle() 53 | 54 | print('Day 10 Part 2:') 55 | for i, p in enumerate(crt): 56 | print(p,end='') 57 | if (i+1) % 40 == 0: 58 | print('\n',end='') 59 | 60 | # One-line Solutions 61 | print('Day 10 Part 1:', sum(signalStrengths) if not (signalStrengths := []) and (x := 1) and not (cycle := 0) and [[(c[0] == 'addx') and [(cycle := cycle+1) and ((cycle+20) % 40 == 0 and signalStrengths.append(cycle*x)) for _ in range(2)] and (x := x+int(c[1]))] and [(c[0] == 'noop') and [(cycle := cycle+1) and ((cycle+20) % 40 == 0 and signalStrengths.append(cycle*x))]] for c in [y.split(' ') for y in open('inputs/day-10.txt').read().split('\n')]] else '') 62 | print('Day 10 Part 2:\n',''.join(v[:-1]) if not (v := []) and (x := 1) and not (cycle := 0) and (sprite := ['#']*3 + ['.']*37) and not (crt := []) and [((c[0] == 'addx' and [(cycle := cycle+1) and ([crt.append('#' if sprite[cycle-((cycle//40)*40)-1] == '#' else '.')] or 1) for _ in range(2)] and ((x := x+int(c[1])) or 1) and (sprite := ['.']*40) and [sprite.pop(i) and sprite.insert(i, '#') for i in range(x-1,x+2) if i < 40 and i >= 0]) or (c[0] == 'noop' and [(cycle := cycle+1) and crt.append('#' if sprite[cycle-((cycle//40)*40)-1] == '#' else '.')])) for c in [y.split(' ') for y in open('inputs/day-10.txt').read().split('\n')]] and [not v.append(p) and ((i+1) % 40 == 0 and v.append('\n')) for i, p in enumerate(crt)] else '', sep='') -------------------------------------------------------------------------------- /2022/day-11.py: -------------------------------------------------------------------------------- 1 | def resetMonkeys(): 2 | with open('inputs/day-11.txt') as file: 3 | monkeys = file.read().split('\n\n') 4 | 5 | monkeys = [[z.split(' ') for z in y[1:]] for y in [x.split('\n') for x in monkeys]] 6 | 7 | for mon in monkeys: 8 | mon[0] = list(map(int,[a.replace(',','') for a in mon[0][4:]])) 9 | if mon[1][6] == '*': 10 | if mon[1][7] == 'old': 11 | mon[1] = lambda a: a * a 12 | else: 13 | mon[1] = lambda a, n=int(mon[1][7]): a * n 14 | elif mon[1][6] == '+': 15 | if mon[1][7] == 'old': 16 | mon[1] = lambda a: a + a 17 | else: 18 | mon[1] = lambda a, n=int(mon[1][7]): a + n 19 | mon[2] = int(mon[2][5]) 20 | mon[3] = int(mon[3][9]) 21 | mon[4] = int(mon[4][9]) 22 | mon.append(0) 23 | 24 | return monkeys 25 | 26 | # Part 1 27 | monkeys = resetMonkeys() 28 | for _ in range(20): 29 | for m in monkeys: 30 | for i in m[0]: 31 | m[5] += 1 32 | i = m[1](i) // 3 33 | if i % m[2] == 0: 34 | monkeys[m[3]][0].append(i) 35 | else: 36 | monkeys[m[4]][0].append(i) 37 | m[0] = [] 38 | inspectionCount = sorted([k[5] for k in monkeys], reverse=True) 39 | print('Day 11 Part 1:', inspectionCount[0] * inspectionCount[1]) 40 | 41 | 42 | # Part 2 43 | monkeys = resetMonkeys() 44 | lcm = 1 45 | for k in monkeys: 46 | lcm *= k[2] 47 | 48 | for _ in range(10000): 49 | for m in monkeys: 50 | for i in m[0]: 51 | m[5] += 1 52 | i = m[1](i) % lcm 53 | if i % m[2] == 0: 54 | monkeys[m[3]][0].append(i) 55 | else: 56 | monkeys[m[4]][0].append(i) 57 | m[0] = [] 58 | inspectionCount = sorted([k[5] for k in monkeys], reverse=True) 59 | print('Day 11 Part 2:', inspectionCount[0] * inspectionCount[1]) 60 | 61 | 62 | # One-line Solutions 63 | print('Day 11 Part 1:',inspectionCount[0] * inspectionCount[1] if (monkeys := [[list(map(int,[a.replace(',','') for a in mon[0][4:]])), (mon[1][6] == '*' and ((mon[1][7] == 'old' and (lambda a: a * a)) or (lambda a, n=int(mon[1][7]): a * n))) or ((mon[1][6] == '+' and ((mon[1][7] == 'old' and (lambda a: a + a)) or (lambda a, n=int(mon[1][7]): a + n)))), int(mon[2][5]), int(mon[3][9]), int(mon[4][9]), 0] for mon in [[z.split(' ') for z in y[1:]] for y in [x.split('\n') for x in open('inputs/day-11.txt').read().split('\n\n')]]]) and [[[not (m.insert(5, m.pop(5)+1)) and ((m[1](i) // 3 % m[2] == 0 and not monkeys[m[3]][0].append(m[1](i) // 3)) or not monkeys[m[4]][0].append(m[1](i) // 3)) for i in m[0]] and (not m.insert(1,[]) and m.pop(0)) for m in monkeys] for _ in range(20)] and (inspectionCount := sorted([k[5] for k in monkeys], reverse=True)) else '') 64 | print('Day 11 Part 2:',inspectionCount[0] * inspectionCount[1] if (monkeys := [[list(map(int,[a.replace(',','') for a in mon[0][4:]])), (mon[1][6] == '*' and ((mon[1][7] == 'old' and (lambda a: a * a)) or (lambda a, n=int(mon[1][7]): a * n))) or ((mon[1][6] == '+' and ((mon[1][7] == 'old' and (lambda a: a + a)) or (lambda a, n=int(mon[1][7]): a + n)))), int(mon[2][5]), int(mon[3][9]), int(mon[4][9]), 0] for mon in [[z.split(' ') for z in y[1:]] for y in [x.split('\n') for x in open('inputs/day-11.txt').read().split('\n\n')]]]) and (lcm := 1) and ([lcm := lcm * k[2] for k in monkeys]) and [[[not (m.insert(5, m.pop(5)+1)) and (((m[1](i) % lcm) % m[2] == 0 and not monkeys[m[3]][0].append(m[1](i) % lcm)) or not monkeys[m[4]][0].append(m[1](i) % lcm)) for i in m[0]] and (not m.insert(1,[]) and m.pop(0)) for m in monkeys] for _ in range(10000)] and (inspectionCount := sorted([k[5] for k in monkeys], reverse=True)) else '') -------------------------------------------------------------------------------- /2022/day-12.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-12.txt') as file: 2 | grid = file.read().split('\n') 3 | 4 | grid = [[*l] for l in grid] 5 | 6 | possibleStarts = [] 7 | for r in range(len(grid)): 8 | for c in range(len(grid[0])): 9 | if grid[r][c] == 'S': 10 | grid[r][c] = 'a' 11 | start = (r, c) 12 | elif grid[r][c] == 'E': 13 | grid[r][c] = 'z' 14 | end = (r, c) 15 | if grid[r][c] == 'a': 16 | possibleStarts.append([((r, c), 0)]) 17 | 18 | def search(paths): 19 | visited = set() 20 | while len(paths) > 0: 21 | curPath = paths.pop(0) 22 | if curPath[0] == end: 23 | return curPath[1] 24 | elif curPath[0] not in visited: 25 | visited.add(curPath[0]) 26 | for i in range(curPath[0][0]-1, curPath[0][0]+2): 27 | for j in range(curPath[0][1]-1, curPath[0][1]+2): 28 | if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and (i == curPath[0][0] or j == curPath[0][1]) \ 29 | and ((i, j) != curPath[0]) and ord(grid[i][j]) <= ord(grid[curPath[0][0]][curPath[0][1]])+1: 30 | paths.append(((i, j), curPath[1]+1)) 31 | 32 | # Part 1 33 | print('Day 12 Part 1:', search([(start, 0)])) 34 | 35 | # Part 2 36 | print('Day 12 Part 2:', min([n for n in [search([(s[0][0], 0)]) for s in possibleStarts] if n])) 37 | 38 | # One-line Solutions coming soon! 39 | 40 | -------------------------------------------------------------------------------- /2022/day-14.py: -------------------------------------------------------------------------------- 1 | with open('inputs/day-14.txt') as file: 2 | rocks = file.read().split('\n') 3 | 4 | rocks = [[list(map(int, z.split(','))) for z in y] for y in [x.split(' -> ') for x in rocks]] 5 | 6 | def extendCaveX(cave, i): 7 | if len(cave) == 0: 8 | cave.extend(list(list()) for _ in range(i+1)) 9 | elif len(cave) <= i: 10 | cave.extend([['.' for _ in range(len(cave[0]))] for _ in range(i-len(cave)+2)]) 11 | 12 | def extendCaveY(cave, j): 13 | if len(cave[0]) <= j: 14 | [c.extend(['.' for _ in range(j-len(c)+2)]) for c in cave] 15 | 16 | def caveSetup(): 17 | cave = [] 18 | for row in rocks: 19 | for l, line in enumerate(row): 20 | if l != len(row)-1: 21 | extendCaveX(cave, max(line[0], row[l+1][0])) 22 | if line[0] == row[l+1][0]: 23 | for a in range(min(line[1], row[l+1][1]), max(line[1], row[l+1][1])+1): 24 | extendCaveY(cave, a) 25 | cave[line[0]][a] = '#' 26 | else: 27 | for b in range(min(line[0], row[l+1][0]), max(line[0], row[l+1][0])+1): 28 | cave[b][line[1]] = '#' 29 | return cave 30 | 31 | # Part 1 32 | cave = caveSetup() 33 | stopAll = 0 34 | sandCount = 0 35 | while not stopAll: 36 | curX, curY = 500, 0 37 | for _ in range(len(cave[0])): 38 | if curY+1 > len(cave[0])-1: 39 | stopAll = 1 40 | sandCount -= 1 41 | elif cave[curX][curY+1] == '.': 42 | curY += 1 43 | elif cave[curX-1][curY+1] == '.': 44 | curX -= 1 45 | curY += 1 46 | elif cave[curX+1][curY+1] == '.': 47 | curX += 1 48 | curY += 1 49 | else: 50 | break 51 | cave[curX][curY] = 'o' 52 | sandCount += 1 53 | if cave[500][0] == 'o': 54 | stopAll = 1 55 | 56 | print('Day 14 Part 1:', sandCount) 57 | 58 | # Part 2 59 | cave = caveSetup() 60 | cave = [['.' for _ in range(len(cave[0]))] for _ in range(len(cave[0])+1)] + cave + [['.' for _ in range(len(cave[0]))] for _ in range(len(cave[0])+1)] 61 | [c.extend(['.', '#']) for c in cave] 62 | stopAll = 0 63 | sandCount = 0 64 | while not stopAll: 65 | curX, curY = 500+len(cave[0]), 0 66 | for _ in range(len(cave[0])): 67 | if curY+1 >= len(cave[0]): 68 | break 69 | elif cave[curX][curY+1] == '.': 70 | curY += 1 71 | elif cave[curX-1][curY+1] == '.': 72 | curX -= 1 73 | curY += 1 74 | elif cave[curX+1][curY+1] == '.': 75 | curX += 1 76 | curY += 1 77 | else: 78 | break 79 | cave[curX][curY] = 'o' 80 | sandCount += 1 81 | if cave[500+len(cave[0])][0] == 'o': 82 | stopAll = 1 83 | 84 | print('Day 14 Part 2:', sandCount) 85 | 86 | 87 | # One-line Solutions 88 | print('Day 14 Part 1:', sandCount if [(not (cave := [])) and [(l != len(row)-1 and ((len(cave) == 0 and cave.extend(list(list()) for _ in range(max(line[0], row[l+1][0])+1)) or 1) and (0 < len(cave) <= max(line[0], row[l+1][0]) and cave.extend([['.' for _ in range(len(cave[0]))] for _ in range(max(line[0], row[l+1][0])-len(cave)+2)]) or 1) and (line[0] == row[l+1][0] and [(len(cave[0]) <= a and [c.extend(['.' for _ in range(a-len(c)+2)]) for c in cave] or 1) and (cave[line[0]].pop(a) and cave[line[0]].insert(a, '#')) for a in range(min(line[1], row[l+1][1]), max(line[1], row[l+1][1])+1)]) or [cave[b].pop(line[1]) and cave[b].insert(line[1], '#') for b in range(min(line[0], row[l+1][0]), max(line[0], row[l+1][0])+1)])) for row in [[list(map(int, z.split(','))) for z in y] for y in [x.split(' -> ') for x in open('inputs/day-14.txt').read().split('\n')]] for l, line in enumerate(row)] and [(not stopAll) and ((curX := 500) and not (curY := 0)) and [(curY+1 > len(cave[0])-1 and (stopAll := 1) and (sandCount := sandCount-1)) or (curY+1 > len(cave[0])-1) or (cave[curX][curY+1] == '.' and (curY := curY+1)) or (cave[curX-1][curY+1] == '.' and (curX := curX-1) and (curY := curY+1)) or (cave[curX+1][curY+1] == '.' and (curX := curX+1) and (curY := curY+1)) for _ in range(len(cave[0]))] and (cave[curX].pop(curY) and not cave[curX].insert(curY, 'o') and (sandCount := sandCount+1)) for _ in range(len(cave[0])*5)] if (not (stopAll := 0) and not (sandCount := 0)) else ''] else '') 89 | print('Day 14 Part 2:', sandCount if [((not (cave := [])) and [(l != len(row)-1 and ((len(cave) == 0 and cave.extend(list(list()) for _ in range(max(line[0], row[l+1][0])+1)) or 1) and (0 < len(cave) <= max(line[0], row[l+1][0]) and cave.extend([['.' for _ in range(len(cave[0]))] for _ in range(max(line[0], row[l+1][0])-len(cave)+2)]) or 1) and (line[0] == row[l+1][0] and [(len(cave[0]) <= a and [c.extend(['.' for _ in range(a-len(c)+2)]) for c in cave] or 1) and (cave[line[0]].pop(a) and cave[line[0]].insert(a, '#')) for a in range(min(line[1], row[l+1][1]), max(line[1], row[l+1][1])+1)]) or [cave[b].pop(line[1]) and cave[b].insert(line[1], '#') for b in range(min(line[0], row[l+1][0]), max(line[0], row[l+1][0])+1)])) for row in [[list(map(int, z.split(','))) for z in y] for y in [x.split(' -> ') for x in open('inputs/day-14.txt').read().split('\n')]] for l, line in enumerate(row)]) and (cave := [['.' for _ in range(len(cave[0]))] for _ in range(len(cave[0])+1)] + cave + [['.' for _ in range(len(cave[0]))] for _ in range(len(cave[0])+1)]) and [c.extend(['.', '#']) for c in cave] and [(not stopAll) and ((curX := 500+len(cave[0])) and not (curY := 0)) and [(curY+1 >= len(cave[0])) or (cave[curX][curY+1] == '.' and (curY := curY+1)) or (cave[curX-1][curY+1] == '.' and ((curX := curX-1) or 1) and (curY := curY+1)) or (cave[curX+1][curY+1] == '.' and (curX := curX+1) and (curY := curY+1)) for _ in range(len(cave[0]))] and (cave[curX].pop(curY) and not cave[curX].insert(curY, 'o') and (sandCount := sandCount+1) and (cave[500+len(cave[0])][0] == 'o' and (stopAll := 1))) for _ in range(len(cave[0])*500)] if (not (stopAll := 0) and not (sandCount := 0)) else ''] else '') -------------------------------------------------------------------------------- /2022/one-line-solutions.py: -------------------------------------------------------------------------------- 1 | # Day 01 2 | print('Day 01 Part 1:', max([sum([int(x) for x in g]) for g in [group.split('\n') for group in open('inputs/day-01.txt').read().split('\n\n')]])) 3 | print('Day 01 Part 2:', sum(sorted([sum([int(x) for x in g]) for g in [group.split('\n') for group in open('inputs/day-01.txt').read().split('\n\n')]], reverse=True)[0:3])) 4 | 5 | # Day 02 6 | print('Day 02 Part 1:', sum([{'A X':3+1,'A Y':6+2,'A Z':0+3,'B X':0+1,'B Y':3+2,'B Z':6+3,'C X':6+1,'C Y':0+2,'C Z':3+3}[x] for x in open('inputs/day-02.txt').read().split('\n')])) 7 | print('Day 02 Part 2:', sum([{'A X':0+3,'A Y':3+1,'A Z':6+2,'B X':0+1,'B Y':3+2,'B Z':6+3,'C X':0+2,'C Y':3+3,'C Z':6+1}[x] for x in open('inputs/day-02.txt').read().split('\n')])) 8 | 9 | # Day 03 10 | print('Day 03 Part 1:', sum([ord(x)-96 if x.islower() else ord(x)-38 for x in [set(x).intersection(y).pop() for x, y in [[i[:len(i)//2], i[len(i)//2:]] for i in open('inputs/day-03.txt').read().split('\n')]]])) 11 | print('Day 03 Part 2:', sum([ord(x)-96 if x.islower() else ord(x)-38 for x in [set(open('inputs/day-03.txt').read().split('\n')[i]).intersection(open('inputs/day-03.txt').read().split('\n')[i+1]).intersection(open('inputs/day-03.txt').read().split('\n')[i+2]).pop() for i in range(0,len(open('inputs/day-03.txt').read().split('\n')),3)]])) 12 | 13 | # Day 04 14 | print('Day 04 Part 1:', sum([(n[0][0] >= n[1][0] and n[0][1] <= n[1][1]) or (n[0][0] <= n[1][0] and n[0][1] >= n[1][1]) for n in [[[int(x) for x in a.split('-')], [int(y) for y in b.split('-')]] for a, b in [x.split(',') for x in open('inputs/day-04.txt').read().split('\n')]]])) 15 | print('Day 04 Part 2:', sum([n[0][0] <= n[1][1] and n[0][1] >= n[1][0] for n in [[[int(x) for x in a.split('-')], [int(y) for y in b.split('-')]] for a, b in [x.split(',') for x in open('inputs/day-04.txt').read().split('\n')]]])) 16 | 17 | # Day 05 - This one is a bit cheese but I'm doing my best. Requires Python 3.8 (https://peps.python.org/pep-0572/) 18 | print('Day 05 Part 1:', ''.join([c[0] for c in crates] if not (input := open('inputs/day-05.txt').read().split('\n')) or not (moves := [[int(x[1]), int(x[3]), int(x[5])] for x in [y.split(' ') for y in input[10:]]]) or not (crates := [[] for i in range(9)]) or not [crates[j//4].append(line[j]) for line in input[:8] for j in range(1,len(line),4) if line[j].isalpha()] or [crates[move[2]-1].insert(0, crates[move[1]-1].pop(0)) for move in moves for n in range(move[0])] else '')) 19 | print('Day 05 Part 2:', ''.join([c[0] for c in crates] if not (input := open('inputs/day-05.txt').read().split('\n')) or not (moves := [[int(x[1]), int(x[3]), int(x[5])] for x in [y.split(' ') for y in input[10:]]]) or not (crates := [[] for i in range(9)]) or not [crates[j//4].append(line[j]) for line in input[:8] for j in range(1,len(line),4) if line[j].isalpha()] or [crates[move[2]-1].insert(0, item) for move in moves for item in reversed([crates[move[1]-1].pop(0) for n in range(move[0])])] else '')) 20 | 21 | # Day 06 22 | print('Day 06 Part 1:', [i+1 for x in [open('inputs/day-06.txt').read()] for i in range(3,len(x)) if len(set(x[i-3:i+1])) == 4][0]) 23 | print('Day 06 Part 2:', [i+1 for x in [open('inputs/day-06.txt').read()] for i in range(13,len(x)) if len(set(x[i-13:i+1])) == 14][0]) 24 | 25 | # Day 07 - Even more cheese. But we got it! 26 | print('Day 07 Part 1:', sum([x for x in dirs.values() if x <= 100000] if not (dirs := {}) and not (curDirs := []) and [((l[0] == '$' and l[1] == 'cd') and (((l[2] == '/') and (curDirs := ['//']) and not (dirs.update({'//':0}))) or (l[2] == '..' and curDirs.pop()) or ((curDir := '/'.join(curDirs) + '/' + l[2]) and not curDirs.append(curDir) and (not dirs.get(curDir) and not dirs.update({curDir:0}))))) or (l[0].isdigit() and [dirs.update({d: dirs[d] + int(l[0])}) for d in curDirs]) for l in [c.split(' ') for c in open('inputs/day-07.txt').read().split('\n')]] else '')) 27 | print('Day 07 Part 2:', min([x for x in dirs.values() if x > dirs['//']-40000000]) if not (dirs := {}) and not (curDirs := []) and [((l[0] == '$' and l[1] == 'cd') and (((l[2] == '/') and (curDirs := ['//']) and not (dirs.update({'//':0}))) or (l[2] == '..' and curDirs.pop()) or ((curDir := '/'.join(curDirs) + '/' + l[2]) and not curDirs.append(curDir) and (not dirs.get(curDir) and not dirs.update({curDir:0}))))) or (l[0].isdigit() and [dirs.update({d: dirs[d] + int(l[0])}) for d in curDirs]) for l in [c.split(' ') for c in open('inputs/day-07.txt').read().split('\n')]] else '') 28 | 29 | # Day 08 - Oh boy, I've started cheesing in my OG solutions now too. 30 | print('Day 08 Part 1:', sum([not bool([x for x in t[r][:c] if x >= t[r][c]] and [x for x in t[r][c+1:] if x >= t[r][c]] and [x[c] for i, x in enumerate(t) if x[c] >= t[r][c] and i < r] and [x[c] for i, x in enumerate(t) if x[c] >= t[r][c] and i > r]) for t in [[[int(y) for y in x] for x in open('inputs/day-08.txt').read().split('\n')]] for r in range(len(t)) for c in range(len(t[r]))])) 31 | print('Day 08 Part 2:', max([sum([(x < t[r][c]) or (found:=True) for x in t[r][:c][::-1] if not found] if not (found:=False) else '') * sum([(x < t[r][c]) or (found:=True) for x in t[r][c+1:] if not found] if not (found:=False) else '') * sum([(x[c] < t[r][c]) or (found:=True) for i, x in reversed(list(enumerate(t))) if not found and i < r] if not (found:=False) else '') * sum([(x[c] < t[r][c]) or (found:=True) for i, x in enumerate(t) if not found and i > r] if not (found:=False) else '') for t in [[[int(y) for y in x] for x in open('inputs/day-08.txt').read().split('\n')]] for r in range(len(t)) for c in range(len(t[r]))])) 32 | 33 | # Day 09 - Today's solution is brought to you by x.insert(0, x.pop(0)+1) 34 | print('Day 09 Part 1:', len(visited) if (visited := {(0,0)}) and (h := [0,0]) and (t := [0,0]) and [((d == 'R' and ((t[1] == h[1] and t[0] == h[0]-1 and (t.insert(0, t.pop(0)+1))) or (t[1] > h[1] and t[0] == h[0]-1 and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)-1))) or (t[1] < h[1] and t[0] == h[0]-1 and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)+1))) or 1) and not h.insert(0, h.pop(0)+1)) or (d == 'L' and ((t[1] == h[1] and t[0] == h[0]+1 and (t.insert(0, t.pop(0)-1))) or (t[1] > h[1] and t[0] == h[0]+1 and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)-1))) or (t[1] < h[1] and t[0] == h[0]+1 and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)+1))) or 1) and not h.insert(0, h.pop(0)-1)) or (d == 'U' and ((t[1] == h[1]-1 and t[0] == h[0] and (t.insert(1, t.pop(1)+1))) or (t[1] == h[1]-1 and t[0] < h[0] and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)+1))) or (t[1] == h[1]-1 and t[0] > h[0] and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)+1))) or 1) and h.insert(1, h.pop(1)+1)) or (d == 'D' and ((t[1] == h[1]+1 and t[0] == h[0] and (t.insert(1, t.pop(1)-1))) or (t[1] == h[1]+1 and t[0] < h[0] and not (t.insert(0, t.pop(0)+1) or t.insert(1, t.pop(1)-1))) or (t[1] == h[1]+1 and t[0] > h[0] and not (t.insert(0, t.pop(0)-1) or t.insert(1, t.pop(1)-1))) or 1) and not h.insert(1, h.pop(1)-1)) or 1) and (visited.add(tuple(t))) for d, n in (x.split(' ') for x in open('inputs/day-09.txt').read().split('\n')) for _ in range(int(n))] else '') 35 | print('Day 09 Part 2:', len(visited) if (visited := {(0,0)}) and (s := [[0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0], [0,0]]) and [not ((d == 'R' and s[0].insert(0, s[0].pop(0)+1)) or (d == 'L' and s[0].insert(0, s[0].pop(0)-1)) or (d == 'U' and s[0].insert(1, s[0].pop(1)+1)) or (d == 'D' and s[0].insert(1, s[0].pop(1)-1))) and [(s[i][0] < s[i-1][0]-1 and ((s[i][1] == s[i-1][1] and (s[i].insert(0, s[i].pop(0)+1))) or (s[i][1] > s[i-1][1] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)-1))) or (s[i][1] < s[i-1][1] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)+1))))) or (s[i][0] > s[i-1][0]+1 and ((s[i][1] == s[i-1][1] and (s[i].insert(0, s[i].pop(0)-1))) or (s[i][1] > s[i-1][1] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)-1))) or (s[i][1] < s[i-1][1] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)+1))))) or (s[i][1] < s[i-1][1]-1 and ((s[i][0] == s[i-1][0] and (s[i].insert(1, s[i].pop(1)+1))) or (s[i][0] < s[i-1][0] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)+1))) or (s[i][0] > s[i-1][0] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)+1))))) or (s[i][1] > s[i-1][1]+1 and ((s[i][0] == s[i-1][0] and (s[i].insert(1, s[i].pop(1)-1))) or (s[i][0] < s[i-1][0] and not (s[i].insert(0, s[i].pop(0)+1) or s[i].insert(1, s[i].pop(1)-1))) or (s[i][0] > s[i-1][0] and not (s[i].insert(0, s[i].pop(0)-1) or s[i].insert(1, s[i].pop(1)-1))))) for i in range(1,10)] and (visited.add(tuple(s[9]))) for d, n in (x.split(' ') for x in open('inputs/day-09.txt').read().split('\n')) for _ in range(int(n))] else '') 36 | 37 | # Day 10 38 | print('Day 10 Part 1:', sum(signalStrengths) if not (signalStrengths := []) and (x := 1) and not (cycle := 0) and [[(c[0] == 'addx') and [(cycle := cycle+1) and ((cycle+20) % 40 == 0 and signalStrengths.append(cycle*x)) for _ in range(2)] and (x := x+int(c[1]))] and [(c[0] == 'noop') and [(cycle := cycle+1) and ((cycle+20) % 40 == 0 and signalStrengths.append(cycle*x))]] for c in [y.split(' ') for y in open('inputs/day-10.txt').read().split('\n')]] else '') 39 | print('Day 10 Part 2:\n',''.join(v[:-1]) if not (v := []) and (x := 1) and not (cycle := 0) and (sprite := ['#']*3 + ['.']*37) and not (crt := []) and [((c[0] == 'addx' and [(cycle := cycle+1) and ([crt.append('#' if sprite[cycle-((cycle//40)*40)-1] == '#' else '.')] or 1) for _ in range(2)] and ((x := x+int(c[1])) or 1) and (sprite := ['.']*40) and [sprite.pop(i) and sprite.insert(i, '#') for i in range(x-1,x+2) if i < 40 and i >= 0]) or (c[0] == 'noop' and [(cycle := cycle+1) and crt.append('#' if sprite[cycle-((cycle//40)*40)-1] == '#' else '.')])) for c in [y.split(' ') for y in open('inputs/day-10.txt').read().split('\n')]] and [not v.append(p) and ((i+1) % 40 == 0 and v.append('\n')) for i, p in enumerate(crt)] else '', sep='') 40 | 41 | # Day 11 42 | print('Day 11 Part 1:',inspectionCount[0] * inspectionCount[1] if (monkeys := [[list(map(int,[a.replace(',','') for a in mon[0][4:]])), (mon[1][6] == '*' and ((mon[1][7] == 'old' and (lambda a: a * a)) or (lambda a, n=int(mon[1][7]): a * n))) or ((mon[1][6] == '+' and ((mon[1][7] == 'old' and (lambda a: a + a)) or (lambda a, n=int(mon[1][7]): a + n)))), int(mon[2][5]), int(mon[3][9]), int(mon[4][9]), 0] for mon in [[z.split(' ') for z in y[1:]] for y in [x.split('\n') for x in open('inputs/day-11.txt').read().split('\n\n')]]]) and [[[not (m.insert(5, m.pop(5)+1)) and ((m[1](i) // 3 % m[2] == 0 and not monkeys[m[3]][0].append(m[1](i) // 3)) or not monkeys[m[4]][0].append(m[1](i) // 3)) for i in m[0]] and (not m.insert(1,[]) and m.pop(0)) for m in monkeys] for _ in range(20)] and (inspectionCount := sorted([k[5] for k in monkeys], reverse=True)) else '') 43 | print('Day 11 Part 2:',inspectionCount[0] * inspectionCount[1] if (monkeys := [[list(map(int,[a.replace(',','') for a in mon[0][4:]])), (mon[1][6] == '*' and ((mon[1][7] == 'old' and (lambda a: a * a)) or (lambda a, n=int(mon[1][7]): a * n))) or ((mon[1][6] == '+' and ((mon[1][7] == 'old' and (lambda a: a + a)) or (lambda a, n=int(mon[1][7]): a + n)))), int(mon[2][5]), int(mon[3][9]), int(mon[4][9]), 0] for mon in [[z.split(' ') for z in y[1:]] for y in [x.split('\n') for x in open('inputs/day-11.txt').read().split('\n\n')]]]) and (lcm := 1) and ([lcm := lcm * k[2] for k in monkeys]) and [[[not (m.insert(5, m.pop(5)+1)) and (((m[1](i) % lcm) % m[2] == 0 and not monkeys[m[3]][0].append(m[1](i) % lcm)) or not monkeys[m[4]][0].append(m[1](i) % lcm)) for i in m[0]] and (not m.insert(1,[]) and m.pop(0)) for m in monkeys] for _ in range(10000)] and (inspectionCount := sorted([k[5] for k in monkeys], reverse=True)) else '') 44 | 45 | # Day 12 - WIP 46 | 47 | # Day 13 - WIP 48 | 49 | # Day 14 50 | print('Day 14 Part 1:', sandCount if [(not (cave := [])) and [(l != len(row)-1 and ((len(cave) == 0 and cave.extend(list(list()) for _ in range(max(line[0], row[l+1][0])+1)) or 1) and (0 < len(cave) <= max(line[0], row[l+1][0]) and cave.extend([['.' for _ in range(len(cave[0]))] for _ in range(max(line[0], row[l+1][0])-len(cave)+2)]) or 1) and (line[0] == row[l+1][0] and [(len(cave[0]) <= a and [c.extend(['.' for _ in range(a-len(c)+2)]) for c in cave] or 1) and (cave[line[0]].pop(a) and cave[line[0]].insert(a, '#')) for a in range(min(line[1], row[l+1][1]), max(line[1], row[l+1][1])+1)]) or [cave[b].pop(line[1]) and cave[b].insert(line[1], '#') for b in range(min(line[0], row[l+1][0]), max(line[0], row[l+1][0])+1)])) for row in [[list(map(int, z.split(','))) for z in y] for y in [x.split(' -> ') for x in open('inputs/day-14.txt').read().split('\n')]] for l, line in enumerate(row)] and [(not stopAll) and ((curX := 500) and not (curY := 0)) and [(curY+1 > len(cave[0])-1 and (stopAll := 1) and (sandCount := sandCount-1)) or (curY+1 > len(cave[0])-1) or (cave[curX][curY+1] == '.' and (curY := curY+1)) or (cave[curX-1][curY+1] == '.' and (curX := curX-1) and (curY := curY+1)) or (cave[curX+1][curY+1] == '.' and (curX := curX+1) and (curY := curY+1)) for _ in range(len(cave[0]))] and (cave[curX].pop(curY) and not cave[curX].insert(curY, 'o') and (sandCount := sandCount+1)) for _ in range(len(cave[0])*5)] if (not (stopAll := 0) and not (sandCount := 0)) else ''] else '') 51 | print('Day 14 Part 2:', sandCount if [((not (cave := [])) and [(l != len(row)-1 and ((len(cave) == 0 and cave.extend(list(list()) for _ in range(max(line[0], row[l+1][0])+1)) or 1) and (0 < len(cave) <= max(line[0], row[l+1][0]) and cave.extend([['.' for _ in range(len(cave[0]))] for _ in range(max(line[0], row[l+1][0])-len(cave)+2)]) or 1) and (line[0] == row[l+1][0] and [(len(cave[0]) <= a and [c.extend(['.' for _ in range(a-len(c)+2)]) for c in cave] or 1) and (cave[line[0]].pop(a) and cave[line[0]].insert(a, '#')) for a in range(min(line[1], row[l+1][1]), max(line[1], row[l+1][1])+1)]) or [cave[b].pop(line[1]) and cave[b].insert(line[1], '#') for b in range(min(line[0], row[l+1][0]), max(line[0], row[l+1][0])+1)])) for row in [[list(map(int, z.split(','))) for z in y] for y in [x.split(' -> ') for x in open('inputs/day-14.txt').read().split('\n')]] for l, line in enumerate(row)]) and (cave := [['.' for _ in range(len(cave[0]))] for _ in range(len(cave[0])+1)] + cave + [['.' for _ in range(len(cave[0]))] for _ in range(len(cave[0])+1)]) and [c.extend(['.', '#']) for c in cave] and [(not stopAll) and ((curX := 500+len(cave[0])) and not (curY := 0)) and [(curY+1 >= len(cave[0])) or (cave[curX][curY+1] == '.' and (curY := curY+1)) or (cave[curX-1][curY+1] == '.' and ((curX := curX-1) or 1) and (curY := curY+1)) or (cave[curX+1][curY+1] == '.' and (curX := curX+1) and (curY := curY+1)) for _ in range(len(cave[0]))] and (cave[curX].pop(curY) and not cave[curX].insert(curY, 'o') and (sandCount := sandCount+1) and (cave[500+len(cave[0])][0] == 'o' and (stopAll := 1))) for _ in range(len(cave[0])*500)] if (not (stopAll := 0) and not (sandCount := 0)) else ''] else '') -------------------------------------------------------------------------------- /2022/the-beast.py: -------------------------------------------------------------------------------- 1 | # Adding file variables to easily test against other inputs. 2 | # Can easily be hard-coded to make it truly one line. 3 | q = { 4 | 1 : 'inputs/day-01.txt', 5 | 2 : 'inputs/day-02.txt', 6 | 3 : 'inputs/day-03.txt', 7 | 4 : 'inputs/day-04.txt', 8 | 5 : 'inputs/day-05.txt', 9 | 6 : 'inputs/day-06.txt', 10 | 7 : 'inputs/day-07.txt', 11 | 8 : 'inputs/day-08.txt', 12 | 9 : 'inputs/day-09.txt', 13 | 10 : 'inputs/day-10.txt', 14 | 11 : 'inputs/day-11.txt', 15 | # TODO: Day 12 16 | # TODO: Day 13 17 | 14 : 'inputs/day-14.txt', 18 | } 19 | 20 | # I'm sorry. 21 | print('Day 01 Part 1: ',max([sum([int(x)for x in g])for g in[k.split('\n')for k in open(q[1]).read().split('\n\n')]]),'\nDay 01 Part 2: ',sum(sorted([sum([int(x)for x in g])for g in[k.split('\n')for k in open(q[1]).read().split('\n\n')]],reverse=1)[0:3]),'\nDay 02 Part 1: ',sum([{'A X':4,'A Y':8,'A Z':3,'B X':1,'B Y':5,'B Z':9,'C X':7,'C Y':2,'C Z':6}[x]for x in open(q[2]).read().split('\n')]),'\nDay 02 Part 2: ',sum([{'A X':3,'A Y':4,'A Z':8,'B X':1,'B Y':5,'B Z':9,'C X':2,'C Y':6,'C Z':7}[x]for x in open(q[2]).read().split('\n')]),'\nDay 03 Part 1: ',sum([ord(x)-96 if x.islower() else ord(x)-38 for x in[set(x).intersection(y).pop()for x,y in[[i[:len(i)//2],i[len(i)//2:]]for i in open(q[3]).read().split('\n')]]]),'\nDay 03 Part 2: ',sum([ord(x)-96 if x.islower() else ord(x)-38 for x in[set(open(q[3]).read().split('\n')[i]).intersection(open(q[3]).read().split('\n')[i+1]).intersection(open(q[3]).read().split('\n')[i+2]).pop()for i in range(0,len(open(q[3]).read().split('\n')),3)]]),'\nDay 04 Part 1: ',sum([(n[0][0]>=n[1][0]and n[0][1]<=n[1][1])or(n[0][0]<=n[1][0]and n[0][1]>=n[1][1])for n in[[[int(x)for x in a.split('-')],[int(y)for y in b.split('-')]]for a,b in[x.split(',')for x in open(q[4]).read().split('\n')]]]),'\nDay 04 Part 2: ',sum([n[0][0]<=n[1][1]and n[0][1]>=n[1][0]for n in[[[int(x)for x in a.split('-')],[int(y)for y in b.split('-')]]for a,b in[x.split(',')for x in open(q[4]).read().split('\n')]]]),'\nDay 05 Part 1: ',''.join([c[0]for c in k] if not(f:=open(q[5]).read().split('\n'))or not(t:=[[int(x[1]),int(x[3]),int(x[5])]for x in[y.split(' ')for y in f[10:]]])or not(k:=[[]for i in range(9)])or not[k[j//4].append(l[j])for l in f[:8]for j in range(1,len(l),4) if l[j].isalpha()]or[k[p[2]-1].insert(0,k[p[1]-1].pop(0))for p in t for _ in range(p[0])] else ''),'\nDay 05 Part 2: ',''.join([c[0]for c in k] if not(f:=open(q[5]).read().split('\n'))or not(t:=[[int(x[1]),int(x[3]),int(x[5])]for x in[y.split(' ')for y in f[10:]]])or not(k:=[[]for _ in range(9)])or not[k[j//4].append(l[j])for l in f[:8]for j in range(1,len(l),4) if l[j].isalpha()]or[k[p[2]-1].insert(0,e)for p in t for e in reversed([k[p[1]-1].pop(0)for _ in range(p[0])])] else ''),'\nDay 06 Part 1: ',[i+1 for x in[open(q[6]).read()]for i in range(3,len(x)) if len(set(x[i-3:i+1]))==4][0],'\nDay 06 Part 2: ',[i+1 for x in[open(q[6]).read()]for i in range(13,len(x)) if len(set(x[i-13:i+1]))==14][0],'\nDay 07 Part 1: ',sum([x for x in u.values() if x<=100000] if not(u:={})and not(g:=[])and[((l[0]=='$'and l[1]=='cd')and(((l[2]=='/')and(g:=['//'])and not(u.update({'//':0})))or(l[2]=='..'and g.pop())or((h:='/'.join(g)+'/'+l[2])and not g.append(h)and(not u.get(h)and not u.update({h:0})))))or(l[0].isdigit()and[u.update({d:u[d]+int(l[0])})for d in g])for l in[c.split(' ')for c in open(q[7]).read().split('\n')]] else ''),'\nDay 07 Part 2: ',min([x for x in u.values() if x>u['//']-40000000]) if not(u:={})and not(g:=[])and[((l[0]=='$'and l[1]=='cd')and(((l[2]=='/')and(g:=['//'])and not(u.update({'//':0})))or(l[2]=='..'and g.pop())or((h:='/'.join(g)+'/'+l[2])and not g.append(h)and(not u.get(h)and not u.update({h:0})))))or(l[0].isdigit()and[u.update({d:u[d]+int(l[0])})for d in g])for l in[c.split(' ')for c in open(q[7]).read().split('\n')]] else '','\nDay 08 Part 1: ',sum([not bool([x for x in t[r][:c] if x>=t[r][c]]and[x for x in t[r][c+1:] if x>=t[r][c]]and[x[c]for i,x in enumerate(t) if x[c]>=t[r][c]and i=t[r][c]and i>r])for t in[[[int(y)for y in x]for x in open(q[8]).read().split('\n')]]for r in range(len(t))for c in range(len(t[r]))]),'\nDay 08 Part 2: ',max([sum([(xr] if not(e:=False) else '')for t in[[[int(y)for y in x]for x in open(q[8]).read().split('\n')]]for r in range(len(t))for c in range(len(t[r]))]),'\nDay 09 Part 1: ',len(v)if(v:={(0,0)})and(r:=[0,0])and(w:=[0,0])and[((d=='R'and((w[1]==r[1]and w[0]==r[0]-1 and(w.insert(0,w.pop(0)+1)))or(w[1]>r[1]and w[0]==r[0]-1 and not(w.insert(0,w.pop(0)+1)or w.insert(1,w.pop(1)-1)))or(w[1]r[1]and w[0]==r[0]+1 and not(w.insert(0,w.pop(0)-1)or w.insert(1,w.pop(1)-1)))or(w[1]r[0]and not(w.insert(0,w.pop(0)-1)or w.insert(1,w.pop(1)+1)))or 1)and r.insert(1,r.pop(1)+1))or(d=='D'and((w[1]==r[1]+1 and w[0]==r[0]and(w.insert(1,w.pop(1)-1)))or(w[1]==r[1]+1 and w[0]r[0]and not(w.insert(0,w.pop(0)-1)or w.insert(1,w.pop(1)-1)))or 1)and not r.insert(1,r.pop(1)-1))or 1)and(v.add(tuple(w)))for d,n in(x.split(' ')for x in open(q[9]).read().split('\n'))for _ in range(int(n))] else '','\nDay 09 Part 2: ',len(v)if(v:={(0,0)})and(s:=[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]])and[not((d=='R'and s[0].insert(0,s[0].pop(0)+1))or(d=='L'and s[0].insert(0,s[0].pop(0)-1))or(d=='U'and s[0].insert(1,s[0].pop(1)+1))or(d=='D'and s[0].insert(1,s[0].pop(1)-1)))and[(s[i][0]s[i-1][1]and not(s[i].insert(0,s[i].pop(0)+1)or s[i].insert(1,s[i].pop(1)-1)))or(s[i][1]s[i-1][0]+1 and((s[i][1]==s[i-1][1]and(s[i].insert(0,s[i].pop(0)-1)))or(s[i][1]>s[i-1][1]and not(s[i].insert(0,s[i].pop(0)-1)or s[i].insert(1,s[i].pop(1)-1)))or(s[i][1]s[i-1][0]and not(s[i].insert(0,s[i].pop(0)-1)or s[i].insert(1,s[i].pop(1)+1)))))or(s[i][1]>s[i-1][1]+1 and((s[i][0]==s[i-1][0]and(s[i].insert(1,s[i].pop(1)-1)))or(s[i][0]s[i-1][0]and not(s[i].insert(0,s[i].pop(0)-1)or s[i].insert(1,s[i].pop(1)-1)))))or 1 for i in range(1,10)]and(v.add(tuple(s[9])))for d,n in(x.split(' ')for x in open(q[9]).read().split('\n'))for _ in range(int(n))] else '','\nDay 10 Part 1: ',sum(s) if not(s:=[])and(x:=1)and not(u:=0)and[[(c[0]=='addx')and[(u:=u+1)and((u+20)%40==0 and s.append(u*x))for _ in range(2)]and(x:=x+int(c[1]))]and[(c[0]=='noop')and[(u:=u+1)and((u+20)%40==0 and s.append(u*x))]]for c in[y.split(' ')for y in open(q[10]).read().split('\n')]] else '','\nDay 10 Part 2:\n',''.join(v[:-1]) if not(v:=[])and(x:=1)and not(e:=0 )and(s:=['#']*3+['.']*37)and not(t:=[])and[((c[0]=='addx'and[(e:=e+1)and([t.append('#' if s[e-((e//40)*40)-1]=='#' else '.')]or 1)for _ in range(2)]and((x:=x+int(c[1]))or 1)and(s:=['.']*40)and[s.pop(i)and s.insert(i,'#')for i in range(x-1,x+2) if i<40 and i>=0])or(c[0]=='noop'and[(e:=e+1)and t.append('#' if s[e-((e//40)*40)-1]=='#' else '.')]))for c in[y.split(' ')for y in open(q[10]).read().split('\n')]]and[not v.append(p)and((i+1)%40==0 and v.append('\n'))for i,p in enumerate(t)] else '','\nDay 11 Part 1: ',c[0]*c[1]if(f:=[[list(map(int,[a.replace(',','')for a in o[0][4:]])),(o[1][6]=='*'and((o[1][7]=='old'and(lambda a:a*a))or(lambda a,n=int(o[1][7]):a*n)))or((o[1][6]=='+'and((o[1][7]=='old'and(lambda a:a+a))or(lambda a,n=int(o[1][7]):a+n)))),int(o[2][5]),int(o[3][9]),int(o[4][9]),0]for o in[[z.split(' ')for z in y[1:]]for y in[x.split('\n')for x in open(q[11]).read().split('\n\n')]]])and[[[not(m.insert(5,m.pop(5)+1))and((m[1](i)//3%m[2]==0 and not f[m[3]][0].append(m[1](i)//3))or not f[m[4]][0].append(m[1](i)//3))for i in m[0]]and(not m.insert(1,[])and m.pop(0))for m in f]for _ in range(20)]and(c:=sorted([k[5]for k in f],reverse=1)) else '','\nDay 11 Part 2: ',c[0]*c[1]if(f:=[[list(map(int,[a.replace(',','')for a in o[0][4:]])),(o[1][6]=='*'and((o[1][7]=='old'and(lambda a:a*a))or(lambda a,n=int(o[1][7]):a*n)))or((o[1][6]=='+'and((o[1][7]=='old'and(lambda a:a+a))or(lambda a,n=int(o[1][7]):a+n)))),int(o[2][5]),int(o[3][9]),int(o[4][9]),0]for o in[[z.split(' ')for z in y[1:]]for y in[x.split('\n')for x in open(q[11]).read().split('\n\n')]]])and(l:=1)and([l:=l*k[2]for k in f])and[[[not(m.insert(5,m.pop(5)+1))and(((m[1](i)%l)%m[2]==0 and not f[m[3]][0].append(m[1](i)%l))or not f[m[4]][0].append(m[1](i)%l))for i in m[0]]and(not m.insert(1,[])and m.pop(0))for m in f]for _ in range(10000)]and(c:=sorted([k[5]for k in f],reverse=1)) else '','\nDay 14 Part 1: ',s if[(not(v := []))and[(l!=len(o)-1 and((len(v)==0 and v.extend(list(list())for _ in range(max(m[0],o[l+1][0])+1))or 1)and(0 < len(v)<=max(m[0],o[l+1][0])and v.extend([['.'for _ in range(len(v[0]))]for _ in range(max(m[0],o[l+1][0])-len(v)+2)])or 1)and(m[0]==o[l+1][0]and[(len(v[0])<=a and[c.extend(['.'for _ in range(a-len(c)+2)])for c in v]or 1)and(v[m[0]].pop(a)and v[m[0]].insert(a,'#'))for a in range(min(m[1],o[l+1][1]),max(m[1],o[l+1][1])+1)])or[v[b].pop(m[1])and v[b].insert(m[1],'#')for b in range(min(m[0],o[l+1][0]),max(m[0],o[l+1][0])+1)]))for o in [[list(map(int,z.split(',')))for z in y]for y in [x.split(' -> ')for x in open(q[14]).read().split('\n')]]for l,m in enumerate(o)]and[(not w)and((x := 500)and not(y := 0))and[(y+1 > len(v[0])-1 and(w := 1)and(s := s-1))or(y+1 > len(v[0])-1)or(v[x][y+1]=='.'and(y := y+1))or(v[x-1][y+1]=='.'and(x := x-1)and(y := y+1))or(v[x+1][y+1]=='.'and(x := x+1)and(y := y+1))for _ in range(len(v[0]))]and(v[x].pop(y)and not v[x].insert(y,'o')and(s := s+1))for _ in range(len(v[0])*5)]if(not(w := 0)and not(s := 0)) else ''] else '','\nDay 14 Part 2: ',s if[((not(v := []))and[(l!=len(o)-1 and((len(v)==0 and v.extend(list(list())for _ in range(max(m[0],o[l+1][0])+1))or 1)and(0 < len(v)<=max(m[0],o[l+1][0])and v.extend([['.'for _ in range(len(v[0]))]for _ in range(max(m[0],o[l+1][0])-len(v)+2)])or 1)and(m[0]==o[l+1][0]and[(len(v[0])<=a and[c.extend(['.'for _ in range(a-len(c)+2)])for c in v]or 1)and(v[m[0]].pop(a)and v[m[0]].insert(a,'#'))for a in range(min(m[1],o[l+1][1]),max(m[1],o[l+1][1])+1)])or[v[b].pop(m[1])and v[b].insert(m[1],'#')for b in range(min(m[0],o[l+1][0]),max(m[0],o[l+1][0])+1)]))for o in [[list(map(int,z.split(',')))for z in y]for y in [x.split(' -> ')for x in open(q[14]).read().split('\n')]]for l,m in enumerate(o)])and(v := [['.'for _ in range(len(v[0]))]for _ in range(len(v[0])+1)]+v+[['.'for _ in range(len(v[0]))]for _ in range(len(v[0])+1)])and[c.extend(['.','#'])for c in v]and[(not w)and((x := 500+len(v[0]))and not(y := 0))and[(y+1 >= len(v[0]))or(v[x][y+1]=='.'and(y := y+1))or(v[x-1][y+1]=='.'and((x := x-1)or 1)and(y := y+1))or(v[x+1][y+1]=='.'and(x := x+1)and(y := y+1))for _ in range(len(v[0]))]and(v[x].pop(y)and not v[x].insert(y,'o')and(s := s+1)and(v[500+len(v[0])][0]=='o'and(w := 1)))for _ in range(len(v[0])*500)]if(not(w := 0)and not(s := 0)) else ''] else '',sep='') -------------------------------------------------------------------------------- /2023/day-01.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 01 (https://adventofcode.com/2023/day/1) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import re 9 | 10 | # Input files not included in repo per copyright & Eric Wastl's request. 11 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 12 | # Replace with path to your personal input file if you would like to run the code. 13 | input_file = '2023/day-01.txt' 14 | 15 | # To match the format of input files for the Basilisk. 16 | q = { 1: open(input_file).read().strip() } 17 | 18 | 19 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 20 | lines = q[1].split('\n') 21 | calibration = 0 22 | for l in lines: 23 | digits = re.findall(r'\d', l) 24 | calibration += int(digits[0] + digits[-1]) 25 | 26 | print('Day 01 Part 1:', calibration) 27 | 28 | ########################## PART 1: ONE-LINE SOLUTION ########################## 29 | print('Day 01 Part 1:',sum([(d:=re.findall(r'\d',l)) and int(d[0]+d[-1]) for l in q[1].split('\n')])) 30 | 31 | 32 | ######################### PART 2: MULTI-LINE SOLUTION ######################### 33 | lines = q[1].split('\n') 34 | 35 | numbers = { 36 | 'one': '1', 37 | 'two': '2', 38 | 'three': '3', 39 | 'four': '4', 40 | 'five': '5', 41 | 'six': '6', 42 | 'seven': '7', 43 | 'eight': '8', 44 | 'nine': '9', 45 | } 46 | 47 | calibration = 0 48 | for l in lines: 49 | digits = re.findall(r'(?=(\d|one|two|three|four|five|six|seven|eight|nine))', l) 50 | value = ''.join([numbers[d] if d.isalpha() else d for d in [digits[0], digits[-1]]]) 51 | calibration += int(value) 52 | 53 | print('Day 01 Part 2:', calibration) 54 | 55 | ########################## PART 2: ONE-LINE SOLUTION ########################## 56 | print('Day 01 Part 2:',sum([int(''.join([{'one':'1','two':'2','three':'3','four':'4','five':'5','six':'6','seven':'7','eight':'8','nine':'9'}[d] if d.isalpha() else d for d in [n[0], n[-1]]])) for l in q[1].split('\n') for n in [re.findall(r'(?=(\d|one|two|three|four|five|six|seven|eight|nine))', l)]])) 57 | -------------------------------------------------------------------------------- /2023/day-02.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 02 (https://adventofcode.com/2023/day/2) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import re 9 | 10 | # Input files not included in repo per copyright & Eric Wastl's request. 11 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 12 | # Replace with path to your personal input file if you would like to run the code. 13 | input_file = '2023/day-02.txt' 14 | 15 | # To match the format of input files for the Basilisk. 16 | q = { 2: open(input_file).read().strip() } 17 | 18 | 19 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 20 | games = re.findall(r'(\d+):((?: *\d+\s+\w+,?;?)+)', q[2]) 21 | count = sum([int(g[0]) for g in games]) 22 | for g in games: 23 | dice = re.findall(r'(\d+)\s+(\w+)', g[1]) 24 | for d in dice: 25 | n, c = int(d[0]), d[1] 26 | if (n > 12 and c == 'red') or (n > 13 and c == 'green') or (n > 14 and c == 'blue'): 27 | count -= int(g[0]) 28 | break 29 | print('Day 02 Part 1:', count) 30 | 31 | ########################## PART 1: ONE-LINE SOLUTION ########################## 32 | print('Day 02 Part 1:',sum([int(g[0]) for g in re.findall(r'(\d+):((?: *\d+\s+\w+,?;?)+)',q[2])])-sum([int(g[0]) for g in re.findall(r'Game (\d+):((?:\s*\d+\s+\w+,?;?)+)',q[2]) if any([int(d[0])>12 and d[1]=='red' or int(d[0])>13 and d[1]=='green' or int(d[0])>14 and d[1]=='blue' for d in re.findall(r'(\d+)\s+(\w+)',g[1])])])) 33 | 34 | 35 | ######################### PART 2: MULTI-LINE SOLUTION ######################### 36 | games = re.findall(r'(\d+):((?: *\d+\s+\w+,?;?)+)', q[2]) 37 | power = 0 38 | for g in games: 39 | dice = re.findall(r'(\d+)\s+(\w+)', g[1]) 40 | t = {'red': [], 'green': [], 'blue': []} 41 | for d in dice: 42 | n, c = int(d[0]), d[1] 43 | t[c].append(int(n)) 44 | power += max(t['red']) * max(t['green']) * max(t['blue']) 45 | print('Day 02 Part 2:', power) 46 | 47 | ########################## PART 2: ONE-LINE SOLUTION ########################## 48 | print('Day 02 Part 2:',sum([(m:=re.findall(r'(\d+)\s+(\w+)',g[1])) and max([int(d[0]) for d in m if d[1]=='red'])*max([int(d[0]) for d in m if d[1]=='green'])*max([int(d[0]) for d in m if d[1]=='blue']) for g in re.findall(r'(\d+):((?: *\d+\s+\w+,?;?)+)',q[2])])) 49 | -------------------------------------------------------------------------------- /2023/day-03.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 03 (https://adventofcode.com/2023/day/3) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import re 9 | 10 | # Input files not included in repo per copyright & Eric Wastl's request. 11 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 12 | # Replace with path to your personal input file if you would like to run the code. 13 | input_file = '2023/day-03.txt' 14 | 15 | # To match the format of input files for the Basilisk. 16 | q = { 3: open(input_file).read().strip() } 17 | 18 | 19 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 20 | num_coords = [] 21 | symbol_coords = [] 22 | for x, line in enumerate(q[3].split('\n')): 23 | nums = re.finditer(r'\d+', line) 24 | for n in nums: 25 | coords = [] 26 | for i in range(len(n.group())): 27 | coords.append((x, n.start() + i)) 28 | num_coords.append([n.group(), coords]) 29 | symbols = re.finditer(r'[^.\d]', line) 30 | for s in symbols: 31 | symbol_coords.append([s.group(), (x, s.start())]) 32 | adj_nums = [] 33 | for n in num_coords: 34 | for c in n[1]: 35 | for s in symbol_coords: 36 | if abs(c[0] - s[1][0]) <= 1 and abs(c[1] - s[1][1]) <= 1: 37 | adj_nums.append(n) if n not in adj_nums else 0 38 | break 39 | 40 | print('Day 03 Part 1:', sum([int(n[0]) for n in adj_nums])) 41 | 42 | ########################## PART 1: ONE-LINE SOLUTION ########################## 43 | print('Day 03 Part 1:',sum([int(n[0]) for n in [[n.group(),[(x,n.start()+i) for i in range(len(n.group()))]] for x,l in enumerate(q[3].split('\n')) for n in re.finditer(r'\d+',l)] if any([abs(c[0]-s[1][0])<=1 and abs(c[1]-s[1][1])<=1 for c in n[1] for s in [[s.group(),(x, s.start())] for x,l in enumerate(q[3].split('\n')) for s in re.finditer(r'[^.\d]',l)]])])) 44 | 45 | 46 | ######################### PART 2: MULTI-LINE SOLUTION ######################### 47 | num_coords = [] 48 | symbol_coords = [] 49 | for x, line in enumerate(q[3].split('\n')): 50 | nums = re.finditer(r'\d+', line) 51 | for n in nums: 52 | coords = [] 53 | for i in range(len(n.group())): 54 | coords.append((x, n.start() + i)) 55 | num_coords.append([int(n.group()), coords]) 56 | symbols = re.finditer(r'[*]', line) 57 | for s in symbols: 58 | symbol_coords.append([s.group(), (x, s.start()), []]) 59 | for n in num_coords: 60 | for c in n[1]: 61 | for s in symbol_coords: 62 | if abs(c[0] - s[1][0]) <= 1 and abs(c[1] - s[1][1]) <= 1: 63 | s[2].append(n) if n not in s[2] else 0 64 | break 65 | 66 | print('Day 03 Part 2:', sum([s[2][0][0] * s[2][1][0] for s in symbol_coords if len(s[2]) == 2])) 67 | 68 | ########################## PART 2: ONE-LINE SOLUTION ########################## 69 | print('Day 03 Part 2:',(r:=[[s.group(),(x,s.start()),[]] for x,l in enumerate(q[3].split('\n')) for s in re.finditer(r'[*]',l)]) and [s[2].append(n) if n not in s[2] else 0 for n in [[int(n.group()),[(x,n.start()+i) for i in range(len(n.group()))]] for x,l in enumerate(q[3].split('\n')) for n in re.finditer(r'\d+',l)] for c in n[1] for s in r if abs(c[0]-s[1][0])<=1 and abs(c[1]-s[1][1])<=1] and sum([s[2][0][0]*s[2][1][0] for s in r if len(s[2])==2])) -------------------------------------------------------------------------------- /2023/day-04.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 04 (https://adventofcode.com/2023/day/4) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import re 9 | 10 | # Input files not included in repo per copyright & Eric Wastl's request. 11 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 12 | # Replace with path to your personal input file if you would like to run the code. 13 | input_file = '2023/day-04.txt' 14 | 15 | # To match the format of input files for the Basilisk. 16 | q = { 4: open(input_file).read().strip() } 17 | 18 | 19 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 20 | nums = re.findall(r': +((?:\d+\s+)+)\| +((?:\d+\s*)+)', q[4]) 21 | nums = [(set(map(int, n[0].split())), set(map(int, n[1].split()))) for n in nums] 22 | nums = [n[0].intersection(n[1]) for n in nums] 23 | scores = [2 ** (len(n) - 1) if len(n) > 0 else 0 for n in nums] 24 | 25 | print('Day 04 Part 1:', sum(scores)) 26 | 27 | ########################## PART 1: ONE-LINE SOLUTION ########################## 28 | print('Day 04 Part 1:',sum([2**(len(n)-1) if len(n)>0 else 0 for n in [n[0].intersection(n[1]) for n in [(set(map(int,n[0].split())),set(map(int,n[1].split()))) for n in re.findall(r': +((?:\d+\s+)+)\| +((?:\d+\s*)+)',q[4])]]])) 29 | 30 | 31 | ######################### PART 2: MULTI-LINE SOLUTION ######################### 32 | nums = re.findall(r'\d+: +((?:\d+\s+)+)\| +((?:\d+\s*)+)', q[4]) 33 | nums = [(set(map(int, n[0].split())), set(map(int, n[1].split()))) for n in nums] 34 | nums = [[1, len(n[0].intersection(n[1]))] for n in nums] 35 | total_cards = 0 36 | for i, n in enumerate(nums): 37 | total_cards += n[0] 38 | for _ in range(n[0]): 39 | for j in range(1,n[1]+1): 40 | nums[i+j][0] += 1 41 | 42 | print('Day 04 Part 2:', total_cards) 43 | 44 | ########################## PART 2: ONE-LINE SOLUTION ########################## 45 | print('Day 04 Part 2:',((c:=[[1,len(n[0].intersection(n[1]))] for n in [(set(map(int,n[0].split())), set(map(int,n[1].split()))) for n in re.findall(r'\d+: +((?:\d+\s+)+)\| +((?:\d+\s*)+)',q[4])]]) and not (t:=0) and [(t:=t+n[0]) and [c.__setitem__(i+j,[c[i+j][0]+1,c[i+j][1]]) for _ in range(n[0]) for j in range(1,n[1]+1)] for i, n in enumerate(c)] and t)) 46 | -------------------------------------------------------------------------------- /2023/day-05.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 05 (https://adventofcode.com/2023/day/5) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import re 9 | 10 | # Input files not included in repo per copyright & Eric Wastl's request. 11 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 12 | # Replace with path to your personal input file if you would like to run the code. 13 | input_file = '2023/day-05.txt' 14 | 15 | # To match the format of input files for the Basilisk. 16 | q = { 5: open(input_file).read().strip() } 17 | 18 | 19 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 20 | def convert(index, mapping): 21 | closest = min([y for y in mapping if y[1]<=index], default=[0,0,0], key=lambda x: index-x[1]) 22 | if closest[1] + closest[2] > index: 23 | return closest[0] + (index - closest[1]) 24 | return index 25 | 26 | seeds = [] 27 | soil = [] 28 | fertilizer = [] 29 | water = [] 30 | light = [] 31 | temperature = [] 32 | humidity = [] 33 | location = [] 34 | 35 | sections = re.split(r'\n\n', q[5].strip()) 36 | seeds = list(map(int, sections[0].split()[1:])) 37 | for section in sections[1:]: 38 | title, data = re.split(r':\n', section) 39 | data_list = [list(map(int, line.split())) for line in data.split('\n')] 40 | if '-soil' in title: 41 | soil = data_list 42 | elif '-fertilizer' in title: 43 | fertilizer = data_list 44 | elif '-water' in title: 45 | water = data_list 46 | elif '-light' in title: 47 | light = data_list 48 | elif '-temperature' in title: 49 | temperature = data_list 50 | elif '-humidity' in title: 51 | humidity = data_list 52 | elif '-location' in title: 53 | location = data_list 54 | 55 | def seed_to_location(index): 56 | return convert(convert(convert(convert(convert(convert(convert(index, soil), fertilizer), water), light), temperature), humidity), location) 57 | 58 | locs = [seed_to_location(s) for s in seeds] 59 | 60 | print('Day 05 Part 1:',min(locs)) 61 | 62 | ########################## PART 1: ONE-LINE SOLUTION ########################## 63 | print('Day 05 Part 1:',(v:=[[list(map(int,l.split())) for l in d.split('\n')] for d in [d for _,d in [re.split(r':\n',s) for s in re.split(r'\n\n',q[5].strip())[1:]]]]) and (c:=lambda i,m:(lambda c:c[0]+(i-c[1]) if c[1]+c[2]>i else i)(min([y for y in m if y[1]<=i],default=[0,0,0],key=lambda x:i-x[1]))) and min([c(s,v[6])for s in [c(s,v[5]) for s in [c(s,v[4]) for s in [c(s,v[3]) for s in [c(s,v[2]) for s in [c(s,v[1]) for s in [c(s,v[0]) for s in list(map(int,re.split(r'\n\n',q[5].strip())[0].split()[1:]))]]]]]]])) 64 | 65 | 66 | ######################### PART 2: MULTI-LINE SOLUTION ######################### 67 | ########## Credit to Dylan Gray for his help with this solution!! ############# 68 | ####################### https://github.com/DylanDmitri ######################## 69 | sections = re.split(r'\n\n', q[5].strip()) 70 | seeds = list(map(int, sections[0].split()[1:])) 71 | maps = sections[1:] 72 | 73 | current = [(a,a+b) for a,b in zip(seeds[::2], seeds[1::2])] 74 | 75 | for table in maps: 76 | rows = [tuple(map(int, row.split())) for row in table.split('\n')[1:]] 77 | i_start = [-99] 78 | offsets = [0] 79 | latest_end = -99 80 | for row in sorted(rows, key=lambda row: row[1]): 81 | latest_end = max(latest_end, row[1]+row[2]) 82 | offset = row[0] - row[1] 83 | if i_start and i_start[-1] == row[1]: 84 | i_start[-1] = row[1] 85 | offsets[-1] = offset 86 | else: 87 | i_start.append(row[1]) 88 | offsets.append(offset) 89 | i_start.append(row[1]+row[2]) 90 | offsets.append(0) 91 | 92 | out = [] 93 | 94 | for interval in current: 95 | splits = [interval[0]] 96 | start_index = None 97 | for idx, post in enumerate(i_start): 98 | if post <= splits[-1]: 99 | continue 100 | if start_index is None: 101 | start_index = idx - 1 102 | if post < interval[1]: 103 | if post != interval[1]: 104 | splits.append(post) 105 | else: 106 | break 107 | splits.append(interval[1]) 108 | start_index = start_index or len(offsets) 109 | for a,b in zip(splits, splits[1:]): 110 | dx = offsets[min(start_index or float('inf'), len(offsets)-1)] 111 | start_index += 1 112 | out.append((a+dx, b+dx)) 113 | 114 | current = out 115 | 116 | print('Day 05 Part 2:',min(c[0] for c in current)) 117 | 118 | ########################## PART 2: ONE-LINE SOLUTION ########################## 119 | print('Day 05 Part 2:',[(v:=re.split(r'\n\n',q[5].strip())) and (s:=list(map(int,v[0].split()[1:]))) and (m:=v[1:]) and (c:=[(a,a+b) for a,b in zip(s[::2],s[1::2])]) and [[(w:=[tuple(map(int,x.split())) for x in g.split('\n')[1:]]) and (u:=[-99]) and (o:=[0]) and (l:=-99) and [(l:=max(l,(p:=r[0] - r[1])+r[1]+r[2])) and [(not u.__setitem__(-1,r[1]) and not o.__setitem__(-1,p)) if u and u[-1]==r[1] else (u.__iadd__([r[1]])) and o.__iadd__([p])] and (u.__iadd__([r[1]+r[2]]) and o.__iadd__([0])) for r in sorted(w,key=lambda x: x[1])] and not (t:=[]) and [(j:=[i[0]]) and not (h:=None) and [(((h:=d-1) if h is None else 0) and (j.__iadd__([p]) if p < i[1] and p != i[1] else 0) if not p <= j[-1] else 0) for d,p in enumerate(u)] and (j.__iadd__([i[1]]) and (h:=h or len(o))) and [(d:=o[min(h or float('inf'),len(o)-1)]) and (h:=h+1) and t.__iadd__([(a+d,b+d)]) for a,b in zip(j,j[1:])] for i in c]] and (c:=t) for g in m]] and min(x[0] for x in c)) 120 | -------------------------------------------------------------------------------- /2023/day-06.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 06 (https://adventofcode.com/2023/day/6) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import re 9 | from functools import reduce 10 | 11 | # Input files not included in repo per copyright & Eric Wastl's request. 12 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 13 | # Replace with path to your personal input file if you would like to run the code. 14 | input_file = '2023/day-06.txt' 15 | 16 | # To match the format of input files for the Basilisk. 17 | q = { 6: open(input_file).read().strip() } 18 | 19 | 20 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 21 | def solve(b, c): 22 | return [(b+((b**2)-(4*c))**0.5)/2, (b-((b**2)-(4*c))**0.5)/2] 23 | 24 | def num_valid_holds(interval): 25 | num = 0 26 | if interval[0] < interval[1]: 27 | num = int(interval[1]) - int(interval[0]) 28 | else: 29 | num = int(interval[0]) - int(interval[1]) 30 | if interval[0] % 1 == 0: 31 | num -= 1 32 | return num 33 | 34 | nums = [int(n) for n in re.findall(r'\d+', q[6])] 35 | races = [[nums[i], nums[i+int(len(nums)/2)]] for i in range(int(len(nums)/2))] 36 | 37 | total = 1 38 | for r in races: 39 | total *= num_valid_holds(solve(r[0], r[1])) 40 | 41 | print('Day 06 Part 1:',total) 42 | 43 | ########################## PART 1: ONE-LINE SOLUTION ########################## 44 | print('Day 06 Part 1:',(so:=lambda b,c:[(b+((b**2)-(4*c))**0.5)/2,(b-((b**2)-(4*c))**0.5)/2]) and (h:=lambda i:int(i[1])-int(i[0]) if i[0] 0: 54 | return visited 55 | visited.add(move) 56 | return solve(grid, move, pipe_map, visited, (move[0]-pos[0], move[1]-pos[1])) 57 | 58 | start_pos = [(x, y) for y, row in enumerate(grid) for x, char in enumerate(row) if char == 'S'][0] 59 | grid[start_pos[1]][start_pos[0]] = find_start_char(grid, start_pos, pipe_map) 60 | 61 | setrecursionlimit(30000) 62 | print('Day 10 Part 1:',len(solve(grid, start_pos, pipe_map, { start_pos }))//2) 63 | 64 | ########################## PART 1: ONE-LINE SOLUTION ########################## 65 | print('Day 10 Part 1:',(g:=[[x for x in row] for row in q[10].strip().split('\n')],p:={'|':[(0,-1),(0,1)],'-':[(1,0),(-1,0)],'L':[(0,-1),(1,0)],'J':[(0,-1),(-1,0)],'7':[(0,1),(-1,0)],'F':[(0,1),(1,0)],'.':[],'S':[(0,-1),(0,1),(1,0),(-1,0)]},f:=lambda g,c,p,e=None:(r:=g[c[1]][c[0]],s:=p[r],l:=[],[(o:=(c[0]+d[0],c[1]+d[1]),n:=g[o[1]][o[0]],(0<=o[0] 0: 103 | return visited 104 | visited.add(move) 105 | return solve(grid, move, pipe_map, visited, (move[0]-pos[0], move[1]-pos[1])) 106 | 107 | start_pos = [(x, y) for y, row in enumerate(grid) for x, char in enumerate(row) if char == 'S'][0] 108 | grid[start_pos[1]][start_pos[0]] = find_start_char(grid, start_pos, pipe_map) 109 | visited = solve(grid, start_pos, pipe_map, { start_pos }) 110 | 111 | contained = set() 112 | for i in range(len(grid)): 113 | within = 0 114 | for j in range(len(grid[0])): 115 | if (j, i) in visited: 116 | if grid[i][j] in ['|', 'L', 'J']: 117 | within = not within 118 | elif within: 119 | contained.add((j, i)) 120 | 121 | print('Day 10 Part 2:',len(contained)) 122 | 123 | ########################## PART 2: ONE-LINE SOLUTION ########################## 124 | print('Day 10 Part 2:',(g:=[[x for x in row] for row in q[10].strip().split('\n')],p:={'|':[(0,-1),(0,1)],'-':[(1,0),(-1,0)],'L':[(0,-1),(1,0)],'J':[(0,-1),(-1,0)],'7':[(0,1),(-1,0)],'F':[(0,1),(1,0)],'.':[],'S':[(0,-1),(0,1),(1,0),(-1,0)]},f:=lambda g,c,p,e=None:(r:=g[c[1]][c[0]],s:=p[r],l:=[],[(o:=(c[0]+d[0],c[1]+d[1]),n:=g[o[1]][o[0]],(0<=o[0] 0: 70 | if counts and counts[0] == group_loc: 71 | results += count_permutations(symbols[1:], counts[1:]) 72 | else: 73 | results = results + count_permutations(symbols[1:], counts) 74 | return results 75 | 76 | counts = [count_permutations(s[0], s[1]) for s in springs] 77 | 78 | print('Day 12 Part 2:',sum(counts)) 79 | 80 | ########################## PART 2: ONE-LINE SOLUTION ########################## 81 | print('Day 12 Part 2:',sum((count_permutations:=cache(lambda symbols, counts, group_loc=0: (not (results:=0) and [(results:=results+count_permutations(symbols[1:], counts, group_loc + 1)) if p == '#' else 1 and (group_loc > 0 and (counts and counts[0] == group_loc and (results:=results+count_permutations(symbols[1:], counts[1:])))) or (group_loc == 0 and (results:=results+count_permutations(symbols[1:], counts))) if p != '#' else 1 for p in (['.', '#'] if symbols[0] == '?' else symbols[0])] and results) if symbols else not counts and not group_loc)) and [count_permutations(s[0], s[1]) for s in [('?'.join([x[0]] * 5) + '.', x[1] * 5) for x in [(x[0], tuple(map(int, x[1].split(',')))) for x in [x.split() for x in q[12].strip().split('\n')]]]])) 82 | -------------------------------------------------------------------------------- /2023/day-13.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 13 (https://adventofcode.com/2023/day/13) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import itertools as it 9 | 10 | # Input files not included in repo per copyright & Eric Wastl's request. 11 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 12 | # Replace with path to your personal input file if you would like to run the code. 13 | input_file = '2023/day-13.txt' 14 | 15 | # To match the format of input files for the Basilisk. 16 | q = { 13: open(input_file).read().strip() } 17 | 18 | 19 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 20 | maps = [[list(row) for row in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]] 21 | 22 | def find_reflection(map): 23 | for col in range(1, len(map[0])): 24 | spit = min(col, len(map[0])-col) 25 | reflection = 1 26 | for row in map: 27 | if row[col-spit:col] != row[col:col+spit][::-1]: 28 | reflection = 0 29 | break 30 | if reflection: 31 | return col 32 | 33 | columns = 0 34 | rows = 0 35 | for m in maps: 36 | vertical = find_reflection(m) 37 | horizontal = find_reflection(list(zip(*m))) 38 | columns += vertical if vertical else 0 39 | rows += horizontal*100 if horizontal else 0 40 | 41 | print('Day 13 Part 1:', columns+rows) 42 | 43 | ########################## PART 1: ONE-LINE SOLUTION ########################## 44 | print('Day 13 Part 1:',((f:=lambda m:(a:=0,[(s:=min(c,len(m[0])-c),n:=1,[(r[c-s:c]!=r[c:c+s][::-1]) and (n:=0) for r in it.takewhile(lambda _:n==1,m)]) and (n and (a:=c)) for c in range(1,len(m[0]))]) and a),([[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]),x:=0,y:=0,[(v:=f(m),h:=f(list(zip(*m))),(v and (x:=x+v)),(h and (y:=y+h*100))) for m in [[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]]) and x+y) 45 | 46 | 47 | ######################## PART 2: MULTI-LINE SOLUTION ########################## 48 | maps = [[list(row) for row in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]] 49 | 50 | def find_one_off_reflection(map): 51 | for col in range(1, len(map[0])): 52 | split = min(col, len(map[0])-col) 53 | num_differences = 0 54 | for row in map: 55 | for l, r in zip(row[col-split:col], row[col:col+split][::-1]): 56 | if l != r: 57 | num_differences += 1 58 | if num_differences > 1: 59 | break 60 | if num_differences == 1: 61 | return col 62 | 63 | columns = 0 64 | rows = 0 65 | for m in maps: 66 | vertical = find_one_off_reflection(m) 67 | horizontal = find_one_off_reflection(list(zip(*m))) 68 | columns += vertical if vertical else 0 69 | rows += horizontal*100 if horizontal else 0 70 | 71 | print('Day 13 Part 2:', columns+rows) 72 | 73 | ########################## PART 2: ONE-LINE SOLUTION ########################## 74 | print('Day 13 Part 2:',((f:=lambda m:(a:=0,[(s:=min(c,len(m[0])-c),n:=0,[[(l!=r and (n:=n+1)) for l,r in zip(r[c-s:c],r[c:c+s][::-1])] for r in m if n<=1],(n==1 and (a:=c))) for c in range(1,len(m[0]))]) and a),([[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]),x:=0,y:=0,[(v:=f(m),h:=f(list(zip(*m))),(v and (x:=x+v)),(h and (y:=y+h*100))) for m in [[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]]) and x+y) -------------------------------------------------------------------------------- /2023/day-14.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 14 (https://adventofcode.com/2023/day/14) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | import itertools as it 9 | 10 | # Input files not included in repo per copyright & Eric Wastl's request. 11 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 12 | # Replace with path to your personal input file if you would like to run the code. 13 | input_file = '2023/day-14.txt' 14 | 15 | # To match the format of input files for the Basilisk. 16 | q = { 14: open(input_file).read().strip() } 17 | 18 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 19 | # Each platform contains rounded rocks (O) that will roll when the platform is tileted, and cube-shaped rocks (#) which will stay in place. '.' are empty spaces. 20 | # We are tilting the platform north, so all the rocks (O) will move upwards until they hit a cube (#) or the top of the platform. 21 | platform = [list(x) for x in q[14].strip().split('\n')] 22 | platform.insert(0, ['#']*len(platform[0])) 23 | for i in range(len(platform)): 24 | for j in range(len(platform[0])): 25 | if platform[i][j] == 'O': 26 | for k in range(i-1, -1, -1): 27 | if platform[k][j] == '#': 28 | break 29 | elif platform[k][j] == '.': 30 | platform[k][j] = 'O' 31 | platform[k+1][j] = '.' 32 | else: 33 | platform[0][j] = '.' 34 | print('Day 14 Part 1:',sum([sum([1 for x in p if x == 'O'])*(i+1) for i,p in enumerate(platform[::-1])])) 35 | 36 | ########################## PART 1: ONE-LINE SOLUTION ########################## 37 | print('Day 14 Part 1:',sum((platform:=[list(x) for x in q[14].strip().split('\n')]) and not platform.insert(0, ['#']*len(platform[0])) and [[(platform[i][j] == 'O') and [(platform[k][j] == '.') and [(platform[k][j] == '.' and not platform[k].__setitem__(j, 'O') and platform[k+1].__setitem__(j, '.'))] for k in it.takewhile(lambda x: platform[x][j] != '#',range(i-1, -1, -1))] for j in range(len(platform[0]))] for i in range(len(platform))] and [sum([1 for x in p if x == 'O'])*(i+1) for i,p in enumerate(platform[::-1])])) 38 | 39 | 40 | ######################## PART 2: MULTI-LINE SOLUTION ########################## 41 | def tilt_platform(platform, direction): 42 | if direction == 'north': 43 | for i in range(len(platform)): 44 | for j in range(len(platform[0])): 45 | if platform[i][j] == 'O': 46 | for k in range(i-1, -1, -1): 47 | if platform[k][j] == '#': 48 | break 49 | elif platform[k][j] == '.': 50 | platform[k][j] = 'O' 51 | platform[k+1][j] = '.' 52 | else: 53 | platform[0][j] = '.' 54 | elif direction == 'west': 55 | for i in range(len(platform)): 56 | for j in range(len(platform[0])): 57 | if platform[i][j] == 'O': 58 | for k in range(j-1, -1, -1): 59 | if platform[i][k] == '#': 60 | break 61 | elif platform[i][k] == '.': 62 | platform[i][k] = 'O' 63 | platform[i][k+1] = '.' 64 | else: 65 | platform[i][0] = '.' 66 | elif direction == 'south': 67 | for i in range(len(platform)-1, -1, -1): 68 | for j in range(len(platform[0])): 69 | if platform[i][j] == 'O': 70 | for k in range(i+1, len(platform)): 71 | if platform[k][j] == '#': 72 | break 73 | elif platform[k][j] == '.': 74 | platform[k][j] = 'O' 75 | platform[k-1][j] = '.' 76 | else: 77 | platform[-1][j] = '.' 78 | elif direction == 'east': 79 | for i in range(len(platform)): 80 | for j in range(len(platform[0])-1, -1, -1): 81 | if platform[i][j] == 'O': 82 | for k in range(j+1, len(platform[0])): 83 | if platform[i][k] == '#': 84 | break 85 | elif platform[i][k] == '.': 86 | platform[i][k] = 'O' 87 | platform[i][k-1] = '.' 88 | else: 89 | platform[i][-1] = '.' 90 | return platform 91 | 92 | def plat_to_string(platform): 93 | return 'y'.join(['x'.join(x) for x in platform]) 94 | 95 | def string_to_plat(string): 96 | return [x.split('x') for x in string.split('y')] 97 | 98 | platform = [['#'] + list(x) + ['#'] for x in q[14].strip().split('\n')] 99 | platform.insert(0, ['#']*len(platform[0])) 100 | platform.append(['#']*len(platform[0])) 101 | size = len(platform) 102 | 103 | stored_states = [plat_to_string(platform)] 104 | while True: 105 | platform = tilt_platform(platform, 'north') 106 | platform = tilt_platform(platform, 'west') 107 | platform = tilt_platform(platform, 'south') 108 | platform = tilt_platform(platform, 'east') 109 | if plat_to_string(platform) in stored_states: 110 | break 111 | stored_states.append(plat_to_string(platform)) 112 | 113 | first_occurence = stored_states.index(plat_to_string(platform)) 114 | cycles = len(stored_states) - first_occurence 115 | platform = string_to_plat(stored_states[(1000000000 - first_occurence) % cycles + first_occurence]) 116 | 117 | print('Day 14 Part 2:',sum([sum([1 for x in p if x == 'O'])*(i) for i,p in enumerate(platform[::-1])])) 118 | 119 | ########################## PART 2: ONE-LINE SOLUTION ########################## 120 | print('Day 14 Part 2:',sum((tilt_platform:=lambda platform,direction: (((direction == 'north') and [[(platform[i][j] == 'O') and [(platform[k][j] == '.') and [(platform[k][j] == '.' and not platform[k].__setitem__(j, 'O') and platform[k+1].__setitem__(j, '.'))] for k in it.takewhile(lambda x: platform[x][j] != '#',range(i-1, -1, -1))] for j in range(len(platform[0]))] for i in range(len(platform))]) or ((direction == 'west') and [[(platform[i][j] == 'O') and [(platform[i][k] == '.') and [(platform[i][k] == '.' and not platform[i].__setitem__(k, 'O') and platform[i].__setitem__(k+1, '.'))] for k in it.takewhile(lambda x: platform[i][x] != '#',range(j-1, -1, -1))]] for i in range(len(platform)) for j in range(len(platform[0]))]) or (direction == 'south') and [(platform[i][j] == 'O') and [(platform[k][j] == '.') and [(platform[k][j] == '.' and not platform[k].__setitem__(j, 'O') and platform[k-1].__setitem__(j, '.'))] for k in it.takewhile(lambda x: platform[x][j] != '#',range(i+1, len(platform)))] for j in range(len(platform[0])) for i in range(len(platform)-1, -1, -1)] or (direction == 'east') and [(platform[i][j] == 'O') and [(platform[i][k] == '.') and [(platform[i][k] == '.' and not platform[i].__setitem__(k, 'O') and platform[i].__setitem__(k-1, '.'))] for k in it.takewhile(lambda x: platform[i][x] != '#',range(j+1, len(platform[0])))] for i in range(len(platform)) for j in range(len(platform[0])-1, -1, -1)]) and platform) and (plat_to_string:=lambda platform: 'y'.join(['x'.join(x) for x in platform])) and (string_to_plat:=lambda string: [x.split('x') for x in string.split('y')]) and (platform:=[['#'] + list(x) + ['#'] for x in q[14].strip().split('\n')]) and not platform.insert(0, ['#']*len(platform[0])) and not platform.append(['#']*len(platform[0])) and (stored_states:=[plat_to_string(platform)]) and [(platform:=tilt_platform(tilt_platform(tilt_platform(tilt_platform(platform, 'north'), 'west'), 'south'), 'east')) and (plat_to_string(platform) not in stored_states) and stored_states.append(plat_to_string(platform)) for _ in it.takewhile(lambda x: plat_to_string(platform) not in stored_states[:-1], it.repeat(None))] and (platform:=string_to_plat(stored_states[(1000000000 - (first_occurence:=stored_states.index(plat_to_string(platform)))) % (len(stored_states) - first_occurence) + first_occurence])) and [sum([1 for x in p if x == 'O'])*(i) for i,p in enumerate(platform[::-1])])) 121 | -------------------------------------------------------------------------------- /2023/day-15.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 15 (https://adventofcode.com/2023/day/15) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | # Input files not included in repo per copyright & Eric Wastl's request. 9 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 10 | # Replace with path to your personal input file if you would like to run the code. 11 | input_file = '2023/day-15.txt' 12 | 13 | # To match the format of input files for the Basilisk. 14 | q = { 15: open(input_file).read().strip() } 15 | 16 | 17 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 18 | steps = q[15].split(',') 19 | values = [] 20 | for s in steps: 21 | value = 0 22 | for c in s: 23 | value += ord(c) 24 | value *= 17 25 | value %= 256 26 | values.append(value) 27 | 28 | print('Day 15 Part 1:',sum(values)) 29 | 30 | ########################## PART 1: ONE-LINE SOLUTION ########################## 31 | print('Day 15 Part 1:',sum([(v:=0) or [v:=(v+ord(c))*17%256 for c in s] and v for s in q[15].split(',')])) 32 | 33 | 34 | ######################## PART 2: MULTI-LINE SOLUTION ########################## 35 | steps = q[15].split(',') 36 | boxes = [[] for _ in range(256)] 37 | for s in steps: 38 | label = ''.join([c for c in s if c.isalpha()]) 39 | operation = ''.join([c for c in s if not c.isalnum()]) 40 | focal = ''.join([c for c in s if c.isdigit()]) 41 | lens = (label, focal) 42 | box = 0 43 | for c in label: 44 | box += ord(c) 45 | box *= 17 46 | box %= 256 47 | if operation == '=': 48 | if label not in [x[0] for x in boxes[box]]: 49 | boxes[box].append(lens) 50 | else: 51 | index = [x[0] for x in boxes[box]].index(label) 52 | boxes[box].pop(index) 53 | boxes[box].insert(index, lens) 54 | elif operation == '-': 55 | if label in [x[0] for x in boxes[box]]: 56 | boxes[box].pop([x[0] for x in boxes[box]].index(label)) 57 | 58 | score = 0 59 | for i,box in enumerate(boxes): 60 | for j,lens in enumerate(box): 61 | score += (i+1)*(j+1)*int(lens[1]) 62 | 63 | print('Day 15 Part 2:',score) 64 | 65 | ########################## PART 2: ONE-LINE SOLUTION ########################## 66 | print('Day 15 Part 2:',sum((b:=[[] for _ in range(256)]) and [((l:=''.join([c for c in s if c.isalpha()])) and (o:=''.join([c for c in s if not c.isalnum()])) and (f:=''.join([c for c in s if c.isdigit()])) and (d:=(l,f)) and (a:=0) or 1) and not (a:=0) and [a:=(a+ord(c))*17%256 for c in l] and ((b[a].append(d) if l not in [x[0] for x in b[a]] else ((e:=[x[0] for x in b[a]].index(l)) or 1) and b[a].pop(e) and b[a].insert(e,d)) if o=='=' else b[a].pop([x[0] for x in b[a]].index(l)) if l in [x[0] for x in b[a]] else 0) for s in q[15].split(',')] and [(i+1)*(j+1)*int(n[1]) for i,p in enumerate(b) for j,n in enumerate(p)])) -------------------------------------------------------------------------------- /2023/day-16.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2023 Advent of Code - Day 16 (https://adventofcode.com/2023/day/16) 3 | Solution by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code. 5 | See full progress at https://github.com/savbell/advent-of-code-one-liners 6 | ''' 7 | 8 | # Input files not included in repo per copyright & Eric Wastl's request. 9 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 10 | # Replace with path to your personal input file if you would like to run the code. 11 | from sys import setrecursionlimit 12 | import itertools as it 13 | 14 | 15 | input_file = '2023/day-16.txt' 16 | 17 | # To match the format of input files for the Basilisk. 18 | q = { 16: open(input_file).read().strip() } 19 | 20 | 21 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 22 | grid = [list(x) for x in q[16].strip().split('\n')] 23 | 24 | def follow_beam(beam_coord, direction, visited_coords): 25 | if (beam_coord, direction) not in visited_coords: 26 | visited_coords.add((beam_coord, direction)) 27 | 28 | while True: 29 | if grid[beam_coord[1]][beam_coord[0]] == '.': 30 | pass 31 | elif grid[beam_coord[1]][beam_coord[0]] == '/': 32 | if direction == 'right': 33 | direction = 'up' 34 | elif direction == 'left': 35 | direction = 'down' 36 | elif direction == 'up': 37 | direction = 'right' 38 | elif direction == 'down': 39 | direction = 'left' 40 | elif grid[beam_coord[1]][beam_coord[0]] == '\\': 41 | if direction == 'right': 42 | direction = 'down' 43 | elif direction == 'left': 44 | direction = 'up' 45 | elif direction == 'up': 46 | direction = 'left' 47 | elif direction == 'down': 48 | direction = 'right' 49 | elif grid[beam_coord[1]][beam_coord[0]] == '|': 50 | if direction == 'right': 51 | visited_coords = follow_beam(beam_coord, 'up', visited_coords) 52 | direction = 'down' 53 | elif direction == 'left': 54 | visited_coords = follow_beam(beam_coord, 'up', visited_coords) 55 | direction = 'down' 56 | elif direction == 'up': 57 | pass 58 | elif direction == 'down': 59 | pass 60 | elif grid[beam_coord[1]][beam_coord[0]] == '-': 61 | if direction == 'right': 62 | pass 63 | elif direction == 'left': 64 | pass 65 | elif direction == 'up': 66 | visited_coords = follow_beam(beam_coord, 'left', visited_coords) 67 | direction = 'right' 68 | elif direction == 'down': 69 | visited_coords = follow_beam(beam_coord, 'left', visited_coords) 70 | direction = 'right' 71 | 72 | if direction == 'right': 73 | beam_coord = (beam_coord[0]+1, beam_coord[1]) 74 | elif direction == 'left': 75 | beam_coord = (beam_coord[0]-1, beam_coord[1]) 76 | elif direction == 'up': 77 | beam_coord = (beam_coord[0], beam_coord[1]-1) 78 | elif direction == 'down': 79 | beam_coord = (beam_coord[0], beam_coord[1]+1) 80 | 81 | if (beam_coord, direction) in visited_coords or beam_coord[0] < 0 or beam_coord[0] >= len(grid[0]) or beam_coord[1] < 0 or beam_coord[1] >= len(grid): 82 | break 83 | else: 84 | visited_coords.add((beam_coord, direction)) 85 | 86 | return visited_coords 87 | 88 | setrecursionlimit(30000) 89 | visited_coords = follow_beam((0,0), 'right', set()) 90 | print('Day 16 Part 1:',len(set([x[0] for x in visited_coords]))) 91 | 92 | ########################## PART 1: ONE-LINE SOLUTION ########################## 93 | print('Day 16 Part 1:',(sys.setrecursionlimit(30000),g:=[list(x) for x in q[16].strip().split('\n')],(f:=lambda c,d,v: ((c,d) not in v and v.add((c,d)),(end:=0)) and [((g[c[1]][c[0]]=='/') and ((d==4) and (d:=1) or (d==3) and (d:=2) or (d==1) and (d:=4) or (d==2) and (d:=3)) or (g[c[1]][c[0]]=='\\') and ((d==4) and (d:=2) or (d==3) and (d:=1) or (d==1) and (d:=3) or (d==2) and (d:=4)) or (g[c[1]][c[0]]=='|') and ((d==4) and (v:=f(c,1,v)) and (d:=2) or (d==3) and (v:=f(c,1,v)) and (d:=2)) or (g[c[1]][c[0]]=='-') and ((d==2) and (d:=4) and (v:=f(c,3,v)) or (d==1) and (d:=4) and (v:=f(c,3,v))),(c:=(c[0]+1,c[1]) if d==4 else (c[0]-1,c[1]) if d==3 else (c[0],c[1]-1) if d==1 else (c[0],c[1]+1)),(((c,d) in v or c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and (end:=1)),not (c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and v.add((c,d))) for _ in it.takewhile(lambda _: not end,it.count())] and v)) and len(set([x[0] for x in f((0,0),4,set())]))) 94 | 95 | 96 | ######################## PART 2: MULTI-LINE SOLUTION ########################## 97 | grid = [list(x) for x in q[16].strip().split('\n')] 98 | 99 | def follow_beam(beam_coord, direction, visited_coords): 100 | if (beam_coord, direction) not in visited_coords: 101 | visited_coords.add((beam_coord, direction)) 102 | 103 | while True: 104 | if grid[beam_coord[1]][beam_coord[0]] == '.': 105 | pass 106 | elif grid[beam_coord[1]][beam_coord[0]] == '/': 107 | if direction == 'right': 108 | direction = 'up' 109 | elif direction == 'left': 110 | direction = 'down' 111 | elif direction == 'up': 112 | direction = 'right' 113 | elif direction == 'down': 114 | direction = 'left' 115 | elif grid[beam_coord[1]][beam_coord[0]] == '\\': 116 | if direction == 'right': 117 | direction = 'down' 118 | elif direction == 'left': 119 | direction = 'up' 120 | elif direction == 'up': 121 | direction = 'left' 122 | elif direction == 'down': 123 | direction = 'right' 124 | elif grid[beam_coord[1]][beam_coord[0]] == '|': 125 | if direction == 'right': 126 | visited_coords = follow_beam(beam_coord, 'up', visited_coords) 127 | direction = 'down' 128 | elif direction == 'left': 129 | visited_coords = follow_beam(beam_coord, 'up', visited_coords) 130 | direction = 'down' 131 | elif direction == 'up': 132 | pass 133 | elif direction == 'down': 134 | pass 135 | elif grid[beam_coord[1]][beam_coord[0]] == '-': 136 | if direction == 'right': 137 | pass 138 | elif direction == 'left': 139 | pass 140 | elif direction == 'up': 141 | visited_coords = follow_beam(beam_coord, 'left', visited_coords) 142 | direction = 'right' 143 | elif direction == 'down': 144 | visited_coords = follow_beam(beam_coord, 'left', visited_coords) 145 | direction = 'right' 146 | 147 | if direction == 'right': 148 | beam_coord = (beam_coord[0]+1, beam_coord[1]) 149 | elif direction == 'left': 150 | beam_coord = (beam_coord[0]-1, beam_coord[1]) 151 | elif direction == 'up': 152 | beam_coord = (beam_coord[0], beam_coord[1]-1) 153 | elif direction == 'down': 154 | beam_coord = (beam_coord[0], beam_coord[1]+1) 155 | 156 | if (beam_coord, direction) in visited_coords or beam_coord[0] < 0 or beam_coord[0] >= len(grid[0]) or beam_coord[1] < 0 or beam_coord[1] >= len(grid): 157 | break 158 | else: 159 | visited_coords.add((beam_coord, direction)) 160 | 161 | return visited_coords 162 | 163 | max_energized = 0 164 | for x in range(len(grid[0])): 165 | visited_coords = follow_beam((x,0), 'down', set()) 166 | energized_coords = set([x[0] for x in visited_coords]) 167 | max_energized = len(energized_coords) if len(energized_coords) > max_energized else max_energized 168 | for x in range(len(grid[0])): 169 | visited_coords = follow_beam((x,len(grid)-1), 'up', set()) 170 | energized_coords = set([x[0] for x in visited_coords]) 171 | max_energized = len(energized_coords) if len(energized_coords) > max_energized else max_energized 172 | for y in range(len(grid)): 173 | visited_coords = follow_beam((0,y), 'right', set()) 174 | energized_coords = set([x[0] for x in visited_coords]) 175 | max_energized = len(energized_coords) if len(energized_coords) > max_energized else max_energized 176 | for y in range(len(grid)): 177 | visited_coords = follow_beam((len(grid[0])-1,y), 'left', set()) 178 | energized_coords = set([x[0] for x in visited_coords]) 179 | max_energized = len(energized_coords) if len(energized_coords) > max_energized else max_energized 180 | 181 | print('Day 16 Part 2:',max_energized) 182 | 183 | ########################## PART 2: ONE-LINE SOLUTION ########################## 184 | print('Day 16 Part 2:',(g:= [list(x) for x in q[16].strip().split('\n')],(f:=lambda c,d,v: ((c,d) not in v and v.add((c,d)),(end:=0)) and [((g[c[1]][c[0]]=='/') and ((d==4) and (d:=1) or (d==3) and (d:=2) or (d==1) and (d:=4) or (d==2) and (d:=3)) or (g[c[1]][c[0]]=='\\') and ((d==4) and (d:=2) or (d==3) and (d:=1) or (d==1) and (d:=3) or (d==2) and (d:=4)) or (g[c[1]][c[0]]=='|') and ((d==4) and (v:=f(c,1,v)) and (d:=2) or (d==3) and (v:=f(c,1,v)) and (d:=2)) or (g[c[1]][c[0]]=='-') and ((d==2) and (d:=4) and (v:=f(c,3,v)) or (d==1) and (d:=4) and (v:=f(c,3,v))),(c:=(c[0]+1,c[1]) if d==4 else (c[0]-1,c[1]) if d==3 else (c[0],c[1]-1) if d==1 else (c[0],c[1]+1)),(((c,d) in v or c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and (end:=1)),not (c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and v.add((c,d))) for _ in it.takewhile(lambda _: not end,it.count())] and v),(m:=0),[(v:=f((x,0),2,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for x in range(len(g[0]))] and [(v:=f((x,len(g)-1),1,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for x in range(len(g[0]))] and [(v:=f((0,y),4,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for y in range(len(g))] and [(v:=f((len(g[0])-1,y),3,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for y in range(len(g))] and m) and m) -------------------------------------------------------------------------------- /2023/the-basilisk.py: -------------------------------------------------------------------------------- 1 | ''' 2 | One-line Python solution for Advent of Code 2023 (https://adventofcode.com/2023/) 3 | Written by Sav Bell (https://github.com/savbell) 4 | Challenge: Solve every day in a single line of Python code, affectionately nicknamed the Basilisk. 5 | Current progress: 6 | Day | Pt1 | Pt2 7 | ----------------- 8 | 01 | ✔ | ✔ 9 | 02 | ✔ | ✔ 10 | 03 | ✔ | ✔ 11 | 04 | ✔ | ✔ 12 | 05 | ✔ | ✔ 13 | 06 | ✔ | ✔ 14 | 07 | ✔ | ✔ 15 | 08 | ✔ | ✔ 16 | 09 | ✔ | ✔ 17 | 10 | ✔ | ✔ 18 | 11 | ✔ | ✔ 19 | 12 | ✔ | ✔ 20 | 13 | ✔ | ✔ 21 | 14 | ✔ | ✔ 22 | 15 | ✔ | ✔ 23 | 16 | ✔ | ✔ 24 | 17 | ✖ | ✖ 25 | 18 | ✖ | ✖ 26 | See README and explanation of solutions at https://github.com/savbell/advent-of-code-one-liners 27 | ''' 28 | 29 | # Input files not included in repo per Eric Wastl's request. 30 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 31 | # To run the Basilisk, replace with the paths to your own input files 32 | f = { 33 | 1 : '2023/day-01.txt', 34 | 2 : '2023/day-02.txt', 35 | 3 : '2023/day-03.txt', 36 | 4 : '2023/day-04.txt', 37 | 5 : '2023/day-05.txt', 38 | 6 : '2023/day-06.txt', 39 | 7 : '2023/day-07.txt', 40 | 8 : '2023/day-08.txt', 41 | 9 : '2023/day-09.txt', 42 | 10: '2023/day-10.txt', 43 | 11: '2023/day-11.txt', 44 | 12: '2023/day-12.txt', 45 | 13: '2023/day-13.txt', 46 | 14: '2023/day-14.txt', 47 | 15: '2023/day-15.txt', 48 | 16: '2023/day-16.txt', 49 | # 17: '2023/day-17.txt', # Haven't started yet... 50 | # 18: '2023/day-18.txt', # Working on Part 2... 51 | } 52 | 53 | ################################ THE BASILISK ################################ 54 | print((re:=__import__('re'),ft:=__import__('functools'),it:=__import__('itertools'),math:=__import__('math'),sys:=__import__('sys'),sys.setrecursionlimit(30000),q:={d:open(p).read().strip() for d,p in f.items()}) and 'Day 01 Part 1:',sum([(d:=re.findall(r'\d',l)) and int(d[0]+d[-1]) for l in q[1].split('\n')]),'\nDay 01 Part 2:',sum([int(''.join([{'one':'1','two':'2','three':'3','four':'4','five':'5','six':'6','seven':'7','eight':'8','nine':'9'}[d] if d.isalpha() else d for d in [n[0],n[-1]]])) for l in q[1].split('\n') for n in [re.findall(r'(?=(\d|one|two|three|four|five|six|seven|eight|nine))',l)]]),'\nDay 02 Part 1:',sum([int(g[0]) for g in re.findall(r'(\d+):((?: *\d+\s+\w+,?;?)+)',q[2])])-sum([int(g[0]) for g in re.findall(r'Game (\d+):((?:\s*\d+\s+\w+,?;?)+)',q[2]) if any([int(d[0])>12 and d[1]=='red' or int(d[0])>13 and d[1]=='green' or int(d[0])>14 and d[1]=='blue' for d in re.findall(r'(\d+)\s+(\w+)',g[1])])]),'\nDay 02 Part 2:',sum([(m:=re.findall(r'(\d+)\s+(\w+)',g[1])) and max([int(d[0]) for d in m if d[1]=='red'])*max([int(d[0]) for d in m if d[1]=='green'])*max([int(d[0]) for d in m if d[1]=='blue']) for g in re.findall(r'(\d+):((?: *\d+\s+\w+,?;?)+)',q[2])]),'\nDay 03 Part 1:',sum([int(n[0]) for n in [[n.group(),[(x,n.start()+i) for i in range(len(n.group()))]] for x,l in enumerate(q[3].split('\n')) for n in re.finditer(r'\d+',l)] if any([abs(c[0]-s[1][0])<=1 and abs(c[1]-s[1][1])<=1 for c in n[1] for s in [[s.group(),(x,s.start())] for x,l in enumerate(q[3].split('\n')) for s in re.finditer(r'[^.\d]',l)]])]),'\nDay 03 Part 2:',(r:=[[s.group(),(x,s.start()),[]] for x,l in enumerate(q[3].split('\n')) for s in re.finditer(r'[*]',l)]) and [s[2].append(n) if n not in s[2] else 0 for n in [[int(n.group()),[(x,n.start()+i) for i in range(len(n.group()))]] for x,l in enumerate(q[3].split('\n')) for n in re.finditer(r'\d+',l)] for c in n[1] for s in r if abs(c[0]-s[1][0])<=1 and abs(c[1]-s[1][1])<=1] and sum([s[2][0][0]*s[2][1][0] for s in r if len(s[2])==2]),'\nDay 04 Part 1:',sum([2**(len(n)-1) if len(n)>0 else 0 for n in [n[0].intersection(n[1]) for n in [(set(map(int,n[0].split())),set(map(int,n[1].split()))) for n in re.findall(r': +((?:\d+\s+)+)\| +((?:\d+\s*)+)',q[4])]]]),'\nDay 04 Part 2:',((c:=[[1,len(n[0].intersection(n[1]))] for n in [(set(map(int,n[0].split())), set(map(int,n[1].split()))) for n in re.findall(r'\d+: +((?:\d+\s+)+)\| +((?:\d+\s*)+)',q[4])]]) and not (t:=0) and [(t:=t+n[0]) and [c.__setitem__(i+j,[c[i+j][0]+1,c[i+j][1]]) for _ in range(n[0]) for j in range(1,n[1]+1)] for i, n in enumerate(c)] and t),'\nDay 05 Part 1:',(v:=[[list(map(int,l.split())) for l in d.split('\n')] for d in [d for _,d in [re.split(r':\n',s) for s in re.split(r'\n\n',q[5])[1:]]]]) and (c:=lambda i,m:(lambda c:c[0]+(i-c[1]) if c[1]+c[2]>i else i)(min([y for y in m if y[1]<=i],default=[0,0,0],key=lambda x:i-x[1]))) and min([c(s,v[6])for s in [c(s,v[5]) for s in [c(s,v[4]) for s in [c(s,v[3]) for s in [c(s,v[2]) for s in [c(s,v[1]) for s in [c(s,v[0]) for s in list(map(int,re.split(r'\n\n',q[5])[0].split()[1:]))]]]]]]]),'\nDay 05 Part 2:',[(v:=re.split(r'\n\n',q[5])) and (s:=list(map(int,v[0].split()[1:]))) and (m:=v[1:]) and (c:=[(a,a+b) for a,b in zip(s[::2],s[1::2])]) and [[(w:=[tuple(map(int,x.split())) for x in g.split('\n')[1:]]) and (u:=[-99]) and (o:=[0]) and (l:=-99) and [(l:=max(l,(p:=r[0] - r[1])+r[1]+r[2])) and [(not u.__setitem__(-1,r[1]) and not o.__setitem__(-1,p)) if u and u[-1]==r[1] else (u.__iadd__([r[1]])) and o.__iadd__([p])] and (u.__iadd__([r[1]+r[2]]) and o.__iadd__([0])) for r in sorted(w,key=lambda x: x[1])] and not (t:=[]) and [(j:=[i[0]]) and not (h:=None) and [(((h:=d-1) if h is None else 0) and (j.__iadd__([p]) if p < i[1] and p != i[1] else 0) if not p <= j[-1] else 0) for d,p in enumerate(u)] and (j.__iadd__([i[1]]) and (h:=h or len(o))) and [(d:=o[min(h or float('inf'),len(o)-1)]) and (h:=h+1) and t.__iadd__([(a+d,b+d)]) for a,b in zip(j,j[1:])] for i in c]] and (c:=t) for g in m]] and min(x[0] for x in c),'\nDay 06 Part 1:',(so:=lambda b,c:[(b+((b**2)-(4*c))**0.5)/2,(b-((b**2)-(4*c))**0.5)/2]) and (h:=lambda i:int(i[1])-int(i[0]) if i[0] 0 and (n and n[0]==g and (r:=r+c(b[1:],n[1:])))) or (g==0 and (r:=r+c(b[1:],n))) if p!='#' else 1 for p in (['.','#'] if b[0]=='?' else b[0])] and r) if b else not n and not g)) and [c(s[0],s[1]) for s in [('?'.join([x[0]]*5)+'.',x[1]*5) for x in [(x[0],tuple(map(int,x[1].split(',')))) for x in [x.split() for x in q[12].strip().split('\n')]]]]),'\nDay 13 Part 1:',((f:=lambda m:(a:=0,[(s:=min(c,len(m[0])-c),n:=1,[(r[c-s:c]!=r[c:c+s][::-1]) and (n:=0) for r in it.takewhile(lambda _:n==1,m)]) and (n and (a:=c)) for c in range(1,len(m[0]))]) and a),([[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]),x:=0,y:=0,[(v:=f(m),h:=f(list(zip(*m))),(v and (x:=x+v)),(h and (y:=y+h*100))) for m in [[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]]) and x+y,'\nDay 13 Part 2:',((f:=lambda m:(a:=0,[(s:=min(c,len(m[0])-c),n:=0,[[(l!=r and (n:=n+1)) for l,r in zip(r[c-s:c],r[c:c+s][::-1])] for r in m if n<=1],(n==1 and (a:=c))) for c in range(1,len(m[0]))]) and a),([[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]),x:=0,y:=0,[(v:=f(m),h:=f(list(zip(*m))),(v and (x:=x+v)),(h and (y:=y+h*100))) for m in [[list(r) for r in m] for m in [m.split('\n') for m in q[13].strip().split('\n\n')]]]) and x+y,'\nDay 14 Part 1:',sum((p:=[list(x) for x in q[14].strip().split('\n')]) and not p.insert(0,['#']*len(p[0])) and [[(p[i][j]=='O') and [(p[k][j]=='.') and [(p[k][j]=='.' and not p[k].__setitem__(j,'O') and p[k+1].__setitem__(j,'.'))] for k in it.takewhile(lambda x:p[x][j]!='#',range(i-1,-1,-1))] for j in range(len(p[0]))] for i in range(len(p))] and [sum([1 for x in p if x=='O'])*(i+1) for i,p in enumerate(p[::-1])]),'\nDay 14 Part 2:',sum((t:=lambda p,d:(((d==1) and [[(p[i][j]=='O') and [(p[k][j]=='.') and [(p[k][j]=='.' and not p[k].__setitem__(j,'O') and p[k+1].__setitem__(j,'.'))] for k in it.takewhile(lambda x:p[x][j]!='#',range(i-1,-1,-1))] for j in range(len(p[0]))] for i in range(len(p))]) or ((d==2) and [[(p[i][j]=='O') and [(p[i][k]=='.') and [(p[i][k]=='.' and not p[i].__setitem__(k,'O') and p[i].__setitem__(k+1,'.'))] for k in it.takewhile(lambda x:p[i][x]!='#',range(j-1,-1,-1))]] for i in range(len(p)) for j in range(len(p[0]))]) or (d==3) and [(p[i][j]=='O') and [(p[k][j]=='.') and [(p[k][j]=='.' and not p[k].__setitem__(j,'O') and p[k-1].__setitem__(j,'.'))] for k in it.takewhile(lambda x:p[x][j]!='#',range(i+1,len(p)))] for j in range(len(p[0])) for i in range(len(p)-1,-1,-1)] or (d==4) and [(p[i][j]=='O') and [(p[i][k]=='.') and [(p[i][k]=='.' and not p[i].__setitem__(k,'O') and p[i].__setitem__(k-1,'.'))] for k in it.takewhile(lambda x:p[i][x]!='#',range(j+1,len(p[0])))] for i in range(len(p)) for j in range(len(p[0])-1,-1,-1)]) and p) and (o:=lambda p:'y'.join(['x'.join(x) for x in p])) and (g:=lambda x:[x.split('x') for x in x.split('y')]) and (p:=[['#']+list(x)+['#'] for x in q[14].strip().split('\n')]) and not p.insert(0,['#']*len(p[0])) and not p.append(['#']*len(p[0])) and (s:=[o(p)]) and [(p:=t(t(t(t(p,1),2),3),4)) and (o(p) not in s) and s.append(o(p)) for _ in it.takewhile(lambda x:o(p) not in s[:-1],it.repeat(None))] and (p:=g(s[(1000000000-(b:=s.index(o(p)))) % (len(s)-b)+b])) and [sum([1 for x in p if x=='O'])*(i) for i,p in enumerate(p[::-1])]),'\nDay 15 Part 1:',sum([(v:=0) or [v:=(v+ord(c))*17%256 for c in s] and v for s in q[15].split(',')]),'\nDay 15 Part 2:',sum((b:=[[] for _ in range(256)]) and [((l:=''.join([c for c in s if c.isalpha()])) and (o:=''.join([c for c in s if not c.isalnum()])) and (f:=''.join([c for c in s if c.isdigit()])) and (d:=(l,f)) and (a:=0) or 1) and not (a:=0) and [a:=(a+ord(c))*17%256 for c in l] and ((b[a].append(d) if l not in [x[0] for x in b[a]] else ((e:=[x[0] for x in b[a]].index(l)) or 1) and b[a].pop(e) and b[a].insert(e,d)) if o=='=' else b[a].pop([x[0] for x in b[a]].index(l)) if l in [x[0] for x in b[a]] else 0) for s in q[15].split(',')] and [(i+1)*(j+1)*int(n[1]) for i,p in enumerate(b) for j,n in enumerate(p)]),'\nDay 16 Part 1:',(g:=[list(x) for x in q[16].strip().split('\n')],(f:=lambda c,d,v: ((c,d) not in v and v.add((c,d)),(end:=0)) and [((g[c[1]][c[0]]=='/') and ((d==4) and (d:=1) or (d==3) and (d:=2) or (d==1) and (d:=4) or (d==2) and (d:=3)) or (g[c[1]][c[0]]=='\\') and ((d==4) and (d:=2) or (d==3) and (d:=1) or (d==1) and (d:=3) or (d==2) and (d:=4)) or (g[c[1]][c[0]]=='|') and ((d==4) and (v:=f(c,1,v)) and (d:=2) or (d==3) and (v:=f(c,1,v)) and (d:=2)) or (g[c[1]][c[0]]=='-') and ((d==2) and (d:=4) and (v:=f(c,3,v)) or (d==1) and (d:=4) and (v:=f(c,3,v))),(c:=(c[0]+1,c[1]) if d==4 else (c[0]-1,c[1]) if d==3 else (c[0],c[1]-1) if d==1 else (c[0],c[1]+1)),(((c,d) in v or c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and (end:=1)),not (c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and v.add((c,d))) for _ in it.takewhile(lambda _: not end,it.count())] and v)) and len(set([x[0] for x in f((0,0),4,set())])),'\nDay 16 Part 2:',(g:= [list(x) for x in q[16].strip().split('\n')],(f:=lambda c,d,v: ((c,d) not in v and v.add((c,d)),(end:=0)) and [((g[c[1]][c[0]]=='/') and ((d==4) and (d:=1) or (d==3) and (d:=2) or (d==1) and (d:=4) or (d==2) and (d:=3)) or (g[c[1]][c[0]]=='\\') and ((d==4) and (d:=2) or (d==3) and (d:=1) or (d==1) and (d:=3) or (d==2) and (d:=4)) or (g[c[1]][c[0]]=='|') and ((d==4) and (v:=f(c,1,v)) and (d:=2) or (d==3) and (v:=f(c,1,v)) and (d:=2)) or (g[c[1]][c[0]]=='-') and ((d==2) and (d:=4) and (v:=f(c,3,v)) or (d==1) and (d:=4) and (v:=f(c,3,v))),(c:=(c[0]+1,c[1]) if d==4 else (c[0]-1,c[1]) if d==3 else (c[0],c[1]-1) if d==1 else (c[0],c[1]+1)),(((c,d) in v or c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and (end:=1)),not (c[0] < 0 or c[0] >= len(g[0]) or c[1] < 0 or c[1] >= len(g)) and v.add((c,d))) for _ in it.takewhile(lambda _: not end,it.count())] and v),(m:=0),[(v:=f((x,0),2,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for x in range(len(g[0]))] and [(v:=f((x,len(g)-1),1,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for x in range(len(g[0]))] and [(v:=f((0,y),4,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for y in range(len(g))] and [(v:=f((len(g[0])-1,y),3,set())) and (m:=len(set([x[0] for x in v])) if len(set([x[0] for x in v])) > m else m) for y in range(len(g))] and m) and m) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🐍📅 Advent of Code One-Line Solutions 2 | As a personal challenge, I'm trying to solve every [Advent of Code](https://adventofcode.com/) problem in a single line of Python code. No, my solutions are not optimal. Nor readable. Nor useful in any other way. But it's fun, so here we go! 3 | 4 | I originally attempted this in 2022 and made it through about a dozen days. I'm now working on 2023 in real time! You can follow along on this repository or through [my Reddit posts](https://www.reddit.com/u/ImpossibleSav). 5 | 6 | Note that per copyright and [Eric Wastl's request](https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/), input files are not included in this repository, so you must replace the file paths if you would like to run this code. 7 | 8 | I'm using Python version `3.11.3`. The solutions should not require any additional packages (I'm only importing from the [Python Standard Library](https://docs.python.org/3/library/index.html)), but in the [tools](#tools) folder, I have a script for importing the input files from the Advent of Code server that uses [`requests`](https://pypi.org/project/requests/) and a visualization tool that uses [`matplotlib`](https://pypi.org/project/matplotlib/) and [`svgwrite`](https://pypi.org/project/svgwrite). 9 | 10 | ## Progress Tracking 11 | | Status | Description | 12 | | ------ | ----------- | 13 | | ❌ | Problem not attempted yet | 14 | | ✍ | Working on original solution | 15 | | ⭐ | Original (OG) solution finished, working on one-line solution | 16 | | ✅ | Completed both OG and one-line solutions | 17 | | ☑️ | Completed both solutions with help from others on the multi-line part | 18 | 19 | ### 2023 Solutions 20 | | Day | Part 1 | Part 2 | Commentary | 21 | |------------------|--------|--------|------------| 22 | | [01](2023/day-01.py) | ✅ | ✅ | This year, I'm removing my "no imports" restriction 😅 | 23 | | [02](2023/day-02.py) | ✅ | ✅ | Getting in a lot of RegEx practice this year! | 24 | | [03](2023/day-03.py) | ✅ | ✅ | Oh boy, the amount of RegEx I'm using is slowing down my computer... and [the Walrus](https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions) is back! | 25 | | [04](2023/day-04.py) | ✅ | ✅ | Pulling out some [dunder (magic) methods](https://docs.python.org/3/reference/datamodel.html#special-method-names) for this one! | 26 | | [05](2023/day-05.py) | ✅ | ☑️ | `lambda`s are making their first appearance... And credit to [Dylan Gray](https://github.com/DylanDmitri) for his immense help with my Part 2 OG solution! | 27 | | [06](2023/day-06.py) | ✅ | ✅ | `reduce` has joined the fray! | 28 | | [07](2023/day-07.py) | ✅ | ✅ | First solution I didn't use RegEx... there goes that challenge for myself 😂 | 29 | | [08](2023/day-08.py) | ✅ | ✅ | [`itertools.takewhile`](https://docs.python.org/3/library/itertools.html#itertools.takewhile) is a lifesaver! | 30 | | [09](2023/day-09.py) | ✅ | ✅ | Gonna be a busy few days so I might fall behind for a bit... | 31 | | [10](2023/day-10.py) | ✅ | ✅ | Not sure why this one took me until Day 17 to solve, but we finally did it! Proud of my Part 2 😁 | 32 | | [11](2023/day-11.py) | ✅ | ✅ | So glad I didn't need to modify my approach for Part 2! | 33 | | [12](2023/day-12.py) | ✅ | ☑️ | Credit to [Søren Fuglede Jørgensen](https://github.com/fuglede) for their solution for Part 2! | 34 | | [13](2023/day-13.py) | ✅ | ✅ | I did go back and rewrite Part 1 after solving Part 2. This one took me a while for some reason! | 35 | | [14](2023/day-14.py) | ✅ | ✅ | The hardest part is always the `while` loops! | 36 | | [15](2023/day-15.py) | ✅ | ✅ | My fastest solve yet! | 37 | | [16](2023/day-16.py) | ✅ | ✅ | Let's just ignore the `setrecursionlimit(30000)`... | 38 | | [17](2023/day-17.py) | ✍ | ❌ | | 39 | | [18](2023/day-18.py) | ⭐ | ✍ | | 40 | | [The Basilisk](2023/the-basilisk.py) ||| A single line of code that combines all of the above days' solutions into one! | 41 | 42 | ### 2022 Solutions 43 | Currently I am not working on 2022 problems, but this is where I left off: 44 | 45 | | Day | Part 1 | Part 2 | Commentary | 46 | |------------------|--------|--------|------------| 47 | | [01](2022/day-01.py) | ✅ | ✅ | | 48 | | [02](2022/day-02.py) | ✅ | ✅ | | 49 | | [03](2022/day-03.py) | ✅ | ✅ | | 50 | | [04](2022/day-04.py) | ✅ | ✅ | | 51 | | [05](2022/day-05.py) | ✅ | ✅ | This one is a bit cheese but I'm doing my best. Requires Python 3.8 (https://peps.python.org/pep-0572/). | 52 | | [06](2022/day-06.py) | ✅ | ✅ | | 53 | | [07](2022/day-07.py) | ✅ | ✅ | Even more cheese. But we got it! | 54 | | [08](2022/day-08.py) | ✅ | ✅ | Oh boy, I've started cheesing in my OG solutions now too. | 55 | | [09](2022/day-09.py) | ✅ | ✅ | Today's solution is brought to you by `x.insert(0, x.pop(0)+1)`. | 56 | | [10](2022/day-10.py) | ✅ | ✅ | | 57 | | [11](2022/day-11.py) | ✅ | ✅ | | 58 | | [12](2022/day-12.py) | ⭐ | ⭐ | | 59 | | [13](2022/day-13.py) | ✍ | ❌ | | 60 | | [14](2022/day-14.py) | ✅ | ✅ | | 61 | | [The Beast](2022/the-beast.py) ||| A single line of code that combines all of the above days' solutions into one! | 62 | 63 | 64 | ## Repo Organization 65 | ### Solutions 66 | Within each year's folder: 67 | - All the one-line solutions are combined into a single disgusting line of code that solves all the Advent of Code problems at once, nicknamed based on the year: 68 | - **2023:** [`the-basilisk`](2023/the-basilisk.py) 69 | - **2022:** [`the-beast`](2022/the-beast.py) 70 | - The `day-xx.py` files have my first solution attempts and the resulting one-liners. See them to better understand what the blasphemous one-liners do. 71 | 72 | ### Images 73 | I've created some visualizations and memes throughout the month. They can be found in the [images](https://github.com/savbell/advent-of-code-one-liners/blob/master/images/) folder. 74 | 75 | Below is an example vizualization of the length of each day's solution in the Basilisk as of Day 8. I automated creating parts of it; see the tools below. 76 | 77 | A snake with rainbow bands where each colour corresponds to how many characters were used to solve each Advent of Code problem 78 | 79 | ### Tools 80 | - **[`create-rainbow-line-svg.py`](tools/create-rainbow-line-svg.py)**: Creates a rainbow line SVG image from a list of numbers, with each band a calculated percent of the whole. Used to automatically generate the colours and proportions for the visualization above. Also included is a tool for calculating the character counts in my one-line combined solutions, e.g. [The Basilisk](2023/the-basilisk.py), or all your solution files in a given year if you provide your first day's file name. 81 | - **[`create-blank-solution.py`](tools/create-blank-solution.py)**: Creates a new file with a blank solution template for the given year and day. Written explicitly for myself, but feel free to modify it for your personal use if you'd like. 82 | - **[`import-input.py`](tools/import-input.py)**: Requests the AoC server for a given day's input and saves it as a new text file. Try to [limit your use](https://www.reddit.com/r/adventofcode/wiki/faqs/automation/) of this tool to once per day. 83 | 84 | ## Some Strategy Explanations 85 | Here are some fun ways I've been able to convert Python statements that normally require their own line into one-line expressions: 86 | - **List comprehensions:** This entire thing wouldn't be possible without Python's [list comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions), which allows you to have `for` and `if` statements within a single expression/line. 87 | - **Short-circuit (lazy) evaluation:** Python has [short-circuit evaluation for its Boolean operations](https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not), which means the second expression in a Boolean operation is only evaluated if the result of the first expression does not guarantee the final result of the expression. This allows me to strategically use `and` and `or` to determine the order that expressions are executed, skipping around when necessary. 88 | - **In-line assignment operator:** The [Walrus operator (`:=`)](https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions) allows you to create and assign variables within an expression. I discovered it trying to parse [Day 5 in 2022](2022/day-05.py), and it has since been [a hard carry](images/2023-day-05-walrus-meme.png). 89 | - **Updating a list element in-line:** Since the assignment operator cannot be used with subscripts, it cannot be used to update lists (e.g. `a[0] := 1` is invalid). My solution for [Day 9 in 2022](2022/day-09.py) was to pop the element, modify it, and then insert it back into the same position, e.g. `x.insert(0, x.pop(0)+1)`. Then, for [Day 4 in 2023](2023/day-04.py), I discovered the [`__setitem__()`](https://docs.python.org/3/reference/datamodel.html#object.__setitem__) method, which allows you to update a list element in-line, e.g. `x.__setitem__(0, x[0]+1)`. On [Day 5 in 2023](2023/day-05.py), I figured out [`x.__iadd__([0])`](https://docs.python.org/3/reference/datamodel.html#object.__iadd__) is equivalent to `x.append(0)`. 90 | - **In-line import statements:** After not using import statements in 2022 since it would technically make my solutions more than one line, I discovered the built-in [`__import__()`](https://docs.python.org/3/library/functions.html#import__) function in 2023 that has finally allowed me to use [RegEx](images/2023-day-03-regex-meme.png) in my solutions. 91 | - **My `while` loop within a list comprehension:** ~~I was very proud of discovering this while working on [2022's Day 8](2022/day-08.py). Since I wanted my list comprehension to end execution once a condition was met, I had a tracker variable turn `True` when it was and included it in the `for` condition. But to do this in a single line, I needed to add another `if` condition that simply creates and assigns the tracker variable `False`, making sure it ran before the main list comprehension was calculated. An example line with a tracker variable called `found`: `[(x < t[r][c]) or (found:=True) for x in t[r][:c][::-1] if not found] if not (found:=False) else ''`~~
**Update:** While solving [2023's Day 8](2023/day-08.py), I discovered [`itertools.takewhile(predicate, iterable)`](https://docs.python.org/3/library/itertools.html#itertools.takewhile), which solved my `while` loop problem in a much cleaner way! Thank goodness I removed my "no import" restriction for this year. 92 | 93 | ## Concluding Notes 94 | Potential employers: I promise my production code is much, much better than this. Please don't blacklist me :( 95 | 96 | ... but if you're looking to reduce the lines of code in your codebase, I've got some ideas! ;) 97 | -------------------------------------------------------------------------------- /images/2022-day-07-meme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2022-day-07-meme.png -------------------------------------------------------------------------------- /images/2022-day-10-beast-length.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2022-day-10-beast-length.png -------------------------------------------------------------------------------- /images/2023-day-03-regex-meme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2023-day-03-regex-meme.png -------------------------------------------------------------------------------- /images/2023-day-05-walrus-meme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2023-day-05-walrus-meme.png -------------------------------------------------------------------------------- /images/2023-day-06-the-basilisk-viz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2023-day-06-the-basilisk-viz.png -------------------------------------------------------------------------------- /images/2023-day-07-the-basilisk-viz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2023-day-07-the-basilisk-viz.png -------------------------------------------------------------------------------- /images/2023-day-08-the-basilisk-viz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2023-day-08-the-basilisk-viz.png -------------------------------------------------------------------------------- /images/2023-day-09-the-basilisk-viz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2023-day-09-the-basilisk-viz.png -------------------------------------------------------------------------------- /images/2023-day-16-the-basilisk-viz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/2023-day-16-the-basilisk-viz.png -------------------------------------------------------------------------------- /images/why-use-long-code-meme.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savbell/advent-of-code-one-liners/82ce2339fafb8000b63dda165b464c65db4e7c12/images/why-use-long-code-meme.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2023.11.17 2 | charset-normalizer==3.3.2 3 | contourpy==1.2.0 4 | cycler==0.12.1 5 | fonttools==4.46.0 6 | idna==3.6 7 | kiwisolver==1.4.5 8 | matplotlib==3.8.2 9 | numpy==1.26.2 10 | packaging==23.2 11 | Pillow==10.1.0 12 | pyparsing==3.1.1 13 | python-dateutil==2.8.2 14 | requests==2.31.0 15 | six==1.16.0 16 | svgwrite==1.4.3 17 | urllib3==2.1.0 18 | -------------------------------------------------------------------------------- /tools/create-blank-solution.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This program creates a blank template for my one-line Advent of Code solutions. 3 | It doesn't have much use beyond that. 4 | Created by Sav Bell (https://github.com/savbell). 5 | ''' 6 | 7 | 8 | ################################# FUNCTIONS ################################# 9 | def create_aoc_template(day, file_path, file_name=None): 10 | if file_name is None: 11 | file_name = f"day-{str(day).zfill(2)}.py" 12 | template = f"""''' 13 | 2023 Advent of Code - Day {day:02} (https://adventofcode.com/2023/day/{day}) 14 | Solution by Sav Bell (https://github.com/savbell) 15 | Challenge: Solve every day in a single line of Python code. 16 | See full progress at https://github.com/savbell/advent-of-code-one-liners 17 | ''' 18 | 19 | # Input files not included in repo per copyright & Eric Wastl's request. 20 | # https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/ 21 | # Replace with path to your personal input file if you would like to run the code. 22 | input_file = '2023/day-{day:02}.txt' 23 | 24 | # To match the format of input files for the Basilisk. 25 | q = {{ {day}: open(input_file).read().strip() }} 26 | 27 | 28 | ######################### PART 1: MULTI-LINE SOLUTION ######################### 29 | # Haven't started yet... 30 | 31 | ########################## PART 1: ONE-LINE SOLUTION ########################## 32 | # Haven't started yet... 33 | 34 | 35 | ######################## PART 2: MULTI-LINE SOLUTION ########################## 36 | # Haven't started yet... 37 | 38 | ########################## PART 2: ONE-LINE SOLUTION ########################## 39 | # Haven't started yet... 40 | """ 41 | with open(file_path + file_name, 'w') as file: 42 | file.write(template) 43 | 44 | 45 | ################################# EXECUTION ################################# 46 | create_aoc_template(14, '2023/') 47 | -------------------------------------------------------------------------------- /tools/create-rainbow-line-svg.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This program creates a rainbow line visualization from a list of percentages or numbers. 3 | I'm using it to visualize the length of my one-line Python solutions for Advent of Code. 4 | It can also be used to automatically count and visualize the length of your solutions if 5 | you change the options below. 6 | Created by Sav Bell (https://github.com/savbell). 7 | ''' 8 | 9 | from matplotlib.colors import to_hex 10 | import matplotlib.pyplot as plt 11 | import re 12 | import svgwrite 13 | import os 14 | 15 | ################################## OPTIONS ################################## 16 | svg_path = 'images/rainbow-line-visualization.svg' # Where to save the SVG 17 | color_mapping = 'turbo' # https://matplotlib.org/stable/users/explain/colors/colormaps.html 18 | solutions_folder = '2023/' # You may need your full path 19 | first_day_file = 'day-01.py' # Used to automatically determine your naming convention 20 | 21 | 22 | ################################# FUNCTIONS ################################# 23 | # Creates and saves a rainbow line SVG from a list of numbers. 24 | # Returns a list of [number, percentage, color] for each rectangle. 25 | def create_rainbow_line(numbers, color_mapping=color_mapping, svg_path=svg_path): 26 | total = sum(numbers) 27 | normalized_percentages = [p / total for p in numbers] 28 | 29 | dwg = svgwrite.Drawing(svg_path, size=(1000, 200)) 30 | 31 | start_x = 0 32 | layer = dwg.add(dwg.g(id=f'{color_mapping}-line')) 33 | colormap = plt.get_cmap(color_mapping) 34 | colors = [] 35 | for i, p in enumerate(normalized_percentages): 36 | color = to_hex(colormap(i / len(numbers))) 37 | colors.append([numbers[i], p, color]) 38 | 39 | # Calculate width of the rectangle proportionally 40 | width = p * 1000 41 | 42 | layer.add(dwg.rect(insert=(start_x, 0), size=(width, 200), fill=color, id=f'Color{i+1}')) 43 | 44 | # Update the start position for the next rectangle 45 | start_x += width 46 | 47 | dwg.save() 48 | print('SVG saved to', svg_path) 49 | 50 | 51 | # Counts the number of characters in a file. 52 | def count_file_chars(file_path): 53 | with open(file_path, 'r') as file: 54 | file_content = file.read() 55 | return len(file_content.strip()) 56 | 57 | 58 | # Creates a list [[day, None], file_path, num_chars] based on the name of the first day's solution. 59 | # Assumes your files follow a naming convention like "day-01.py", "1.js", etc. 60 | # Does not account for if you saved each part as a separate file (that's the None in [day, None]). 61 | def count_aoc_solutions(folder_path, first_day_file): 62 | base_name, ext = os.path.splitext(first_day_file) 63 | match = re.search(r'(\D*)(\d+)(\D*)', base_name) 64 | prefix, day, postfix = match.groups() 65 | 66 | pattern = re.compile(rf'^{re.escape(prefix)}(\d+){re.escape(postfix)}{re.escape(ext)}$') 67 | 68 | solutions = [] 69 | for file in os.listdir(folder_path): 70 | match = pattern.match(file) 71 | if match: 72 | day = int(match.group(1)) 73 | file_path = os.path.join(folder_path, file) 74 | solutions.append([[day, None], file_path, count_file_chars(file_path)]) 75 | 76 | # Sorting the list based on day 77 | return sorted(solutions, key=lambda x: x[0]) 78 | 79 | 80 | # Uses RegEx to calculate the number of characters in each part of each day's solution. 81 | # Returns a list with each element in the format [[day, part], file_path, num_chars]. 82 | # Explicitly written to be used with my combined one-line solutions. 83 | def count_oneliners(file_path): 84 | with open(file_path, 'r') as file: 85 | file_content = file.read() 86 | 87 | pattern = r'(Day \d{2} Part \d{1,2}:.*?)(?=Day \d{2} Part \d{1,2}:|$)' 88 | matches = re.findall(pattern, file_content, re.DOTALL) 89 | solutions = [] 90 | 91 | for match in matches: 92 | title, content = match.split(':', 1) 93 | day, part = map(int, re.findall(r'\d+', title)[:2]) 94 | num_chars = len(content.strip()) 95 | print(str(title).rjust(2) + ' - ' + str(num_chars).rjust(3)) 96 | solutions.append([[day, part], file_path, num_chars]) 97 | 98 | return sorted(solutions, key=lambda x: x[0]) 99 | 100 | # Creates a rainbow line SVG from the number of characters in each part of each day's solution. 101 | def create_oneliners_svg(file_path, color_mapping=color_mapping, svg_path=svg_path): 102 | solutions = count_oneliners(file_path) 103 | create_rainbow_line([s[2] for s in solutions], color_mapping, svg_path) 104 | 105 | # Creates a rainbow line SVG from the number of characters in each day's solution. 106 | def create_solutions_svg(folder_path, first_day_file, color_mapping=color_mapping, svg_path=svg_path): 107 | solutions = count_aoc_solutions(folder_path, first_day_file) 108 | create_rainbow_line([s[2] for s in solutions], color_mapping, svg_path) 109 | 110 | 111 | ################################# EXECUTION ################################# 112 | # Find the number of characters in my one-line solution and create a rainbow line SVG. 113 | create_oneliners_svg('2023/the-basilisk.py', color_mapping, f'images/oneliners-{color_mapping}-line.svg') 114 | 115 | # Find the number of characters for all solution files and create a rainbow line SVG. 116 | create_solutions_svg(solutions_folder, first_day_file, color_mapping, f'images/aoc-solutions-{color_mapping}-line.svg') 117 | 118 | # Another example: Make a rainbow line SVG from a list of numbers. Will be saved to path set in options. 119 | # create_rainbow_line([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) 120 | -------------------------------------------------------------------------------- /tools/import-input.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This program automatically downloads the input file for a given day of Advent of Code. 3 | Be sure to replace the session token with your own. 4 | NOTE: Try not to overload the servers. Your input file will never change, so no need to download it more than once. 5 | Also do not send more than one request every 15 minutes. Try to only download the input on the day you need it. 6 | More info: https://www.reddit.com/r/adventofcode/wiki/faqs/automation/ 7 | Created by Sav Bell (https://github.com/savbell). 8 | ''' 9 | 10 | import requests 11 | 12 | 13 | ################################## OPTIONS ################################## 14 | # How to get your session token: https://github.com/wimglenn/advent-of-code-wim/issues/1 15 | session_token = 'your_session_token' 16 | 17 | 18 | ################################# FUNCTIONS ################################# 19 | def import_aoc_input(year, day, file_path, file_name=None): 20 | if file_name is None: 21 | file_name = f'day-{str(day).zfill(2)}.txt' 22 | 23 | url = f'https://adventofcode.com/{year}/day/{day}/input' 24 | headers = { 25 | 'User-Agent': 'github.com/savbell/advent-of-code-one-liners by sav@savbell.com', 26 | 'Cookie': f'session={session_token}' 27 | } 28 | 29 | response = requests.get(url, headers=headers) 30 | if response.status_code == 200: 31 | with open(file_path + file_name, 'w') as file: 32 | file.write(response.text) 33 | else: 34 | print(f'Failed to fetch input: HTTP {response.status_code}') 35 | 36 | 37 | ################################# EXECUTION ################################# 38 | import_aoc_input(2023, 6, '2023/') 39 | --------------------------------------------------------------------------------