Moved year
This commit is contained in:
9
2022/LICENSE
Normal file
9
2022/LICENSE
Normal 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
15
2022/README.md
Normal 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
3
2022/deps.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
cpl-cli==2022.12.0
|
||||
cpl-core==2022.12.0
|
||||
cpl-query==2022.12.1.post1
|
0
2022/src/aoc/__init__.py
Normal file
0
2022/src/aoc/__init__.py
Normal file
41
2022/src/aoc/aoc.py
Normal file
41
2022/src/aoc/aoc.py
Normal 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
34
2022/src/day1.py
Normal 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
220
2022/src/day10.py
Normal 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
122
2022/src/day11.py
Normal 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
80
2022/src/day12.py
Normal 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
86
2022/src/day13.py
Normal 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
165
2022/src/day14.py
Normal 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
92
2022/src/day15.py
Normal 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
96
2022/src/day2.py
Normal 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
60
2022/src/day3.py
Normal 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
67
2022/src/day4.py
Normal 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
94
2022/src/day5.py
Normal 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
64
2022/src/day6.py
Normal 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
144
2022/src/day7.py
Normal 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
83
2022/src/day8.py
Normal 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
118
2022/src/day9.py
Normal 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
23
2022/src/template_dayX.py
Normal 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()
|
Reference in New Issue
Block a user