Moved year

This commit is contained in:
2023-11-28 13:28:09 +00:00
parent 9054a9ac40
commit 74431e28c1
22 changed files with 0 additions and 0 deletions

9
2022/LICENSE Normal file
View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) 2022 Sven Heidemann
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

15
2022/README.md Normal file
View File

@@ -0,0 +1,15 @@
# adventofcode-2022
https://adventofcode.com/2022
Original at: https://git.sh-edraft.de/edraft/adventofcode-2022.git
## Session
Save the session key from https://adventofcode.com/ to .env file in the variable ```session=```
## Execute
First create a venv and install deps with ```pip install -r deps.txt --upgrade --extra-index-url https://pip.sh-edraft.de```
Then run code easily with ```./run {Number-of-day}```

3
2022/deps.txt Normal file
View File

@@ -0,0 +1,3 @@
cpl-cli==2022.12.0
cpl-core==2022.12.0
cpl-query==2022.12.1.post1

3
2022/run Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
python src/day$1.py

0
2022/src/aoc/__init__.py Normal file
View File

41
2022/src/aoc/aoc.py Normal file
View File

@@ -0,0 +1,41 @@
import os
import shutil
import urllib.request
from cpl_core.console import Console
def _get_cookie_headers() -> dict[str, str]:
"""
original code from https://github.com/anthonywritescode/aoc2022/blob/main/support/support.py
"""
env = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../.env')
if not os.path.exists(env):
Console.error(f'Session key from https://adventofcode.com/ required')
with open(env) as f:
contents = f.read().strip()
return {'Cookie': contents}
def get_input(year: int, day: int) -> str:
"""
original code from https://github.com/anthonywritescode/aoc2022/blob/main/support/support.py
"""
file = f'input/{year}/input_{day}.txt'
if not os.path.exists(os.path.dirname(file)):
os.makedirs(os.path.dirname(file))
if not os.path.exists(file):
url = f'https://adventofcode.com/{year}/day/{day}/input'
req = urllib.request.Request(url, headers=_get_cookie_headers())
txt = urllib.request.urlopen(req).read().decode()
with open(file, 'w+') as f:
f.write(txt)
f.close()
txt = ''
with open(file, 'r') as f:
txt = f.read()
f.close()
return txt

34
2022/src/day1.py Normal file
View File

@@ -0,0 +1,34 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 1
aoc_input = get_input(2022, day)
elfs = List(int)
def part1() -> int:
elf = 0
for cal in aoc_input.splitlines():
if cal == '':
elfs.append(elf)
elf = 0
continue
elf += int(cal)
return elfs.max()
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
Console.write_line(f'Part 1: {part1()}')
Console.write_line(f'Part 2: {elfs.order_by_descending().take(3).sum()}')
Console.write_line()

220
2022/src/day10.py Normal file
View File

@@ -0,0 +1,220 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 10
aoc_input = get_input(2022, day)
aoc_input1 = """noop
addx 3
addx -5
"""
def get_test_data():
return """addx 15
addx -11
addx 6
addx -3
addx 5
addx -1
addx -8
addx 13
addx 4
noop
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx -35
addx 1
addx 24
addx -19
addx 1
addx 16
addx -11
noop
noop
addx 21
addx -15
noop
noop
addx -3
addx 9
addx 1
addx -3
addx 8
addx 1
addx 5
noop
noop
noop
noop
noop
addx -36
noop
addx 1
addx 7
noop
noop
noop
addx 2
addx 6
noop
noop
noop
noop
noop
addx 1
noop
noop
addx 7
addx 1
noop
addx -13
addx 13
addx 7
noop
addx 1
addx -33
noop
noop
noop
addx 2
noop
noop
noop
addx 8
noop
addx -1
addx 2
addx 1
noop
addx 17
addx -9
addx 1
addx 1
addx -3
addx 11
noop
noop
addx 1
noop
addx 1
noop
noop
addx -13
addx -19
addx 1
addx 3
addx 26
addx -30
addx 12
addx -1
addx 3
addx 1
noop
noop
noop
addx -9
addx 18
addx 1
addx 2
noop
noop
addx 9
noop
noop
noop
addx -1
addx 2
addx -37
addx 1
addx 3
noop
addx 15
addx -21
addx 22
addx -6
addx 1
noop
addx 2
addx 1
noop
addx -10
noop
noop
addx 20
addx 1
addx 2
addx 2
addx -6
addx -11
noop
noop
noop
"""
class CPU:
x = 1
cycles = 1
signal_strength = 0
position = 0
@classmethod
def cycle(cls, value: int = None):
Console.write('' if cls.position >= cls.x - 1 and cls.position <= cls.x + 1 else ' ')
cls.position += 1
if cls.position == 40:
cls.position = 0
Console.write_line()
if (cls.cycles - 20) % 40 == 0:
cls.signal_strength += cls.x * cls.cycles
cls.cycles += 1
if value is not None:
cls.x += value
def main():
ops = List(tuple)
# aoc_input = get_test_data()
Console.write_line()
for line in aoc_input.splitlines():
s_line = line.split()
cmd = s_line[0]
value = None
if len(s_line) > 1:
value = int(s_line[1])
match cmd:
case 'noop':
CPU.cycle(None)
case 'addx':
CPU.cycle(None)
CPU.cycle(value)
Console.write_line()
Console.write_line(CPU.cycles, CPU.x, CPU.signal_strength)
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
main()
Console.write_line()

122
2022/src/day11.py Normal file
View File

@@ -0,0 +1,122 @@
import textwrap
from dataclasses import dataclass
from functools import reduce
from math import lcm
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 11
aoc_input = get_input(2022, day)
aoc_input1 = """Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
Monkey 2:
Starting items: 79, 60, 97
Operation: new = old * old
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 3
Monkey 3:
Starting items: 74
Operation: new = old + 3
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 1
"""
class Monkey:
def __init__(self, m: List[str]):
self.items = List(int)
self.operation = ''
self.test = ''
self.test_true_action = None
self.test_false_action = None
self.inspects = 0
for x in m:
x = str(x).replace(' ', '')
if ':' not in x:
continue
atr, value = x.split(':')
match atr:
case 'Startingitems':
for v in value.split(','):
self.items.append(int(v))
case 'Operation':
self.operation = value
case 'Test':
self.test = value
self.divisor = int(self.test.split('divisibleby')[1])
case 'Iftrue':
self.test_true_action = value
case 'Iffalse':
self.test_false_action = value
self.initial_items = self.items.copy()
def __repr__(self):
return f'<Monkey {self.inspects} {self.items}>'
def do_work(self, monkeys: List['Monkey'], modulus, part2=False):
remove = []
for old in self.items:
self.inspects += 1
if part2:
new = int(eval(self.operation.split('=')[1]))
else:
new = int(eval(self.operation.split('=')[1]) / 3)
new %= modulus
divisible = new % int(self.test.split('divisibleby')[1]) == 0
throw_to = monkeys.element_at(int((self.test_true_action if divisible else self.test_false_action).split('throwtomonkey')[1]))
throw_to.items.append(new)
remove.append(old)
for r in remove:
self.items.remove(r)
def main(part2=False):
monkeys = List(str, aoc_input.splitlines()) \
.select(lambda x: x if not str(x).startswith('Monkey') else None).where(lambda x: x is not None) \
.split(lambda x: '') \
.select(lambda monkey: Monkey(monkey))
mod = lcm(*monkeys.select(lambda x: x.divisor))
for i in range(0, 10000 if part2 else 20):
for m in monkeys:
m.do_work(monkeys, mod, part2)
Console.write_line(reduce((lambda x, y: x * y), monkeys.order_by_descending(lambda x: x.inspects).take(2).select(lambda x: x.inspects)))
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
main()
main(True)
Console.write_line()

80
2022/src/day12.py Normal file
View File

@@ -0,0 +1,80 @@
import collections
import string
from dataclasses import dataclass
from typing import Union
from cpl_core.console import Console
from cpl_query.extension import List
from aoc.aoc import get_input
# global vars
day = 12
aoc_input = get_input(2022, day)
aoc_input1 = """Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi"""
@dataclass
class Position:
x: int = 0
y: int = 0
def get_position(grid: List[List[str]], char: str) -> Position:
y = grid.index_of(grid.where(lambda row: char in row).single())
x = grid.element_at(y).index_of(char)
return Position(x, y)
def get_path(grid: List[List[Union[str, int]]], start: Position, reverse=False):
width = grid.first().count()
height = grid.count()
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
paths = collections.defaultdict(lambda: 10e15)
paths[(start.y, start.x)] = 0
should_search = [(start.x, start.y, 0)]
while len(should_search) > 0:
x, y, steps = should_search[0]
should_search = should_search[1:]
from_height = ord(grid[y][x])
for (dx, dy) in directions:
nx = x + dx
ny = y + dy
if nx < 0 or nx >= width or ny < 0 or ny >= height:
continue
to_height = ord(grid[ny][nx])
if not reverse and not from_height - to_height >= -1:
continue
if reverse and not from_height - to_height <= 1:
continue
if paths[(ny, nx)] > steps + 1:
paths[(ny, nx)] = steps + 1
should_search.append((nx, ny, steps + 1))
return paths
def main():
grid = List(str, aoc_input.splitlines()).select(lambda x: List(int, x))
Console.write_line(grid)
start = get_position(grid, 'S')
target = get_position(grid, 'E')
grid: List[List[Union[str, int]]] = grid.select(lambda x: x.select(lambda y: 'a' if y == 'S' else 'z' if y == 'E' else y))
Console.write_line(get_path(grid, start)[target.y, target.x])
Console.write_line(min([dist for ((y, x), dist) in get_path(grid, target, True).items() if grid[y][x] == 'a']))
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
main()
Console.write_line()

86
2022/src/day13.py Normal file
View File

@@ -0,0 +1,86 @@
import json
from functools import cmp_to_key
from math import prod
from typing import Union
from cpl_core.console import Console
from cpl_query.extension import List
from aoc.aoc import get_input
# global vars
day = 13
aoc_input = get_input(2022, day)
test_input = """[1,1,3,1,1]
[1,1,5,1,1]
[[1],[2,3,4]]
[[1],4]
[9]
[[8,7,6]]
[[4,4],4,4]
[[4,4],4,4,4]
[7,7,7,7]
[7,7,7]
[]
[3]
[[[]]]
[[]]
[1,[2,[3,[4,[5,6,7]]]],8,9]
[1,[2,[3,[4,[5,6,0]]]],8,9]
"""
def compare(left: Union[int, list], right: Union[int, list]):
match left, right:
case int(), list():
return compare([left], right)
case list(), int():
return compare(left, [right])
case int(), int():
return left - right
case list(), list():
for i, j in zip(left, right):
if (r := compare(i, j)) != 0:
return r
return compare(len(left), len(right))
def main(lines=aoc_input, part2=False):
lists: List[List[int]] = List(str, lines.splitlines()) \
.select(lambda x: List(object, json.loads(x)) if x != '' else None) \
.split(lambda x: None) \
.select(lambda x: x.where(lambda y: y is not None))
if not part2:
lists: List[List[int]] = List(str, lines.splitlines()) \
.select(lambda x: List(object, json.loads(x)) if x != '' else None) \
.split(lambda x: None) \
.select(lambda x: x.where(lambda y: y is not None))
compared = lists \
.where(lambda pair: compare(pair.element_at(0).to_list(), pair.element_at(1).to_list()) < 0) \
.select(lambda x: lists.index_of(x) + 1)
Console.write_line(compared.count(), compared.sum(lambda x: x))
return
two_six = List(object, [List(object, [List(object, [2])]), List(object, [List(object, [6])])])
compared = lists.extend(two_six) \
.select_many(lambda x: x.select(lambda y: y.to_list() if isinstance(x, List) else y).to_list() if isinstance(x, List) else x) \
.order_by(cmp_to_key(compare))
Console.write_line(prod(two_six.select_many(lambda x: x.select(lambda y: compared.index_of(y.to_list()) + 1))))
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
main()
Console.write_line()
main(part2=True)
Console.write_line()

165
2022/src/day14.py Normal file
View File

