Skip to content

Instantly share code, notes, and snippets.

@JakeCoxon
Last active March 8, 2023 23:05
Show Gist options
  • Save JakeCoxon/cf818f658a303e77c04c312bc04498fe to your computer and use it in GitHub Desktop.
Save JakeCoxon/cf818f658a303e77c04c312bc04498fe to your computer and use it in GitHub Desktop.
Advent of Code 2021
# Python 2 only because they removed lambda argument unpacking in 3.0
import math, sys
from functools import reduce
from itertools import izip_longest
# AOC Day 1 part 1
print(len((lambda nums: [1 for x, y in zip(nums[:], nums[1:]) if y > x])
([int(x) for x in open("input1.txt").read().split()])))
# AOC Day 1 part 2
print(len((lambda windows: [1 for x, y in zip(windows[:], windows[1:]) if y > x])(
(lambda nums: [sum(w) for w in zip(nums[:], nums[1:], nums[2:])])(
[int(x) for x in open("input1.txt").read().split()]
))))
# AOC Day 2 part 1
print((lambda depths, inputs:
sum([depths.get(cmd, 0) * int(dist) for cmd, dist in inputs]) * sum([int(dist) for cmd, dist in inputs if cmd == 'forward']))(
{'down': 1, 'up': -1}, [x.split() for x in open("input2.txt").read().split('\n')]))
# AOC Day 2 part 2
print((lambda (horizontal, depth, aim): horizontal * depth)((
lambda cmds, inputs: reduce(lambda (horizontal, depth, aim), (cmd, dist): (
horizontal + cmds[cmd][0] * int(dist), depth + cmds[cmd][1] * int(dist) * aim, aim + cmds[cmd][2] * int(dist)
), inputs,(0,0,0)))({'forward': (1, 1, 0), 'down': (0, 0, 1), 'up': (0, 0, -1)},
[x.split() for x in open("input2.txt").read().split('\n')])))
# AOC Day 3 part 1
print((lambda (gamma, epsilon): (int("".join(gamma), 2) * int("".join(epsilon), 2)))(
zip(*[('1', '0') if len([y for y in x if y == '1']) > len(x)/2 else ('0', '1')
for x in zip(*open("input3.txt").read().split('\n'))])))
# AOC Day 3 part 2
print((lambda inputs: (lambda ((oxy,), (co2,)): (int(oxy, 2) * int(co2, 2)))(
reduce((lambda (max_rows, min_rows), col_idx: (lambda max_common, min_common: (
max_rows if len(max_rows) == 1 else [row for row in max_rows if row[col_idx] == max_common],
min_rows if len(min_rows) == 1 else [row for row in min_rows if row[col_idx] == min_common]
))(
'1' if len([y for y in zip(*max_rows)[col_idx] if y == '1']) >= math.ceil(float(len(zip(*max_rows)[col_idx])) / 2) else '0',
'0' if len([y for y in zip(*min_rows)[col_idx] if y == '1']) >= math.ceil(float(len(zip(*min_rows)[col_idx])) / 2) else '1'
)), range(len(inputs[0])), (inputs, inputs))))(open("input3.txt").read().split('\n')))
# AOC Day 4 part 1
print((lambda input:
reduce(lambda (result, boards), num: reduce(lambda (result, new_boards), board:
(result, []) if result != None else (lambda b: (
sum([c for c in b if c is not None]) * num if
any([all([c == None for c in s]) for s in [b[x:x+5] for x in range(0,25,5)] + [b[x:25:5] for x in range(0,5)]])
else None, new_boards + [b])
)([None if c == num else c for c in board]), boards, (result, [])), [int(x) for x in input[0].split(",")],
(None, [[int(y) for y in x.split()] for x in input[1:]])))(input=open("input4.txt").read().split('\n\n'))[0])
# AOC Day 4 part 2
print((lambda input:
reduce(lambda (result, boards), num: reduce(lambda (result, new_boards), board:
(result, []) if not boards else (lambda b: (
(sum([c for c in b if c is not None]) * num, new_boards) if
any([all([c == None for c in s]) for s in [b[x:x+5] for x in range(0,25,5)] + [b[x:25:5] for x in range(0,5)]])
else (result, new_boards + [b]))
)([None if c == num else c for c in board]), boards, (result, [])), [int(x) for x in input[0].split(",")],
(None, [[int(y) for y in x.split()] for x in input[1:]])))(input=open("input4.txt").read().split('\n\n'))[0])
# AOC Day 5 part 1
print(len([x for x in
reduce(lambda map, ((x1, y1), (x2, y2)):
reduce(lambda map, it:
map.update({((it, y1) if y1 == y2 else (x1, it)): map.get((it, y1) if y1 == y2 else (x1, it), 0) + 1}) or map if x1 == x2 or y1 == y2 else map
, (range(x1, x2+1, 1) if x1 < x2 else range(x1, x2-1, -1)) if y1 == y2 else (range(y1, y2+1, 1) if y1 < y2 else range(y1, y2-1, -1)), map)
, [[[int(z) for z in y.strip().split(',')] for y in x.split("->")] for x in open("input5.txt").read().split('\n')], dict())
.values() if x > 1]))
# AOC Day 5 part 2
print(len([x for x in
reduce(lambda map, ((x1, y1), (x2, y2)):
reduce(lambda map, (x, y):
(lambda point: map.update({point: map.get(point, 0) + 1}) or map)((x1 if x is None else x, y1 if y is None else y))
, list(izip_longest(range(x1, x2+1, 1) if x1 < x2 else range(x1, x2-1, -1),range(y1, y2+1, 1) if y1 < y2 else range(y1, y2-1, -1)
)), map)
, [[[int(z) for z in y.strip().split(',')] for y in x.split("->")] for x in open("input5.txt").read().split('\n')], dict())
.values() if x > 1]))
# AOC Day 6 part 1
print(sum(reduce(lambda timers, day:
[timers[0] if n == 8 else (timers[7] + timers[0] if n == 6 else timers[n + 1]) for n in range(9)]
, range(80)
, [len([1 for x in [int(x) for x in open("input6.txt").read().split(',')] if x == n]) for n in range(9)])))
# AOC Day 6 part 2
print(sum(reduce(lambda timers, day:
[timers[0] if n == 8 else (timers[7] + timers[0] if n == 6 else timers[n + 1]) for n in range(9)]
, range(256)
, [len([1 for x in [int(x) for x in open("input6.txt").read().split(',')] if x == n]) for n in range(9)])))
# AOC Day 7 part 1
print((lambda input: min([sum([abs(n - x) for x in input]) for n in range(max(input))]))([int(x) for x in open("input7.txt").read().split(',')]))
# AOC Day 7 part 2
print((lambda input: min([sum([int(float(abs(n - x)) / 2 * (1 + abs(n - x))) for x in input]) for n in range(max(input))]))
([int(x) for x in open("input7.txt").read().split(',')]))
# AOC Day 8 part 1
print(sum([sum([1 for y in x.split("|")[1].split() if len(y) in [2, 3, 4, 7]]) for x in open("input8.txt").read().split('\n')]))
# AOC Day 8 part 2
print(sum([
(lambda (inputs, out): (lambda length_map, wires_map, digit_map, counts: (lambda mapping:
sum([digit_map[sum([(digit & pow(2, n) and mapping[pow(2, n)] or 0)
for n in range(7)])] * pow(10, 3-idx) for (idx, (digit, len)) in enumerate(out)])
)(mapping={
next(x for x, count in counts if count == wires_map[n][0] and (x & length_map[wires_map[n][1]] != 0) == wires_map[n][2]): pow(2, n) for n in range(7)
}))(
length_map={b:a for a, b in inputs},
wires_map=[(8, 4, False), (6, 2, False), (8, 2, True), (7, 4, True), (4, 2, False), (9, 3, True), (7, 4, False)],
digit_map={119: 0, 36: 1, 93: 2, 109: 3, 46: 4, 107: 5, 123: 6, 37: 7, 127: 8, 111: 9},
counts=[(pow(2, x), count) for x, count in list(enumerate([sum(x) for x in zip(*[[(1 if pow(2, n) & x[0] else 0) for n in range(8)] for x in inputs])]))]
))([[(sum([pow(2, ord(c) - ord('a')) for c in z]), len(z)) for z in y.split()] for y in x.split("|")])
for x in open("input8.txt").read().split('\n')]))
# AOC Day 9 part 1
print((lambda input: sum([sum([col + 1 if all([not (0 <= next_y < len(input) and 0 <= next_x < len(input[0])) or col < input[next_y][next_x]
for next_x, next_y in [(x-1,y),(x+1,y),(x,y+1),(x,y-1)]]) else 0
for x, col in enumerate(row)]) for y, row in enumerate(input)]))([[int(b) for b in a] for a in open("input9.txt").read().split('\n')]))
# AOC Day 9 part 2
print((lambda out: out.sort(reverse=True) or reduce(lambda a,b: a*b, out[:3]))((lambda visit, input: [
1 + sum(visit(x,y,input,{},True,lambda *args: 1 + sum(visit(*args)))) if not any(visit(x,y,input,{},False,lambda *args: True)) else 0
for y, row in enumerate(input) for x, col in enumerate(row)])(
visit=lambda x, y, input, visit_map, up, visit:
visit_map.update({(x,y): True}) or [0 if not (0 <= next_y < len(input) and 0 <= next_x < len(input[0])) or
visit_map.get((next_x,next_y)) or input[next_y][next_x] == 9 or (input[next_y][next_x] < input[y][x]) == up else
visit(next_x, next_y, input, visit_map, up, visit) for next_x, next_y in [(x-1,y),(x+1,y),(x,y+1),(x,y-1)]],
input=[[int(b) for b in a] for a in open("input9.txt").read().split('\n')])))
# AOC Day 10 part 1
print((lambda input, chars, scores: sum([x for x in [(lambda stack: reduce(lambda acc, char:
acc if acc else stack.append(char) if chars.get(char) else (stack.pop() and None if char == chars.get(stack[-1]) else scores[char])
, line, None))([]) for line in input] if x]))(
input=open("input10.txt").read().split('\n'),
chars={'(': ')', '[': ']', '{': '}', '<': '>'},
scores={')': 3, ']': 57, '}': 1197, '>': 25137}
))
# AOC Day 10 part 2
print((lambda scores: scores.sort() or scores[len(scores)/2])((lambda input, chars, scores: [x for x in [(lambda stack:
reduce(lambda acc, char: acc * 5 + scores[chars[char]], stack.reverse() or stack, 0) if
reduce(lambda acc, char: None if acc is None else stack.append(char) or stack if chars.get(char) else (stack.pop() or stack if char == chars.get(stack[-1]) else None)
, line, stack) else None)([]) for line in input] if x])(
input=open("input10.txt").read().split('\n'),
chars={'(': ')', '[': ']', '{': '}', '<': '>'},
scores={')': 3, ']': 57, '}': 1197, '>': 25137, ')': 1, ']': 2, '}': 3, '>': 4}
)))
# AOC Day 11 part 1
print((lambda input, do_board: reduce(lambda (flashes, input), iteration:
(lambda board: (flashes + sum([1 if col > 9 else 0 for row in board for col in row]),
[[0 if col > 9 else col for col in row] for row in board])
)(do_board(do_board, input, {(x,y): 1 for y, row in enumerate(input) for x, col in enumerate(row)}, {}))
, range(100), (0, input)))(
input=[[int(b) for b in a] for a in open("input11.txt").read().split('\n')],
do_board=lambda do_board, input, in_stage, out_stage:
(lambda res: do_board(do_board, res, out_stage, {}) if any([x > 0 for x in out_stage.values()]) else res)(
[[(lambda num: [out_stage.update({(x+a,y+b): out_stage.get((x+a,y+b), 0) + 1}) if not (a==0 and b==0) else 1
for a in range(-1,2) for b in range(-1,2)] and (num + 100) if num >= 10 and num < 20 else num
)(col + in_stage.get((x,y), 0)) for x, col in enumerate(row)] for y, row in enumerate(input)])
)[0])
# AOC Day 11 part 2
print((lambda input, do_board: reduce(lambda (res, input), iteration:
(lambda board: (res, board) if res is not None else ((iteration+1, board) if all([col > 9 for row in board for col in row])
else (None, [[0 if col > 9 else col for col in row] for row in board]))
)(do_board(do_board, input, {(x,y): 1 for y, row in enumerate(input) for x, col in enumerate(row)}, {}))
, range(1000), (None, input)))(
input=[[int(b) for b in a] for a in open("input11.txt").read().split('\n')],
do_board=lambda do_board, input, in_stage, out_stage:
(lambda res: do_board(do_board, res, out_stage, {}) if any([x > 0 for x in out_stage.values()]) else res)(
[[(lambda num: [out_stage.update({(x+a,y+b): out_stage.get((x+a,y+b), 0) + 1}) if not (a==0 and b==0) else 1
for a in range(-1,2) for b in range(-1,2)] and (num + 100) if num >= 10 and num < 20 else num
)(col + in_stage.get((x,y), 0)) for x, col in enumerate(row)] for y, row in enumerate(input)])
)[0])
# AOC Day 12 part 1
print((lambda map, visit, small: visit(visit, small, map, {}, 'start'))(
map=reduce(lambda map, (a, b): map.update({a: map.get(a, []) + [b]}) or map.update({b: map.get(b, []) + [a]}) or map
, [x.split('-') for x in open("input12.txt").read().split('\n')], {}),
visit=lambda visit, small, map, visited, current: sum([
1 if next == 'end' else (
(small(visit, small, map, visited.copy(), next) if next[0].lower() == next[0] else visit(visit, small, map, visited, next))
if not visited.get(next) and next != 'start' else 0) for next in map.get(current, [])])
, small=lambda visit, small, map, visited, next: visit(visit, small, map, visited.update({next: True}) or visited, next)
))
# AOC Day 12 part 2
print((lambda map, visit, small: visit(visit, small, map, {}, 'start', False))(
map=reduce(lambda map, (a, b): map.update({a: map.get(a, []) + [b]}) or map.update({b: map.get(b, []) + [a]}) or map
, [x.split('-') for x in open("input12.txt").read().split('\n')], {}),
visit=lambda visit, small, map, visited, current, has_visited_small_twice: sum([
1 if next == 'end' else (
(small(visit, small, map, visited.copy(), next, has_visited_small_twice) if next[0].lower() == next[0] else
visit(visit, small, map, visited, next, has_visited_small_twice))
if visited.get(next, 0) <= (0 if has_visited_small_twice else 1) and next != 'start' else 0
) for next in map.get(current, [])])
, small=lambda visit, small, map, visited, next, has_visited_small_twice:
visit(visit, small, map, visited.update({next: visited.get(next, 0) + 1}) or visited, next, has_visited_small_twice or visited.get(next) == 2)
))
# AOC Day 13 part 1
print((lambda input: (lambda folds: len({(x,y) if x < folds[0][1] else (2*folds[0][1] - x, y) for x,y in
{tuple([int(y) for y in x.split(',')]) for x in input[0].split('\n')}}))(
[('x' in x.split('=')[0],int(x.split('=')[1])) for x in input[1].split('\n')]
))(open("input13.txt").read().split('\n\n')))
# AOC Day 13 part 2
print((lambda input: (lambda folds: (lambda result:
"\n".join(["".join(['#' if (x,y) in result else ' ' for x in range(max(x for x, y in result)+1)])
for y in range(max(y for x, y in result)+1)]))(
reduce(lambda coords, (hor, fold):
{(x,y) if x < fold else (2*fold - x, y) for x,y in coords} if hor else {(x,y) if y < fold else (x, 2*fold - y) for x,y in coords}, folds
, {tuple([int(y) for y in x.split(',')]) for x in input[0].split('\n')})
))([('x' in x.split('=')[0],int(x.split('=')[1])) for x in input[1].split('\n')]))(open("input13.txt").read().split('\n\n')))
# AOC Day 14 part 1 and 2
print((lambda input: (lambda template, insertions: (lambda count_list: count_list.sort(key=lambda x: x[1]) or count_list[-1][1] - count_list[0][1])(
list(reduce(lambda counts, (pair, value): counts.update({
pair[0]: counts.get(pair[0], 0) + value,
}) or counts, reduce(lambda template, num:
[template.update({ pair: template.get(pair) - value }) or
template.update({ pair[0] + insertions[pair]: template.get(pair[0] + insertions[pair], 0) + value }) or
template.update({ insertions[pair] + pair[1]: template.get(insertions[pair] + pair[1], 0) + value })
for pair, value in list(template.items())
] and template, range(40), template).items(), {input[0][-1]: 1}).items())))(
template=reduce(lambda template, (x, y): template.update({x+y: template.get(x+y, 0) + 1}) or template, zip(input[0], input[0][1:]), {}),
insertions={x.split(' -> ')[0]:x.split(' -> ')[1] for x in input[1].split('\n')}
))(open("input14.txt").read().split('\n\n')))
# AOC Day 15 part 1
print((lambda input: (lambda path, unvisted_nodes: reduce(lambda acc, num: (lambda (minx, miny):
[path.update({n: min(path[n], path[(minx, miny)] + input[n[1]][n[0]])})
for n in [(x, y) for x, y in [(minx-1,miny),(minx+1,miny),(minx,miny+1),(minx,miny-1)] if 0 <= x < len(input[0]) and 0 <= y < len(input)]] and unvisted_nodes.remove((minx, miny))
)(min(unvisted_nodes, key=lambda pos: path[pos])), range(len(input[0]) * len(input)), 0) or path[(len(input) - 1, len(input[0]) - 1)])(
{(x,y): 0 if x == y == 0 else sys.maxsize for y, rows in enumerate(input) for x, cols in enumerate(rows)},
[(x,y) for y, rows in enumerate(input) for x, cols in enumerate(rows)]
))([[int(y) for y in x] for x in open("input15.txt").read().split('\n')]))
# AOC Day 15 part 2
print((lambda iterator, path, frontier, visited_nodes, unvisted_nodes, input:
reduce(lambda (minx, miny), num: [
(lambda new_value: path.update({(nx, ny): new_value}) or frontier.add((nx, ny))
if new_value < path.get((nx, ny), sys.maxsize) and (nx, ny) not in visited_nodes else None)
(new_value=path[(minx, miny)] + (input[ny % len(input[0])][nx % len(input)] + (nx / len(input) + ny / len(input[0])) - 1) % 9 + 1)
for nx, ny in [(x, y) for x, y in [(minx-1,miny),(minx+1,miny),(minx,miny+1),(minx,miny-1)] if 0 <= x < len(input[0]) * 5 and 0 <= y < len(input) * 5]
] and (lambda next: frontier.remove(min(frontier, key=lambda pos: path[pos])) or iterator.append(len(iterator)) or visited_nodes.add(next) or next)(
min(frontier, key=lambda pos: path[pos])
) if frontier else path.get((len(input) * 5 - 1, len(input[0]) * 5 - 1)), iterator, (0,0))
)([0], {(0,0):0}, set([(0,0)]), set([(0,0)]), None, [[int(y) for y in x] for x in open("input15.txt").read().split('\n')]))
# AOC Day 16 part 1
print((lambda iterator: (lambda funcs: reduce(lambda acc, it: iterator.append(1) or acc() if callable(acc) else acc, iterator, funcs["read_packet"](funcs,
"".join([bin(int(x, 16))[2:] .zfill(4)for x in open("input16.txt").read()]), lambda x, input: x))
)({
"read": lambda input, length, next: lambda: next(int(input[:length], 2), input[length:]),
"read_packet": lambda funcs, input, next: funcs["read"](input, 3, lambda version, input:
funcs["read"](input, 3, lambda type_id, input:
funcs["read_literal_part"](funcs, input, [], True, lambda num, input: next(version, input)) if type_id == 4 else
funcs["read_operator"](funcs, input, lambda values, input: next(version + sum(values), input))
)),
"read_operator": lambda funcs, input, next:
funcs["read"](input, 1, lambda length_type_id, input:
funcs["read"](input, 15, lambda total_length_bits, input: funcs["read_length_part"](funcs, input, total_length_bits, [], next)) if length_type_id == 0
else funcs["read"](input, 11, lambda num_of_sub_packets, input: funcs["read_num_part"](funcs, input, num_of_sub_packets, [], next))),
"read_num_part": lambda funcs, input, num_of_sub_packets, values, next:
next(values, input) if num_of_sub_packets == 0 else funcs["read_packet"](funcs, input, lambda num, input:
funcs["read_num_part"](funcs, input, num_of_sub_packets - 1, values.append(num) or values, next)),
"read_length_part": lambda funcs, input, length, values, next:
next(values, input) if length == 0 else funcs["read_packet"](funcs, input, lambda num, input2:
funcs["read_length_part"](funcs, input2, length - (len(input) - len(input2)), values.append(num) or values, next)),
"read_literal_part": lambda funcs, input, segments, more, next:
funcs["read"](input, 1, lambda more, input:
funcs["read"](input, 4, lambda segment, input: funcs["read_literal_part"](funcs, input, [segments.insert(0, segment)] and segments, more, next))
) if more else next(sum(x << i * 4 for i, x in enumerate(segments)), input)
}))([0]))
# AOC Day 16 part 2
print((lambda iterator: (lambda funcs: reduce(lambda acc, it: iterator.append(1) or acc() if callable(acc) else acc, iterator, funcs["read_packet"](funcs,
"".join([bin(int(x, 16))[2:] .zfill(4)for x in open("input16.txt").read()]), lambda x, input: x))
)({
0: sum, 2: min, 3: max,
1: lambda it: reduce(lambda a,b:a*b, it, 1), 5: lambda (a,b): 1 if a>b else 0, 6: lambda (a,b): 1 if a<b else 0, 7: lambda (a,b): 1 if a==b else 0,
"read": lambda input, length, next: lambda: next(int(input[:length], 2), input[length:]),
"read_packet": lambda funcs, input, next: funcs["read"](input, 3, lambda version, input:
funcs["read"](input, 3, lambda type_id, input:
funcs["read_literal_part"](funcs, input, [], True, lambda num, input: next(num, input)) if type_id == 4 else
funcs["read_operator"](funcs, input, lambda values, input: next(funcs[type_id](values), input))
)),
"read_operator": lambda funcs, input, next:
funcs["read"](input, 1, lambda length_type_id, input:
funcs["read"](input, 15, lambda total_length_bits, input: funcs["read_length_part"](funcs, input, total_length_bits, [], next)) if length_type_id == 0
else funcs["read"](input, 11, lambda num_of_sub_packets, input: funcs["read_num_part"](funcs, input, num_of_sub_packets, [], next))),
"read_num_part": lambda funcs, input, num_of_sub_packets, values, next:
next(values, input) if num_of_sub_packets == 0 else funcs["read_packet"](funcs, input, lambda num, input:
funcs["read_num_part"](funcs, input, num_of_sub_packets - 1, values.append(num) or values, next)),
"read_length_part": lambda funcs, input, length, values, next:
next(values, input) if length == 0 else funcs["read_packet"](funcs, input, lambda num, input2:
funcs["read_length_part"](funcs, input2, length - (len(input) - len(input2)), values.append(num) or values, next)),
"read_literal_part": lambda funcs, input, segments, more, next:
funcs["read"](input, 1, lambda more, input:
funcs["read"](input, 4, lambda segment, input: funcs["read_literal_part"](funcs, input, [segments.insert(0, segment)] and segments, more, next))
) if more else next(sum(x << i * 4 for i, x in enumerate(segments)), input)
}))([0]))
# AOC Day 17 part 1
print(lambda bottom: (bottom - 1) * bottom / 2)(abs(int("target area: x=124..174, y=-123..-86".split('=')[2].split('..')[0])))
# AOC Day 17 part 2
print((lambda ((left, right), (bottom, top)): sum([1 for vx in range(0, right + 1) for vy in range(bottom, abs(bottom)) if
(lambda state: any((True if state['x'] >= left and state['x'] <= right and state['y'] <= top and state['y'] >= bottom else
state.update({'x': state['x'] + state['vx'], 'y': state['y'] + state['vy'], 'vx': state['vx'] - 1 if state['vx'] > 0 else 0, 'vy': state['vy'] - 1}) for i in range(300))))(
{'vx': vx, 'vy': vy, 'x': 0, 'y': 0}
)]))([[int(y) for y in x.split('..')] for x in "target area: x=124..174, y=-123..-86"[15:].split(", y=")]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment