Merge remote-tracking branch 'origin/master'

This commit is contained in:
Stefan Harmuth 2022-08-10 23:35:01 +02:00
commit c254bb8643
7 changed files with 48 additions and 46 deletions

View File

@ -28,17 +28,17 @@ class AOCDay:
self.part_func = [self.part1, self.part2] self.part_func = [self.part1, self.part2]
def part1(self) -> Any: def part1(self) -> Any:
pass raise NotImplementedError()
def part2(self) -> Any: def part2(self) -> Any:
pass raise NotImplementedError()
def runPart(self, part: int, verbose: bool = False, measure_runtime: bool = False, timeit_number: int = 50): def run_part(self, part: int, verbose: bool = False, measure_runtime: bool = False, timeit_number: int = 50):
case_count = 0 case_count = 0
for solution, input_file in self.inputs[part]: for solution, input_file in self.inputs[part]:
exec_time = None exec_time = None
answer = None answer = None
self._loadInput(input_file) self._load_input(input_file)
if not measure_runtime or case_count < len(self.inputs[part]) - 1: if not measure_runtime or case_count < len(self.inputs[part]) - 1:
answer = self.part_func[part]() answer = self.part_func[part]()
@ -50,35 +50,35 @@ class AOCDay:
exec_time = stopwatch.avg_string(timeit_number) exec_time = stopwatch.avg_string(timeit_number)
if solution is None: if solution is None:
printSolution(self.day, part + 1, answer, solution, case_count, exec_time) print_solution(self.day, part + 1, answer, solution, case_count, exec_time)
if answer not in {u"", b"", None, b"None", u"None"}: if answer not in {u"", b"", None, b"None", u"None"}:
self._submit(part + 1, answer) self._submit(part + 1, answer)
else: else:
if verbose or answer != solution: if verbose or answer != solution:
printSolution(self.day, part + 1, answer, solution, case_count, exec_time) print_solution(self.day, part + 1, answer, solution, case_count, exec_time)
if answer != solution: if answer != solution:
return False return False
case_count += 1 case_count += 1
if case_count == len(self.inputs[part]) and not verbose: if case_count == len(self.inputs[part]) and not verbose:
printSolution(self.day, part + 1, answer, exec_time=exec_time) print_solution(self.day, part + 1, answer, exec_time=exec_time)
def run(self, parts: int = 3, verbose: bool = False, measure_runtime: bool = False, timeit_number: int = 50): def run(self, parts: int = 3, verbose: bool = False, measure_runtime: bool = False, timeit_number: int = 50):
if parts & 1: if parts & 1:
self.runPart(0, verbose, measure_runtime, timeit_number) self.run_part(0, verbose, measure_runtime, timeit_number)
if parts & 2: if parts & 2:
self.runPart(1, verbose, measure_runtime, timeit_number) self.run_part(1, verbose, measure_runtime, timeit_number)
def _loadInput(self, filename): def _load_input(self, filename):
file_path = os.path.join(INPUTS_PATH, filename) file_path = os.path.join(INPUTS_PATH, filename)
if not os.path.exists(file_path): if not os.path.exists(file_path):
self._downloadInput(file_path) self._download_input(file_path)
with open(os.path.join(INPUTS_PATH, filename)) as f: with open(os.path.join(INPUTS_PATH, filename)) as f:
self.input = f.read().splitlines() self.input = f.read().splitlines()
def _downloadInput(self, filename: str): def _download_input(self, filename: str):
# FIXME: implement wait time for current day before 06:00:00 ? # FIXME: implement wait time for current day before 06:00:00 ?
session_id = open(".session", "r").readlines()[0].strip() session_id = open(".session", "r").readlines()[0].strip()
response = requests.get( response = requests.get(
@ -212,16 +212,16 @@ class AOCDay:
if input has multiple lines, returns a 2d array (a[line][values]) if input has multiple lines, returns a 2d array (a[line][values])
""" """
if len(self.input) == 1: if len(self.input) == 1:
return splitLine(line=self.input[0], split_char=split_char, return_type=return_type) return split_line(line=self.input[0], split_char=split_char, return_type=return_type)
else: else:
return_array = [] return_array = []
for line in self.input: for line in self.input:
return_array.append(splitLine(line=line, split_char=split_char, return_type=return_type)) return_array.append(split_line(line=line, split_char=split_char, return_type=return_type))
return return_array return return_array
def printSolution(day: int, part: int, solution: Any, test: Any = None, test_case: int = 0, exec_time: str = None): def print_solution(day: int, part: int, solution: Any, test: Any = None, test_case: int = 0, exec_time: str = None):
if test is not None: if test is not None:
print( print(
"%s (TEST day%d/part%d/case%d): got '%s'; expected '%s'" "%s (TEST day%d/part%d/case%d): got '%s'; expected '%s'"
@ -241,7 +241,7 @@ def printSolution(day: int, part: int, solution: Any, test: Any = None, test_cas
print("Day %s, Part %s - Average run time: %s" % (day, part, exec_time)) print("Day %s, Part %s - Average run time: %s" % (day, part, exec_time))
def splitLine(line, split_char: str = ',', return_type: Union[Type, List[Type]] = None): def split_line(line, split_char: str = ',', return_type: Union[Type, List[Type]] = None):
if split_char: if split_char:
line = line.split(split_char) line = line.split(split_char)

View File

@ -18,6 +18,7 @@ import sys
import time import time
from signal import SIGTERM, signal from signal import SIGTERM, signal
DEV_NULL = "/dev/null"
class Daemon: class Daemon:
""" """
@ -26,7 +27,7 @@ class Daemon:
Usage: subclass the Daemon class and override the run() method Usage: subclass the Daemon class and override the run() method
""" """
def __init__(self, pidfile='_.pid', stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): def __init__(self, pidfile='_.pid', stdin=DEV_NULL, stdout=DEV_NULL, stderr=DEV_NULL):
self.stdin = stdin self.stdin = stdin
self.stdout = stdout self.stdout = stdout
self.stderr = stderr self.stderr = stderr

View File

@ -19,10 +19,10 @@ class DataFile(dict):
self.load() self.load()
def load(self): def load(self):
pass raise NotImplementedError()
def save(self): def save(self):
pass raise NotImplementedError()
class JSONFile(DataFile): class JSONFile(DataFile):

View File

@ -2,6 +2,7 @@ from time import sleep
from .schedule import Scheduler from .schedule import Scheduler
from .simplesocket import ClientSocket from .simplesocket import ClientSocket
from .types import StrOrNone
from datetime import timedelta from datetime import timedelta
from enum import Enum from enum import Enum
from typing import Callable, Dict, List, Union from typing import Callable, Dict, List, Union
@ -166,24 +167,24 @@ class ServerMessage(str, Enum):
class User: class User:
user: str identifier: str
nickname: str nickname: str
username: str username: str
hostname: str hostname: str
def __init__(self, user: str): def __init__(self, identifier: str):
self.user = user self.identifier = identifier
if "@" not in self.user: if "@" not in self.identifier:
self.nickname = self.hostname = self.user self.nickname = self.hostname = self.identifier
else: else:
user, self.hostname = self.user.split("@") identifier, self.hostname = self.identifier.split("@")
if "!" in user: if "!" in identifier:
self.nickname, self.username = user.split("!") self.nickname, self.username = identifier.split("!")
else: else:
self.nickname = self.username = user self.nickname = self.username = identifier
def nick(self, new_nick: str): def nick(self, new_nick: str):
self.user.replace("%s!" % self.nickname, "%s!" % new_nick) self.identifier.replace("%s!" % self.nickname, "%s!" % new_nick)
self.nickname = new_nick self.nickname = new_nick
@ -198,12 +199,12 @@ class Channel:
self.userlist = {} self.userlist = {}
def join(self, user: User): def join(self, user: User):
if user.user not in self.userlist: if user.identifier not in self.userlist:
self.userlist[user.user] = user self.userlist[user.identifier] = user
def quit(self, user: User): def quit(self, user: User):
if user.user in self.userlist: if user.identifier in self.userlist:
del self.userlist[user.user] del self.userlist[user.identifier]
class Client: class Client:
@ -212,8 +213,7 @@ class Client:
__server_caps: Dict[str, Union[str, int]] __server_caps: Dict[str, Union[str, int]]
__userlist: Dict[str, User] __userlist: Dict[str, User]
__channellist: Dict[str, Channel] __channellist: Dict[str, Channel]
__server_name: str = None __my_user: StrOrNone
__my_user: str = None
def __init__(self, server: str, port: int, nick: str, username: str, realname: str = "Python Bot"): def __init__(self, server: str, port: int, nick: str, username: str, realname: str = "Python Bot"):
self.__userlist = {} self.__userlist = {}
@ -276,7 +276,6 @@ class Client:
self.__function_register[msg_type] = [func] self.__function_register[msg_type] = [func]
def on_rpl_welcome(self, msg_from: str, msg_to: str, message: str): def on_rpl_welcome(self, msg_from: str, msg_to: str, message: str):
self.__server_name = msg_from
self.__my_user = message.split()[-1] self.__my_user = message.split()[-1]
self.__userlist[self.__my_user] = User(self.__my_user) self.__userlist[self.__my_user] = User(self.__my_user)
@ -302,7 +301,7 @@ class Client:
def on_nick(self, msg_from: str, msg_to: str, message: str): def on_nick(self, msg_from: str, msg_to: str, message: str):
self.__userlist[msg_from].nick(msg_to) self.__userlist[msg_from].nick(msg_to)
self.__userlist[self.__userlist[msg_from].user] = self.__userlist[msg_from] self.__userlist[self.__userlist[msg_from].identifier] = self.__userlist[msg_from]
del self.__userlist[msg_from] del self.__userlist[msg_from]
def on_join(self, msg_from: str, msg_to: str, message: str): def on_join(self, msg_from: str, msg_to: str, message: str):

View File

@ -163,9 +163,6 @@ class Stack(LinkedList):
def push(self, obj: Any): def push(self, obj: Any):
self._append(obj) self._append(obj)
def pop(self) -> Any:
return self._pop()
def peek(self) -> Any: def peek(self) -> Any:
return self._tail.value return self._tail.value

View File

@ -1,7 +1,7 @@
from dataclasses import dataclass from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from tools.lists import Queue, Stack from tools.lists import Queue, Stack
from typing import Any, Union from typing import Any, List, Union
class Rotate(Enum): class Rotate(Enum):
@ -29,6 +29,12 @@ class TreeNode:
return str(self) return str(self)
class TrieNode:
value: str
parent: Union['TrieNode', None] = None
children: List['TrieNode'] = field(default_factory=list)
def update_node(node: TreeNode): def update_node(node: TreeNode):
left_depth = node.left.height if node.left is not None else -1 left_depth = node.left.height if node.left is not None else -1
right_depth = node.right.height if node.right is not None else -1 right_depth = node.right.height if node.right is not None else -1
@ -112,10 +118,8 @@ class BinaryTree:
while node is not None: while node is not None:
if obj < node.value: if obj < node.value:
node = node.left node = node.left
continue
elif obj > node.value: elif obj > node.value:
node = node.right node = node.right
continue
else: else:
return node return node
@ -266,7 +270,7 @@ class Heap(BinarySearchTree):
c_node = c_node.left c_node = c_node.left
ret = c_node.value ret = c_node.value
self.remove(ret, c_node.parent) self._remove(c_node)
return ret return ret
def popMax(self): def popMax(self):
@ -278,7 +282,7 @@ class Heap(BinarySearchTree):
c_node = c_node.right c_node = c_node.right
ret = c_node.value ret = c_node.value
self.remove(ret, c_node.parent) self._remove(c_node)
return ret return ret

View File

@ -1,6 +1,7 @@
from typing import Union from typing import Union
Numeric = Union[int, float] Numeric = Union[int, float]
StrOrNone = Union[str, None]
IntOrNone = Union[int, None] IntOrNone = Union[int, None]
FloatOrNone = Union[float, None] FloatOrNone = Union[float, None]
NumericOrNone = Union[Numeric, None] NumericOrNone = Union[Numeric, None]