Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
c254bb8643
32
tools/aoc.py
32
tools/aoc.py
@ -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)
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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):
|
||||||
|
|||||||
35
tools/irc.py
35
tools/irc.py
@ -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):
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user