@@ -0,0 +1,165 @@
import time
from dataclasses import dataclass
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 14
aoc_input = get_input(2022, day)
test_input = """498,4 -> 498,6 -> 496,6
503,4 -> 502,4 -> 502,9 -> 494,9
"""
@dataclass
class Position:
x: int = 0
y: int = 0
def build_rocks(grid: List[List[str]], paths: List[List[Position]], index_map: List[int]):
for path in paths:
last_pos = None
for pos in path:
if last_pos is None:
last_pos = pos
continue
x_bias = 1 if last_pos.x - pos.x > 0 else -1
y_bias = 1 if last_pos.y - pos.y > 0 else -1
vertical = List(int).extend(range(pos.y, last_pos.y + y_bias, y_bias))
horizontal = List(int).extend(range(index_map.index_of(pos.x), index_map.index_of(last_pos.x) + x_bias, x_bias))
for y in vertical:
for x in horizontal:
grid[y][x] = '#'
last_pos = pos
def draw(grid: List[List[Position]], pos: Position = None):
Console.clear()
draw_grid = grid.select(lambda x: x.copy()).copy()
if pos is not None:
draw_grid[pos.y][pos.x] = 'x'
Console.write_line()
i = 0
for i, row in enumerate(draw_grid):
Console.write_line(f'{i:03d}', ''.join(row))
time.sleep(0.01)
def place_tile(grid: List[List[Position]], x: int, y: int):
grid[y][x] = 'o'
if grid[y - 1][x] == '.' and grid[y - 1][x + 1] != '#':
grid[y - 1][x + 1] = '.'
elif grid[y - 1][x + 1] == 'o':
grid[y - 1][x + 1] = '.'
if grid[y - 1][x] != '#':
grid[y - 1][x] = '.'
def in_boundary(grid: List[List[Position]], x: int, y: int) -> bool:
return 0 <= y < grid.count() and 0 <= x < grid.first().count()
def is_blocked(grid: List[List[Position]], x: int, y: int) -> bool:
if not in_boundary(grid, x, y):
return True
return grid[y][x] == 'o' or grid[y][x] == '#'
def simulate_sand(grid: List[List[Position]], index_map: List[int]):
start = Position(index_map.index_of(500), 0)
x = start.x
y = start.y
count = 0
can_continue = True
while can_continue:
# draw(grid, Position(x, y))
# if grid[y + 1][x] == '.':
# y += 1
# continue
if not is_blocked(grid, x, y + 1):
y += 1
elif not in_boundary(grid, x, y + 1):
break
elif not is_blocked(grid, x - 1, y + 1):
x -= 1
y += 1
elif not in_boundary(grid, x - 1, y + 1):
break
elif not is_blocked(grid, x + 1, y + 1):
x += 1
y += 1
elif not in_boundary(grid, x + 1, y + 1):
break
else:
count += 1
if x == start.x and y == start.y:
break
grid[y][x] = 'o'
x = start.x
y = start.y
draw(grid)
Console.write_line(count)
def main(text: str, part2=False):
if part2:
dx = 500
text += f'{min_pos.x - dx},{max_pos.y + 2} -> {max_pos.x + dx},{max_pos.y + 2}'
paths: List[List[Position]] = List(Position, text.splitlines()) \
.select(lambda x: List(str, x.split(' -> ')).select(lambda y: Position(int(y.split(',')[0]), int(y.split(',')[1]))))
paths_x = paths.select_many(lambda x: x)
min_pos.x = paths_x.min(lambda x: x.x)
min_pos.y = paths_x.min(lambda x: x.y)
max_pos.x = paths_x.max(lambda x: x.x)
max_pos.y = paths_x.max(lambda x: x.y)
index_map = List.range(min_pos.x, paths_x.max(lambda x: x.x) + 1)
grid = List.range(0, max_pos.y + (3 if part2 else 1)).select(
lambda y: index_map.select(lambda x: '.'))
grid[0][index_map.index_of(500)] = '+'
build_rocks(grid, paths, index_map)
# draw(grid)
simulate_sand(grid, index_map)
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
max_pos = Position(0, 0)
min_pos = Position(0, 0)
# main(test_input)
# main(test_input, True)
main(aoc_input)
main(aoc_input, True)
Console.write_line()

92
2022/src/day15.py Normal file
View File

@@ -0,0 +1,92 @@
from __future__ import annotations
import math
import re
from dataclasses import dataclass
from typing import Union
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 15
aoc_input = get_input(2022, day)
test_input = """Sensor at x=2, y=18: closest beacon is at x=-2, y=15
Sensor at x=9, y=16: closest beacon is at x=10, y=16
Sensor at x=13, y=2: closest beacon is at x=15, y=3
Sensor at x=12, y=14: closest beacon is at x=10, y=16
Sensor at x=10, y=20: closest beacon is at x=10, y=16
Sensor at x=14, y=17: closest beacon is at x=10, y=16
Sensor at x=8, y=7: closest beacon is at x=2, y=10
Sensor at x=2, y=0: closest beacon is at x=2, y=10
Sensor at x=0, y=11: closest beacon is at x=2, y=10
Sensor at x=20, y=14: closest beacon is at x=25, y=17
Sensor at x=17, y=20: closest beacon is at x=21, y=22
Sensor at x=16, y=7: closest beacon is at x=15, y=3
Sensor at x=14, y=3: closest beacon is at x=15, y=3
Sensor at x=20, y=1: closest beacon is at x=15, y=3
"""
@dataclass
class Position:
x: int
y: int
def manhattan_distance(self):
return abs(self.x) + abs(self.y)
def __sub__(self, other: Position):
x = self.x - other.x
y = self.y - other.y
return Position(x, y)
def find_blocked_in_row(index: int, elements: List(tuple[Position, Position, Position])):
result = set()
for sensor, beacon, diff in elements:
dist = diff.manhattan_distance()
offset = abs(index - sensor.y)
if offset > dist:
continue
dx = dist - offset
t = list(range(sensor.x - dx, sensor.x + dx + 1))
if beacon.y == index and beacon.x in t:
t.remove(beacon.x)
result.update(set(t))
return result
def parse(text: str) -> List[tuple[Position, Position, Position]]:
elements = List(tuple)
for line in text.splitlines():
found = re.findall(r'=-?\d+', line)
sensor = Position(int(found[0][1:]), int(found[1][1:]))
beacon = Position(int(found[2][1:]), int(found[3][1:]))
diff = sensor - beacon
elements.add((sensor, beacon, diff))
return elements
def part1(text: str, index: int):
elements = parse(text)
result = find_blocked_in_row(index, elements)
Console.write_line(len(result))
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
part1(test_input, 10)
part1(aoc_input, 2_000_000)
# part2(test_input, 20)
# part2(aoc_input, 4_000_000)
Console.write_line()

96
2022/src/day2.py Normal file
View File

@@ -0,0 +1,96 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
from day1 import aoc_input
# global vars
day = 2
aoc_input = get_input(2022, day)
rps = {'A': 'R', 'B': 'P', 'C': 'S', 'X': 'R', 'Y': 'P', 'Z': 'S'}
res = {"X": 1, "Y": 2, "Z": 3}
def get_score(opponent, me) -> int:
if opponent == 'R':
if me == 'R':
return 3
elif me == 'P':
return 6
elif me == 'S':
return 0
elif opponent == 'P':
if me == 'R':
return 0
elif me == 'P':
return 3
elif me == 'S':
return 6
elif opponent == 'S':
if me == 'R':
return 6
elif me == 'P':
return 0
elif me == 'S':
return 3
def get_expected_score(opponent, self):
if self == 'Y':
to_me = {"A": "X", "B": "Y", "C": "Z"}
return to_me[opponent]
else:
if opponent == 'A':
if self == 'X':
return 'Z'
elif self == 'Z':
return 'Y'
elif opponent == 'B':
if self == 'X':
return 'X'
elif self == 'Z':
return 'Z'
elif opponent == 'C':
if self == 'X':
return 'Y'
elif self == 'Z':
return 'X'
def part1(data) -> int:
score = 0
for x in data:
opponent, me = x.split()
score += res[me]
score += get_score(rps[opponent], rps[me])
return score
def part2(data):
score = 0
for x in data:
opponent, me = x.split()
e = get_expected_score(opponent, me)
score += res[e]
score += get_score(rps[opponent], rps[e])
return score
if __name__ == '__main__':
"""
Das ist so fckng dreckige Lösung...
Warum bin ich um 6:30 aufgestanden...
Ich hab kein bock mehr.
"""
Console.write_line(f'Advent of code day {day}')
Console.write_line(part1(aoc_input.splitlines()), part2(aoc_input.splitlines()))
Console.write_line()

