Skip to content

Instantly share code, notes, and snippets.

@sglyon
Created December 7, 2024 15:19
Show Gist options
  • Save sglyon/b9a6a23268eb37840874ecea63f383c2 to your computer and use it in GitHub Desktop.
Save sglyon/b9a6a23268eb37840874ecea63f383c2 to your computer and use it in GitHub Desktop.
AOC 2024 Python
from aoc import AoCDay
class Day7(AoCDay):
def __init__(self):
super().__init__(7)
def parse(self):
raw = super().parse()
self.lines = []
for row in raw:
target, rest = row.split(": ")
numbers = list(map(int, rest.split()))
self.lines.append((int(target), numbers))
def can_be_true(self, x, i, numbers, concat=False):
num = numbers[i]
if i == 0:
return x == num
val_div = x / num
val_minus = x - num
can_div = val_div == int(val_div) and val_div >= 0
can_minus = val_minus >= 0
# need int for val_div
if can_div:
val_div = int(val_div)
can_cat = False
val_cat = 0
if concat:
str_x = str(x)
str_num = str(num)
if str_x.endswith(str_num):
start = str_x[:-len(str_num)]
if start == "":
val_cat = 0
can_cat = True
else:
val_cat = int(start)
can_cat = True
pass
# short circut operations here...
div_true = can_div and self.can_be_true(int(val_div), i-1, numbers, concat)
minus_true = can_minus and self.can_be_true(val_minus, i-1, numbers, concat)
cat_true = can_cat and self.can_be_true(val_cat, i-1, numbers, concat)
return div_true or minus_true or cat_true
def solve1(self):
return sum(
map(
lambda x: x[0],
filter(lambda x: self.can_be_true(x[0], len(x[1])-1, x[1]), self.lines)
)
)
def solve2(self):
return sum(
map(
lambda x: x[0],
filter(lambda x: self.can_be_true(x[0], len(x[1])-1, x[1], True), self.lines)
)
)
class AoCDay(ABC):
def __init__(self, day_number: int, session_cookie: str, year: int = 2024):
self.day_number = day_number
self.year = year
self.session_cookie = session_cookie
self.input = self.parse()
@property
def input_file_name(self):
return f"day{self.day_number:02d}_input.txt"
@property
def text_file_name(self):
return f"day{self.day_number:02d}_text.html"
@property
def headers(self):
return {"cookie": f"session={self.session_cookie}"}
def split_example_txt_to_lines(self, txt):
return list(map(str.strip, txt.split("\n")))
def parse(self):
self.ensure_input()
with open(self.input_file_name) as f:
return list(map(str.strip, f.readlines()))
def ensure_input(self):
if not os.path.isfile(self.input_file_name):
input = self.fetch_problem_input().text
with open(self.input_file_name, "w") as f:
f.write(input)
def load_text(self):
if not os.path.isfile(self.text_file_name):
text = self.fetch_html_text().text
with open(self.text_file_name, "w") as f:
f.write(text)
return text
with open(self.text_file_name, "r") as f:
return f.read()
def fetch_problem_input(self):
url = f"https://adventofcode.com/{self.year}/day/{self.day_number}/input"
res = requests.get(url, headers=self.headers)
return res
def fetch_html_text(self):
url = f"https://adventofcode.com/{self.year}/day/{self.day_number}"
res = requests.get(url, headers=self.headers)
return res
def _repr_markdown_(self):
text = self.load_text()
soup = BeautifulSoup(text, "html.parser")
return soup.prettify()
# return soup.article.prettify()
@abstractmethod
def solve1(self):
pass
@abstractmethod
def solve2(self):
pass
def _submit(self, level, value):
url = f"https://adventofcode.com/{self.year}/day/{self.day_number}/answer"
headers = self.headers
headers["content-type"] = "application/x-www-form-urlencoded"
return requests.post(
url, headers=self.headers, data=dict(level=level, value=value)
)
def submit_1(self):
value = self.solve1()
return self._submit(1, value)
def submit_2(self):
value = self.solve2()
return self._submit(2, value)
@staticmethod
def code_for_new_day(day):
return textwrap.dedent(f"""\
class Day{day}(AoCDay):
def __init__(self):
super().__init__({day})
def solve1(self):
pass
def solve2(self):
pass
d{day} = Day{day}()
d{day}.solve1(), d{day}.solve2()
""")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment