Skip to content

Commit

Permalink
Merge pull request #251 from Stegallo/2024
Browse files Browse the repository at this point in the history
2024
  • Loading branch information
Stegallo authored Dec 7, 2024
2 parents bd6d265 + f9d7fe9 commit 3bbc035
Show file tree
Hide file tree
Showing 6 changed files with 451 additions and 0 deletions.
27 changes: 27 additions & 0 deletions tests/y_2024/test_2024_day3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# from __future__ import annotations

from unittest.mock import mock_open, patch

from y_2024.day3 import Day

with patch(
"builtins.open",
mock_open(
read_data="""xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))""", # noqa: E501
),
):
day = Day()


def test__preprocess_input():
assert True


def test_calculate_1():
r = day._calculate_1()
assert r == 161


def test_calculate_2():
r = day._calculate_2()
assert r == 48
38 changes: 38 additions & 0 deletions y_2024/day0.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import Optional

from pydantic.dataclasses import dataclass

from common.aoc import AoCDay


@dataclass
class Row:
original: str
processed: Optional[str] = None

def __post_init__(self) -> None:
self.processed = "" # self.original


class Day(AoCDay):
def __init__(self, test=0):
super().__init__(__name__, test)

def _preprocess_input(self):
# self.__input_data = [[int(i) for i in chunk] for chunk in self._input_data]
print(f"{self._input_data=}")
print(f"{len(self._input_data)=}")
print(f"{len(self._input_data[0])=}")
# self.__input_data = [Row(i) for i in self._input_data[0]]
self.__input_data = [Row(i) for j in self._input_data for i in j]

def _calculate_1(self):
result = 0
for x in self.__input_data:
print(f"{x}")
...
return result

def _calculate_2(self):
result = 0
return result
57 changes: 57 additions & 0 deletions y_2024/day3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import re

from pydantic.dataclasses import dataclass

from common.aoc import AoCDay


@dataclass
class Row:
original: str


@dataclass
class Mul:
op1: int
op2: int

@staticmethod
def from_str(string):
return (lambda x, y: Mul(int(x), int(y)))(
*string.replace(")", "").replace("mul(", "").split(",")
)

@property
def prod(self):
return self.op1 * self.op2


class Day(AoCDay):
def __init__(self, test=0):
super().__init__(__name__, test)

def _preprocess_input(self):
self.__input_data = [Row(i) for i in self._input_data[0]]

def _calculate_1(self):
result = 0
p = re.compile(r"mul\(\d{1,3}\,\d{1,3}\)")
for j in self.__input_data:
for i in p.findall(j.original):
result += Mul.from_str(i).prod
return result

def _calculate_2(self):
result = 0
p = re.compile(r"mul\(\d{1,3}\,\d{1,3}\)|do\(\)|don't\(\)")
do = True
for j in self.__input_data:
for i in p.findall(j.original):
if i == "do()":
do = True
elif i == "don't()":
do = False
continue
elif "mul" in i and do:
result += Mul.from_str(i).prod
return result
121 changes: 121 additions & 0 deletions y_2024/day4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
from typing import Optional

from pydantic.dataclasses import dataclass

from common.aoc import AoCDay


@dataclass
class Row:
original: str
processed: Optional[str] = None

def __post_init__(self) -> None:
self.processed = "" # self.original


class Day(AoCDay):
def __init__(self, test=0):
super().__init__(__name__, test)

def _preprocess_input(self):
self.__input_data = [[i for i in chunk] for chunk in self._input_data]
self.grid = {}
for y in self.__input_data:
for c, x in enumerate(y):
for i, k in enumerate(x):
self.grid[(c, i)] = k

def _calculate_1(self):
result = 0
for y in self.__input_data:
for c, x in enumerate(y):
for i, k in enumerate(x):
if k != "X":
continue
l = (c, i - 1)
r = (c, i + 1)
u = (c - 1, i)
d = (c + 1, i)
lu = (c - 1, i - 1)
ru = (c - 1, i + 1)
ld = (c + 1, i - 1)
rd = (c + 1, i + 1)
if self.grid.get(l) == "M":
if self.grid.get((c, i - 2)) == "A":
if self.grid.get((c, i - 3)) == "S":
result += 1
if self.grid.get(r) == "M":
if self.grid.get((c, i + 2)) == "A":
if self.grid.get((c, i + 3)) == "S":
result += 1
if self.grid.get(u) == "M":
if self.grid.get((c - 2, i)) == "A":
if self.grid.get((c - 3, i)) == "S":
result += 1
if self.grid.get(d) == "M":
if self.grid.get((c + 2, i)) == "A":
if self.grid.get((c + 3, i)) == "S":
result += 1
if self.grid.get(lu) == "M":
if self.grid.get((c - 2, i - 2)) == "A":
if self.grid.get((c - 3, i - 3)) == "S":
result += 1
if self.grid.get(ru) == "M":
if self.grid.get((c - 2, i + 2)) == "A":
if self.grid.get((c - 3, i + 3)) == "S":
result += 1
if self.grid.get(ld) == "M":
if self.grid.get((c + 2, i - 2)) == "A":
if self.grid.get((c + 3, i - 3)) == "S":
result += 1
if self.grid.get(rd) == "M":
if self.grid.get((c + 2, i + 2)) == "A":
if self.grid.get((c + 3, i + 3)) == "S":
result += 1
return result

def _calculate_2(self):
result = 0
for y in self.__input_data:
for c, x in enumerate(y):
for i, k in enumerate(x):
if k != "A":
continue
lu = (c - 1, i - 1)
ru = (c - 1, i + 1)
ld = (c + 1, i - 1)
rd = (c + 1, i + 1)

if (
self.grid.get(lu) == "M"
and self.grid.get(rd) == "S"
and self.grid.get(ru) == "M"
and self.grid.get(ld) == "S"
):
result += 1

if (
self.grid.get(lu) == "S"
and self.grid.get(rd) == "M"
and self.grid.get(ru) == "S"
and self.grid.get(ld) == "M"
):
result += 1

if (
self.grid.get(lu) == "M"
and self.grid.get(rd) == "S"
and self.grid.get(ru) == "S"
and self.grid.get(ld) == "M"
):
result += 1

if (
self.grid.get(lu) == "S"
and self.grid.get(rd) == "M"
and self.grid.get(ru) == "M"
and self.grid.get(ld) == "S"
):
result += 1
return result
141 changes: 141 additions & 0 deletions y_2024/day5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
from typing import Optional

from pydantic.dataclasses import dataclass
from collections import defaultdict
from common.aoc import AoCDay


@dataclass
class Row:
original: str
processed: Optional[str] = None

def __post_init__(self) -> None:
self.processed = "" # self.original


@dataclass
class Rule:
original: str
processed: Optional[list[str]] = None

def __post_init__(self) -> None:
self.processed = self.original.split("|")


@dataclass
class Update:
original: str
processed: Optional[list[str]] = None

def __post_init__(self) -> None:
self.processed = self.original.split(",")


class Day(AoCDay):
def __init__(self, test=0):
super().__init__(__name__, test)

def _preprocess_input(self):
# self.__input_data = [[int(i) for i in chunk] for chunk in self._input_data]
# print(f"{self._input_data=}")
# print(f"{len(self._input_data[0])=}")
self.__input_data_1 = [Rule(i) for i in self._input_data[0]]
self.__input_data_2 = [Update(i) for i in self._input_data[1]]

def _calculate_1(self):
result = 0
foll = defaultdict(list)
prec = defaultdict(list)
for x in self.__input_data_1:
foll[x.processed[0]].append(x.processed[1])
prec[x.processed[1]].append(x.processed[0])

# print(foll)
# print(prec)
self.valids = []
for x in self.__input_data_2:
valid = True
for c, i in enumerate(x.processed):
for d, j in enumerate(x.processed[c + 1 :]):
# print(i,j)
if j not in foll[i]:
valid = False
if valid:
# print(f"{x.processed}, {len(x.processed)//2=}")
result += int(x.processed[len(x.processed) // 2])
self.valids.append(x.processed)

return result

def _calculate_2(self):
# print(self.valids)
# return 0
result = 0
foll = defaultdict(list)
orfoll = defaultdict(list)
# fixed = []
# prec = defaultdict(list)
for x in self.__input_data_1:
foll[x.processed[0]].append(x.processed[1])
orfoll[x.processed[0]].append(x.processed[1])
# prec[x.processed[1]].append(x.processed[0])
print(foll)

# for k,v in prec.foll():
# print(k, len(v))
# return
# first = True
# while True:
#
# if len(foll.keys())<1:
# break
# for i in foll.keys():
# #
# if len(foll[i])==1:
# if first:
# fixed.append(foll[i][0])
# first = False
# fixed.append(i)
# del foll[i]
# for k, v in foll.items():
# new_val = [k for k in v if k!=i]
# foll[k]= new_val
# break
#
# fixed = fixed[::-1]
# fixed = {i: c for c,i in enumerate(fixed)}
# print(fixed)

# return 0
for x in self.__input_data_2:
valid = True
for c, i in enumerate(x.processed):
for d, j in enumerate(x.processed[c + 1 :]):
# print(i,j)
if j not in orfoll[i]:
valid = False
if valid:
# print(f"{x.processed}, {len(x.processed)//2=}")
pass
# result+=int(x.processed[len(x.processed)//2])
else:
# breakpoint()
proposed = list(x.processed)
valid_p = False
while not valid_p:
ordered = True
# print(proposed)
for i in range(len(proposed) - 1):
j = i + 1
# print(proposed, i, j)
if proposed[j] not in foll[proposed[i]]:
ordered = False
proposed[j], proposed[i] = proposed[i], proposed[j]
if ordered:
valid_p = True
break

result += int(proposed[len(proposed) // 2])

return result
Loading

0 comments on commit 3bbc035

Please sign in to comment.