60
2022/src/day3.py Normal file
View File

@@ -0,0 +1,60 @@
import string
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 3
aoc_input = get_input(2022, day)
# aoc_input = """vJrwpWtwJgWrhcsFMMfFFhFp
# jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
# PmmdzqPrVvPwwTWBwg
# wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
# ttgJtRGJQctTZtZT
# CrZsJsPPZsGzwwsLwLmpwMDw
# """
priorities = [*string.ascii_lowercase, *string.ascii_uppercase]
def part1() -> int:
duplicates = {}
for rucksack in aoc_input.splitlines():
c1, c2 = rucksack[:len(rucksack) // 2], rucksack[len(rucksack) // 2:]
r_duplicates = List(str, c1).select(lambda x: x if x in c2 else '').where(lambda x: x != '')
if r_duplicates.first() not in duplicates:
duplicates[r_duplicates.first()] = 0
duplicates[r_duplicates.first()] += r_duplicates.select(lambda x: priorities.index(x) + 1).distinct().sum()
return sum(duplicates.values())
def part2() -> int:
groups = List(List)
index = 0
for rucksack in aoc_input.splitlines():
if index == 0:
groups.append(List(str))
index += 1
if index == 3:
index = 0
groups.last().append(rucksack)
return groups.select(lambda g: List(str, ''.join(g)).distinct().where(lambda x: x in g[0] and x in g[1] and x in g[2]).single()).select(lambda x: priorities.index(x) + 1).sum()
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
Console.write_line(part1(), part2())
Console.write_line()

67
2022/src/day4.py Normal file
View File

@@ -0,0 +1,67 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 4
aoc_input = get_input(2022, day)
# aoc_input = """2-4,6-8
# 2-3,4-5
# 5-7,7-9
# 2-8,3-7
# 6-6,4-6
# 2-6,4-8
# """
def part1() -> List[List]:
groups = List(List)
overlaps = 0
for pairs in aoc_input.splitlines():
pair1, pair2 = pairs.split(',')
g1 = List(int).extend(range(int(pair1.split('-')[0]), int(pair1.split('-')[1]) + 1))
g2 = List(int).extend(range(int(pair2.split('-')[0]), int(pair2.split('-')[1]) + 1))
if set(g1).issubset(g2):
overlaps += 1
if set(g2).issubset(g1) or set(g1).issubset(g2):
overlaps += 1
groups.add(g1)
groups.add(g2)
Console.write_line(groups.count(), overlaps)
return groups
def part2(groups: List[List]):
pairs = List(List)
pair = List(List)
for i, group in enumerate(groups):
pair.add(group)
if i % 2 != 0:
pairs.add(pair)
pair = List(List)
overlaps = 0
for pair in pairs:
pair: List = pair
if pair[0].any(lambda x: x in pair[1]) or pair[1].any(lambda x: x in pair[0]):
overlaps += 1
Console.write_line(overlaps)
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
groups = part1()
part2(groups)
Console.write_line()

94
2022/src/day5.py Normal file
View File

@@ -0,0 +1,94 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 5
aoc_input = get_input(2022, day)
aoc_input1 = """ [D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2"""
def get_stacks() -> List[List[str]]:
stacks = List(List)
for line in aoc_input.splitlines():
if line.startswith('move'):
continue
if stacks.count() == 0:
for i in range(int(len(line) / 4 + 1)):
stacks.append(List(str))
for i in range(1, len(line), 4):
x = line[i]
if x.isnumeric() or x == ' ':
continue
stacks[int((i - 1) / 4)].append(x)
return stacks.select(lambda s: s.reverse())
def get_moves() -> List[tuple]:
moves = List(tuple)
for line in aoc_input.splitlines():
if not line.startswith('move'):
continue
move_str = line.split()
moves.append((int(move_str[1]), int(move_str[3]), int(move_str[5])))
return moves
def make_move(stacks: List[List[str]], moves: List[tuple], part_two=None):
if moves.first_or_default() is None:
return
move = moves.first()
if part_two is None:
for i in range(move[0]):
e = stacks[move[1] - 1].last()
stacks[move[2] - 1].append(e)
stacks[move[1] - 1].pop()
else:
elements = stacks[move[1] - 1].take_last(move[0])
stacks[move[2] - 1].extend(elements)
stacks[move[1] - 1] = stacks[move[1] - 1].skip_last(move[0])
moves.remove(move)
make_move(stacks, moves, part_two=part_two)
def part1():
stacks = get_stacks()
make_move(stacks, get_moves())
Console.write_line('Part 1: ', ''.join(stacks.select(lambda s: s.last_or_default()).where(lambda x: x is not None).to_list()))
def part2():
stacks = get_stacks()
make_move(stacks, get_moves(), part_two=True)
Console.write_line('Part 2: ', ''.join(stacks.select(lambda s: s.last_or_default()).where(lambda x: x is not None).to_list()))
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
part1()
part2()
Console.write_line()

64
2022/src/day6.py Normal file
View File

@@ -0,0 +1,64 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 6
aoc_input = get_input(2022, day)
# aoc_input = "mjqjpqmgbljsphdztnvjfqwrcgsmlb"
class Marker:
def __init__(self, part2=False):
self._chars = List(str)
self._max_count = 14 if part2 else 4
@property
def chars(self) -> List[str]:
return self._chars
@property
def is_valid(self) -> bool:
return self._max_count == self._chars.count() == self._chars.distinct().count()
def add_char(self, c: str):
if self._chars.count() == self._max_count:
self._chars.remove_at(0)
self._chars.add(c)
def part1():
marker = Marker()
for i, c in enumerate(aoc_input):
marker.add_char(c)
if not marker.is_valid:
continue
Console.write_line(f'Found marker: {"".join(marker.chars)} at {i + 1}')
break
def part2():
marker = Marker(True)
for i, c in enumerate(aoc_input):
marker.add_char(c)
if not marker.is_valid:
continue
Console.write_line(f'Found marker: {"".join(marker.chars)} at {i + 1}')
break
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
part1()
part2()
Console.write_line()

144
2022/src/day7.py Normal file
View File

@@ -0,0 +1,144 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 7
aoc_input = get_input(2022, day)
aoc_input1 = """$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k"""
class Dir:
def __init__(self, name: str, parent: Optional['Dir'] = None):
self._name = name
self._parent = parent
self._files = List(any)
self._dirs = List(Dir)
@property
def name(self) -> str:
return self._name
@property
def parent(self) -> 'Dir':
return self._parent
@property
def files(self) -> List[str]:
return self._files
@property
def dirs(self) -> List['Dir']:
return self._dirs
@property
def size(self) -> int:
total_size = 0
for file, size in self._files:
total_size += size
for directory in self._dirs:
total_size += directory.size
return total_size
@property
def size_small_files(self) -> int:
total_size = 0
file_size = self.size
if file_size > 100000:
file_size = 0
total_size += file_size
for directory in self._dirs:
d_size = directory.size_small_files
total_size += d_size
return total_size
def add_dir(self, name: str):
self._dirs.append(Dir(name, self))
def add_file(self, name: str, size: int):
self._files.append((name, size))
def get_dirs(pwd: Dir, dirs=None) -> List(Dir):
if dirs is None:
dirs = List(Dir)
for d in pwd.dirs:
dirs.append(d)
get_dirs(d, dirs)
return dirs
def part1() -> Dir:
root = Dir('/', None)
pwd = root
for line in aoc_input.splitlines()[1:]:
s_line = line.split()
if line.startswith('$'):
if s_line[1] == 'ls':
continue
if s_line[2] == '..':
pwd = pwd.parent
else:
pwd = pwd.dirs.where(lambda d: d.name == s_line[2]).single()
continue
p1 = s_line[0]
p2 = s_line[1]
if p1 == 'dir':
pwd.add_dir(p2)
else:
pwd.add_file(p2, int(p1))
return root
def part2(root: Dir):
space_required = 30000000 - (70000000 - root.size)
Console.write_line(Enumerable(int, [*get_dirs(root).select(lambda x: x.size), root.size]).order_by(lambda x: x).where(lambda x: x >= space_required).first())
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
root = part1()
part2(root)
Console.write_line()

83
2022/src/day8.py Normal file
View File

@@ -0,0 +1,83 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 8
aoc_input = get_input(2022, day)
aoc_input1 = """30373
25512
65332
33549
35390"""
def parse(lines: str) -> List[List[int]]:
grid = List(List)
for line in lines.splitlines():
trees = List(int)
for tree in line:
trees.add(int(tree))
grid.add(trees)
return grid
def main(grid: List[List[int]]) -> tuple[int, int]:
# consideration for refactoring part1: select bools then select many count
visible = List(int)
scenic_scores = List(int)
for i, trees in enumerate(grid):
if i == 0 or i == grid.count() - 1:
visible.extend(trees)
continue
for n, t in enumerate(trees):
if n == 0 or n == trees.count() - 1:
visible.add(t)
continue
up = all([t > grid[x][n] for x in range(i - 1, -1, -1)])
down = all([t > grid[x][n] for x in range(i + 1, len(grid))])
left = all([t > x for x in trees[:n]])
right = all([t > x for x in trees[n + 1:]])
for l in range(n + 1, grid.first().count()):
if trees[l] >= t:
break
for r in range(n - 1, -1, -1):
if trees[r] >= t:
break
for d in range(i + 1, grid.count()):
if grid[d][n] >= t:
break
for u in range(i - 1, -1, -1):
if grid[u][n] >= t:
break
# im not proud of this shit
score = (l - n) * (n - r) * (d - i) * (i - u)
scenic_scores.add(score)
if up or down or left or right:
visible.add(t)
return visible.count(), scenic_scores.max()
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
tree_map = parse(aoc_input)
p1 = main(tree_map)
Console.write_line(p1)
Console.write_line()

118
2022/src/day9.py Normal file
View File

@@ -0,0 +1,118 @@
from dataclasses import dataclass
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 9
aoc_input = get_input(2022, day)
aoc_input1 = """R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20"""
@dataclass
class Position:
x: int = 0
y: int = 0
def __repr__(self):
return f'({self.x}, {self.y})'
@property
def as_tuple(self) -> tuple[int, int]:
return self.x, self.y
def get_new_tail(head: Position, tail: Position) -> Position:
diff = Position(head.x - tail.x, head.y - tail.y)
bias = Position(0 if diff.x == 0 else int(diff.x / abs(diff.x)), 0 if diff.y == 0 else int(diff.y / abs(diff.y)))
if abs(diff.x) <= 1 and abs(diff.y) <= 1:
return tail
return Position(tail.x + bias.x, tail.y + bias.y)
def part1():
head = Position(0, 0)
tail = Position(0, 0)
start = Position(0, 0)
steps = {tail.as_tuple}
for line in aoc_input.splitlines():
step, width = line.split()
for i in range(0, int(width)):
match step:
case 'R':
head.x += 1
case 'L':
head.x -= 1
case 'U':
head.y += 1
case 'D':
head.y -= 1
tail = get_new_tail(head, tail)
steps.add(tail.as_tuple)
Console.write_line(start, head, tail)
Console.write_line(len(steps), steps)
def part2():
head = Position(0, 0)
tails = List(int).range(0, 9).select(lambda x: Position(0, 0))
steps = {tails.last().as_tuple}
for line in aoc_input.splitlines():
step, width = line.split()
for i in range(0, int(width)):
match step:
case 'R':
head.x += 1
case 'L':
head.x -= 1
case 'U':
head.y += 1
case 'D':
head.y -= 1
last_t = head
new_tails = List(Position)
for t in tails.to_list():
new_t = get_new_tail(last_t, t)
new_tails.add(new_t)
last_t = new_t
tails = new_tails
steps.add(tails.last().as_tuple)
Console.write_line(head, tails.last())
Console.write_line(len(steps), steps)
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
part1()
part2()
Console.write_line()

23
2022/src/template_dayX.py Normal file
View File

@@ -0,0 +1,23 @@
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 0
aoc_input = get_input(2022, day)
def main():
Console.write_line('hello world!')
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
main()
Console.write_line()