From here, you can access all of the events:
15 | 16 | 17 | 18 | 19 | 20 | 21 |2 | .---_ 3 | / / /\| 4 | / / | \ * 5 | / / \ \ MERRY CHRISTMAS! 6 | / / / \ \ -- seligman99 7 | ./~~~~~~~~~~~\. 8 | ( .",^. -". '.~ ) 9 | '~~~~~~~~~~~~~' 10 |-------------------------------------------------------------------------------- /2019/other/mand_intcode/mandelbrot_intcode.txt: -------------------------------------------------------------------------------- 1 | 1101,0,-53,203,1101,0,-37,204,1101,0,-1,205,1007,205,15,202,1006,202,104,1001,205,1,205,2,204,204,202,1002,202,-1,202,2,203,203,206,1,206,202,206,2,203,204,207,1002,207,2,207,101,0,206,209,1101,0,25,210,1101,0,62,212,1105,1,155,1,211,2,203,101,0,207,209,1101,0,25,210,1101,0,81,212,1105,1,155,1,211,6,204,2,203,203,206,2,204,204,202,1,206,202,202,1007,202,15625,202,1005,202,12,4,2,4,6,1008,205,15,202,1005,202,122,1001,205,96,205,1006,202,126,1101,0,32,205,4,205,1001,2,1,2,1007,2,22,202,1005,202,0,1101,0,-53,2,1001,6,1,6,1007,6,38,202,1005,202,0,99,102,-1,210,210,1007,209,0,208,1006,208,170,102,-1,209,209,1101,0,0,211,1007,209,1,202,1005,202,192,1001,211,1,211,1,209,210,209,1006,202,174,6,208,212,102,-1,211,211,105,1,212 -------------------------------------------------------------------------------- /2019/other/mand_intcode/merry_xmas_int.txt: -------------------------------------------------------------------------------- 1 | 1,142,142,317,1101,0,11,320,1105,1,136,1008,319,99,318,1005,318,120,1008,319,100,318,1006,318,76,1008,317,2,318,1006,318,49,1101,0,39,320,1105,1,136,1101,0,46,320,1105,1,136,1105,1,4,1101,0,56,320,1105,1,136,104,27,104,91,4,319,1101,0,69,320,1105,1,136,4,319,104,109,1105,1,4,1007,319,100,318,1005,318,99,4,316,1001,319,-1,319,1007,319,100,318,1006,318,83,1105,1,4,1,316,319,316,1008,316,31,318,1005,318,115,4,316,1105,1,4,104,10,1105,1,4,1008,317,2,318,1005,318,135,104,27,104,91,4,48,104,109,99,1001,147,0,319,1001,137,1,137,105,1,320,100,57,49,1,106,14,-1,101,50,-64,1,105,15,-15,100,51,49,15,-15,100,57,49,15,45,32,-93,1,103,15,-15,100,51,49,15,-15,92,-92,100,57,49,60,-60,100,57,51,10,-11,1,102,100,57,49,15,-15,0,100,51,49,15,-15,0,60,-60,100,57,49,60,-60,101,45,-8,13,0,7,-57,100,57,50,35,5,10,-9,10,1,-7,-12,18,100,57,55,-50,-2,1,101,100,57,49,15,-15,100,51,49,15,-15,0,15,-15,60,-60,0,100,57,49,60,-60,101,100,57,48,13,0,-13,83,-14,7,-3,-2,6,-12,13,-53,0,-26,1,100,57,55,14,1,79,109,-34,-46,-15,9,-8,14,-12,10,50,-48,-14,13,-11,12,-14,7,7,80,-94,9,-10,1,7,87,111,-87,-8,99,31 -------------------------------------------------------------------------------- /2019/other/mand_intcode/runner_ascii.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from datetime import datetime, timedelta 5 | import os 6 | 7 | def main(lines): 8 | sys.path.insert(0, os.path.join('..', '..', 'Helpers')) 9 | 10 | from program import Program 11 | from dummylog import DummyLog 12 | 13 | #Program.debug(lines) 14 | p = Program([int(x) for x in lines.split(",")], DummyLog()) 15 | while p.flag_running: 16 | p.tick() 17 | while len(p.output) > 0: 18 | sys.stdout.write(chr(p.get_output())) 19 | sys.stdout.flush() 20 | 21 | if __name__ == "__main__": 22 | with open(sys.argv[1]) as f: 23 | main(f.read()) 24 | -------------------------------------------------------------------------------- /2019/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | if sys.version_info >= (3, 10): 6 | import importlib.util 7 | import importlib.machinery 8 | else: 9 | import imp 10 | import hashlib 11 | 12 | required_methods = [ 13 | "run", 14 | "test", 15 | "DAY_NUM", 16 | "DAY_DESC", 17 | ] 18 | 19 | def load_source(modname, filename): 20 | if sys.version_info >= (3, 11): 21 | loader = importlib.machinery.SourceFileLoader(modname, filename) 22 | spec = importlib.util.spec_from_file_location(modname, filename, loader=loader) 23 | module = importlib.util.module_from_spec(spec) 24 | loader.exec_module(module) 25 | sys.modules[module.__name__] = module 26 | return module 27 | else: 28 | return imp.load_source(modname, filename) 29 | 30 | def get_helpers(): 31 | for cur in sorted(os.listdir("Helpers")): 32 | if cur.startswith("day_") and cur.endswith(".py"): 33 | name = ".".join(cur.split(".")[:-1]) 34 | cur = os.path.join("Helpers", cur) 35 | with open(cur, "rb") as f: 36 | hash = hashlib.sha256(f.read()).hexdigest() 37 | helper = load_source(name, cur) 38 | for method in required_methods: 39 | if not hasattr(helper, method): 40 | raise Exception(f"ERROR: {cur} doesn't implement '{method}'!") 41 | helper.filename = cur 42 | helper.hash = hash 43 | yield helper 44 | -------------------------------------------------------------------------------- /2020/.gitignore: -------------------------------------------------------------------------------- 1 | /*.png 2 | /*.mp4 3 | -------------------------------------------------------------------------------- /2020/Helpers/Font-DSEG14Classic-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seligman/aoc/b2e14a0233277ce18faa654247a3b5854ce1e858/2020/Helpers/Font-DSEG14Classic-Bold.ttf -------------------------------------------------------------------------------- /2020/Helpers/Font-SourceCodePro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seligman/aoc/b2e14a0233277ce18faa654247a3b5854ce1e858/2020/Helpers/Font-SourceCodePro-Bold.ttf -------------------------------------------------------------------------------- /2020/Helpers/day_01.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | DAY_NUM = 1 4 | DAY_DESC = 'Day 1: Report Repair' 5 | 6 | def calc(log, values, mode): 7 | values = [int(x) for x in values] 8 | 9 | if mode == 1: 10 | for x in range(len(values)): 11 | for y in range(x + 1, len(values)): 12 | if values[x] + values[y] == 2020: 13 | return values[x] * values[y] 14 | else: 15 | for x in range(len(values)): 16 | for y in range(x + 1, len(values)): 17 | for z in range(y + 1, len(values)): 18 | if values[x] + values[y] + values[z] == 2020: 19 | return values[x] * values[y] * values[z] 20 | 21 | return 10 22 | 23 | def test(log): 24 | values = log.decode_values(""" 25 | 1721 26 | 979 27 | 366 28 | 299 29 | 675 30 | 1456 31 | """) 32 | 33 | log.test(calc(log, values, 1), 514579) 34 | log.test(calc(log, values, 2), 241861950) 35 | 36 | def run(log, values): 37 | log(f"Part 1: {calc(log, values, 1)}") 38 | log(f"Part 2: {calc(log, values, 2)}") 39 | 40 | if __name__ == "__main__": 41 | import sys, os 42 | def find_input_file(): 43 | for fn in sys.argv[1:] + ["input.txt", f"day_{DAY_NUM:0d}_input.txt", f"day_{DAY_NUM:02d}_input.txt"]: 44 | for dn in ["", "Puzzles", "../Puzzles", "../../private/inputs/2020/Puzzles"]: 45 | cur = os.path.join(*(dn.split("/") + [fn])) 46 | if os.path.isfile(cur): return cur 47 | fn = find_input_file() 48 | if fn is None: print("Unable to find input file!\nSpecify filename on command line"); exit(1) 49 | print(f"Using '{fn}' as input file:") 50 | with open(fn) as f: values = [x.strip("\r\n") for x in f.readlines()] 51 | print(f"Running day {DAY_DESC}:") 52 | run(print, values) 53 | -------------------------------------------------------------------------------- /2020/Helpers/day_02.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | from collections import defaultdict 5 | 6 | DAY_NUM = 2 7 | DAY_DESC = 'Day 2: Password Philosophy' 8 | 9 | def calc(log, values, mode): 10 | r = re.compile("([0-9]+)-([0-9]+) ([a-z]): ([a-z]+)") 11 | ret = 0 12 | for cur in values: 13 | m = r.search(cur) 14 | a, b = int(m.group(1)), int(m.group(2)) 15 | target = m.group(3) 16 | pw = m.group(4) 17 | 18 | if mode == 1: 19 | counts = defaultdict(int) 20 | for x in pw: 21 | counts[x] += 1 22 | if counts[target] >= a and counts[target] <= b: 23 | ret += 1 24 | else: 25 | if (pw[a-1] == target and pw[b-1] != target) or (pw[a-1] != target and pw[b-1] == target): 26 | ret += 1 27 | 28 | return ret 29 | 30 | def test(log): 31 | values = log.decode_values(""" 32 | 1-3 a: abcde 33 | 1-3 b: cdefg 34 | 2-9 c: ccccccccc 35 | """) 36 | 37 | log.test(calc(log, values, 1), 2) 38 | log.test(calc(log, values, 2), 1) 39 | 40 | def run(log, values): 41 | log(f"Part 1: {calc(log, values, 1)}") 42 | log(f"Part 2: {calc(log, values, 2)}") 43 | 44 | if __name__ == "__main__": 45 | import sys, os 46 | def find_input_file(): 47 | for fn in sys.argv[1:] + ["input.txt", f"day_{DAY_NUM:0d}_input.txt", f"day_{DAY_NUM:02d}_input.txt"]: 48 | for dn in ["", "Puzzles", "../Puzzles", "../../private/inputs/2020/Puzzles"]: 49 | cur = os.path.join(*(dn.split("/") + [fn])) 50 | if os.path.isfile(cur): return cur 51 | fn = find_input_file() 52 | if fn is None: print("Unable to find input file!\nSpecify filename on command line"); exit(1) 53 | print(f"Using '{fn}' as input file:") 54 | with open(fn) as f: values = [x.strip("\r\n") for x in f.readlines()] 55 | print(f"Running day {DAY_DESC}:") 56 | run(print, values) 57 | -------------------------------------------------------------------------------- /2020/Helpers/day_03.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | DAY_NUM = 3 4 | DAY_DESC = 'Day 3: Toboggan Trajectory' 5 | 6 | def calc(log, values, mode): 7 | from grid import Grid 8 | grid = Grid.from_text(values) 9 | ret = [] 10 | 11 | if mode == 1: 12 | passes = [[3,1]] 13 | else: 14 | passes = [[1,1],[3,1],[5,1],[7,1],[1,2]] 15 | for step_x, step_y in passes: 16 | ret.append(0) 17 | x, y = 0, 0 18 | while True: 19 | x += step_x 20 | y += step_y 21 | x = x % grid.width() 22 | if y >= grid.height(): 23 | break 24 | if grid[x, y] == "#": 25 | ret[-1] += 1 26 | 27 | value = 1 28 | for x in ret: 29 | value *= x 30 | 31 | return value 32 | 33 | def test(log): 34 | values = log.decode_values(""" 35 | ..##....... 36 | #...#...#.. 37 | .#....#..#. 38 | ..#.#...#.# 39 | .#...##..#. 40 | ..#.##..... 41 | .#.#.#....# 42 | .#........# 43 | #.##...#... 44 | #...##....# 45 | .#..#...#.# 46 | """) 47 | 48 | log.test(calc(log, values, 1), 7) 49 | log.test(calc(log, values, 2), 336) 50 | 51 | def run(log, values): 52 | log(f"Part 1: {calc(log, values, 1)}") 53 | log(f"Part 2: {calc(log, values, 2)}") 54 | 55 | if __name__ == "__main__": 56 | import sys, os 57 | def find_input_file(): 58 | for fn in sys.argv[1:] + ["input.txt", f"day_{DAY_NUM:0d}_input.txt", f"day_{DAY_NUM:02d}_input.txt"]: 59 | for dn in ["", "Puzzles", "../Puzzles", "../../private/inputs/2020/Puzzles"]: 60 | cur = os.path.join(*(dn.split("/") + [fn])) 61 | if os.path.isfile(cur): return cur 62 | fn = find_input_file() 63 | if fn is None: print("Unable to find input file!\nSpecify filename on command line"); exit(1) 64 | print(f"Using '{fn}' as input file:") 65 | with open(fn) as f: values = [x.strip("\r\n") for x in f.readlines()] 66 | print(f"Running day {DAY_DESC}:") 67 | run(print, values) 68 | -------------------------------------------------------------------------------- /2020/Helpers/day_06.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict 4 | 5 | DAY_NUM = 6 6 | DAY_DESC = 'Day 6: Custom Customs' 7 | 8 | def calc(log, values, mode): 9 | total_answers = 0 10 | this_group = defaultdict(int) 11 | for value in values + [""]: 12 | if len(value) == 0: 13 | if len(this_group) > 0: 14 | if mode == 1: 15 | total_answers += len(this_group) - 1 16 | else: 17 | total_answers += len([x for x in this_group if this_group[x] == this_group['people']]) - 1 18 | this_group = defaultdict(int) 19 | else: 20 | for answer in value: 21 | this_group[answer] += 1 22 | this_group['people'] += 1 23 | 24 | return total_answers 25 | 26 | def test(log): 27 | values = log.decode_values(""" 28 | abc 29 | 30 | a 31 | b 32 | c 33 | 34 | ab 35 | ac 36 | 37 | a 38 | a 39 | a 40 | a 41 | 42 | b 43 | """) 44 | 45 | log.test(calc(log, values, 1), 11) 46 | log.test(calc(log, values, 2), 6) 47 | 48 | def run(log, values): 49 | log(f"Part 1: {calc(log, values, 1)}") 50 | log(f"Part 2: {calc(log, values, 2)}") 51 | 52 | if __name__ == "__main__": 53 | import sys, os 54 | def find_input_file(): 55 | for fn in sys.argv[1:] + ["input.txt", f"day_{DAY_NUM:0d}_input.txt", f"day_{DAY_NUM:02d}_input.txt"]: 56 | for dn in ["", "Puzzles", "../Puzzles", "../../private/inputs/2020/Puzzles"]: 57 | cur = os.path.join(*(dn.split("/") + [fn])) 58 | if os.path.isfile(cur): return cur 59 | fn = find_input_file() 60 | if fn is None: print("Unable to find input file!\nSpecify filename on command line"); exit(1) 61 | print(f"Using '{fn}' as input file:") 62 | with open(fn) as f: values = [x.strip("\r\n") for x in f.readlines()] 63 | print(f"Running day {DAY_DESC}:") 64 | run(print, values) 65 | -------------------------------------------------------------------------------- /2020/Helpers/day_15.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict, deque 4 | 5 | DAY_NUM = 15 6 | DAY_DESC = 'Day 15: Rambunctious Recitation' 7 | 8 | def calc(log, values, mode): 9 | numbers = [int(x) for x in values[0].split(",")] 10 | 11 | said = {} 12 | last = None 13 | 14 | for i in range(len(numbers)): 15 | said[last], last = i, numbers[i] 16 | 17 | for i in range(len(numbers), 2020 if mode == 1 else 30000000): 18 | said[last], last = i, i - said.get(last, i) 19 | if (mode == 1 and i % 1000 == 19) or (mode == 2 and i % 5000000 == 999999): 20 | log(f"For round {i:8d}, {last:8d} was said") 21 | 22 | return last 23 | 24 | def test(log): 25 | values = log.decode_values(""" 26 | 0,3,6 27 | """) 28 | 29 | log.test(calc(log, values, 1), 436) 30 | # log.test(calc(log, values, 2), 175594) 31 | 32 | def run(log, values): 33 | log(f"Part 1: {calc(log, values, 1)}") 34 | log(f"Part 2: {calc(log, values, 2)}") 35 | 36 | if __name__ == "__main__": 37 | import sys, os 38 | def find_input_file(): 39 | for fn in sys.argv[1:] + ["input.txt", f"day_{DAY_NUM:0d}_input.txt", f"day_{DAY_NUM:02d}_input.txt"]: 40 | for dn in ["", "Puzzles", "../Puzzles", "../../private/inputs/2020/Puzzles"]: 41 | cur = os.path.join(*(dn.split("/") + [fn])) 42 | if os.path.isfile(cur): return cur 43 | fn = find_input_file() 44 | if fn is None: print("Unable to find input file!\nSpecify filename on command line"); exit(1) 45 | print(f"Using '{fn}' as input file:") 46 | with open(fn) as f: values = [x.strip("\r\n") for x in f.readlines()] 47 | print(f"Running day {DAY_DESC}:") 48 | run(print, values) 49 | -------------------------------------------------------------------------------- /2020/Helpers/day_25.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | DAY_NUM = 25 4 | DAY_DESC = 'Day 25: Combo Breaker' 5 | 6 | def transform(loop, subject): 7 | value = 1 8 | for _ in range(loop): 9 | value = value * subject 10 | value = value % 20201227 11 | return value 12 | 13 | def transform_bail(subject, bail): 14 | value = 1 15 | loop = 0 16 | while True: 17 | loop += 1 18 | value = value * subject 19 | value = value % 20201227 20 | if bail == value: 21 | return loop 22 | 23 | def calc(log, values, mode): 24 | door = transform_bail(7, int(values[1])) 25 | return transform(door, int(values[0])) 26 | 27 | 28 | def test(log): 29 | values = log.decode_values(""" 30 | 5764801 31 | 17807724 32 | """) 33 | 34 | log.test(calc(log, values, 1), 14897079) 35 | 36 | def run(log, values): 37 | log(f"Part 1: {calc(log, values, 1)}") 38 | 39 | if __name__ == "__main__": 40 | import sys, os 41 | def find_input_file(): 42 | for fn in sys.argv[1:] + ["input.txt", f"day_{DAY_NUM:0d}_input.txt", f"day_{DAY_NUM:02d}_input.txt"]: 43 | for dn in ["", "Puzzles", "../Puzzles", "../../private/inputs/2020/Puzzles"]: 44 | cur = os.path.join(*(dn.split("/") + [fn])) 45 | if os.path.isfile(cur): return cur 46 | fn = find_input_file() 47 | if fn is None: print("Unable to find input file!\nSpecify filename on command line"); exit(1) 48 | print(f"Using '{fn}' as input file:") 49 | with open(fn) as f: values = [x.strip("\r\n") for x in f.readlines()] 50 | print(f"Running day {DAY_DESC}:") 51 | run(print, values) 52 | -------------------------------------------------------------------------------- /2020/Helpers/dummylog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | class DummyLog: 4 | def __init__(self, filename=None): 5 | self.filename = filename 6 | 7 | def show(self, value): 8 | if self.filename is not None: 9 | with open(self.filename, "at") as f: 10 | f.write(str(value) + "\n") 11 | else: 12 | print(value) 13 | 14 | def __call__(self, value): 15 | self.show(value) 16 | 17 | def decode_values(self, values): 18 | ret = values.replace("\t", " ").split("\n") 19 | # Only remove empty lines at the start and end 20 | while len(ret) > 0 and len(ret[0].strip()) == 0: 21 | ret = ret[1:] 22 | while len(ret) > 0 and len(ret[-1].strip()) == 0: 23 | ret = ret[:-1] 24 | # Remove the indenting based off the first line 25 | if len(ret) > 0: 26 | pad = len(ret[0]) - len(ret[0].lstrip(' ')) 27 | pad -= pad % 4 28 | if pad > 0 and len(ret) > 0: 29 | for i in range(len(ret)): 30 | if ret[i].startswith(" " * pad): 31 | ret[i] = ret[i][pad:] 32 | return ret 33 | 34 | def test(self, actual, expected): 35 | self.show("Test returned %s, expected %s" % (str(actual), str(expected))) 36 | if actual != expected: 37 | raise ValueError("Test failure") 38 | -------------------------------------------------------------------------------- /2020/Helpers/example.txt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def get_desc(): 4 | return DAY_NUM, 'DAY_TODO' 5 | 6 | def calc(log, values, mode): 7 | # TODO: Delete or use these 8 | # from grid import Grid 9 | # grid = Grid.from_text(values) 10 | # from program import Program 11 | # prog = Program(values) 12 | 13 | # TODO 14 | return 0 15 | 16 | def test(log): 17 | values = log.decode_values(""" 18 | TODO 19 | """) 20 | 21 | log.test(calc(log, values, 1), 'TODO') 22 | log.test(calc(log, values, 2), 'TODO') 23 | 24 | def run(log, values): 25 | log(calc(log, values, 1)) 26 | log(calc(log, values, 2)) 27 | 28 | if __name__ == "__main__": 29 | import sys, os 30 | def find_input_file(): 31 | for fn in sys.argv[1:] + ["input.txt", f"day_{DAY_NUM:0d}_input.txt", f"day_{DAY_NUM:02d}_input.txt"]: 32 | for dn in ["", "Puzzles", "../Puzzles", "../../private/inputs/2020/Puzzles"]: 33 | cur = os.path.join(*(dn.split("/") + [fn])) 34 | if os.path.isfile(cur): return cur 35 | fn = find_input_file() 36 | if fn is None: print("Unable to find input file!"); exit(1) 37 | with open(fn) as f: values = [x.strip("\r\n") for x in f.readlines()] 38 | print(f"Running day {DAY_DESC}:") 39 | run(print, values) 40 | -------------------------------------------------------------------------------- /2020/Puzzles/SourceCodePro.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Source Code Pro'; 3 | font-style: normal; 4 | font-weight: 300; 5 | src: local('Source Code Pro Light'), local('SourceCodePro-Light'), url(SourceCodePro.ttf) format('truetype'); 6 | } 7 | -------------------------------------------------------------------------------- /2020/Puzzles/SourceCodePro.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seligman/aoc/b2e14a0233277ce18faa654247a3b5854ce1e858/2020/Puzzles/SourceCodePro.ttf -------------------------------------------------------------------------------- /2020/Puzzles/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seligman/aoc/b2e14a0233277ce18faa654247a3b5854ce1e858/2020/Puzzles/favicon.png -------------------------------------------------------------------------------- /2020/Puzzles/highcontrast.css: -------------------------------------------------------------------------------- 1 | * { 2 | background: white !important; 3 | color: black !important; 4 | text-shadow: none !important; 5 | } 6 | a { 7 | color: #0000ff !important; 8 | text-decoration: underline !important; 9 | } 10 | em { 11 | font-weight: 900 !important; 12 | } 13 | -------------------------------------------------------------------------------- /2020/Puzzles/main_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seligman/aoc/b2e14a0233277ce18faa654247a3b5854ce1e858/2020/Puzzles/main_page.png -------------------------------------------------------------------------------- /2020/Puzzles/main_page_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seligman/aoc/b2e14a0233277ce18faa654247a3b5854ce1e858/2020/Puzzles/main_page_small.png -------------------------------------------------------------------------------- /2020/README.md: -------------------------------------------------------------------------------- 1 |
From here, you can access all of the events:
15 | 16 | 17 | 18 | 19 | 20 | 21 |