Gyrfalcon's recent activity
-
Comment on Announcing Tildes' Make Something Month (Timasomo) for 2023! in ~creative.timasomo
-
Comment on Monitor recommendations? in ~tech
Gyrfalcon That's super weird, I have a 1440p monitor with an M1 Mac for work and a Linux desktop for personal and I've never noticed this. My screen is 27" and I use it over HDMI for the Mac, is that...That's super weird, I have a 1440p monitor with an M1 Mac for work and a Linux desktop for personal and I've never noticed this. My screen is 27" and I use it over HDMI for the Mac, is that similar to your setup? Either way, seems like this could be a deal breaker or a complete non issue for OP depending on them as an individual.
-
Comment on Does anyone actually like canned beans? in ~food
Gyrfalcon I honestly don't think I've ever cooked a dried bean? My family always did canned for convenience, and with my SO having food allergies, dried beans are much more likely to be cross contaminated...I honestly don't think I've ever cooked a dried bean? My family always did canned for convenience, and with my SO having food allergies, dried beans are much more likely to be cross contaminated and are almost never labeled as gluten free, so it's just not worth the additional effort and stress to find ones that work for her.
In conclusion, maybe dried beans would be a flavor revolution for me, but I love beans even from cans so I kinda doubt it.
-
Comment on Day 10: Cathode-Ray Tube in ~comp
Gyrfalcon This one I think I got a good handle on. I had some trouble with part 2 because I initially thought I would need to do something special to handle the order of events, but it turned out that...This one I think I got a good handle on. I had some trouble with part 2 because I initially thought I would need to do something special to handle the order of events, but it turned out that didn't matter, but what did matter was me forgetting that upper bounds are non inclusive and also that formatting multiline strings can be hard.
Part 1 and 2, Python
current_dir = os.path.realpath(os.path.dirname(__file__)) INPUT_FILE = "/".join([current_dir, "input.txt"]) TEST_FILE_1 = "/".join([current_dir, "test1.txt"]) TEST_RESULTS_1 = ( 13140, ( "##..##..##..##..##..##..##..##..##..##..\n" "###...###...###...###...###...###...###.\n" "####....####....####....####....####....\n" "#####.....#####.....#####.....#####.....\n" "######......######......######......####\n" "#######.......#######.......#######....." ), ) def process_command(command: List[str], signal_strength: int) -> List[int]: if command[0] == "noop": return [signal_strength] return [signal_strength, signal_strength + int(command[1])] def run_computer(commands: List[List[str]]) -> List[int]: signal_history = [1] signal_strength = 1 for command in commands: signal_history.extend(process_command(command, signal_strength)) signal_strength = signal_history[-1] return signal_history def analyze_signal(signal_history: List[int]) -> int: return sum((signal_history[idx] * (idx + 1) for idx in range(19, 220, 40))) def draw_screen(signal_history: List[int]) -> str: pixels: List[str] = [] for idx in range(240): if abs((len(pixels) % 40) - signal_history[idx]) < 2: pixels.append("#") else: pixels.append(".") grid = ["".join(pixels[0 + idx : 40 + idx]) for idx in range(0, 201, 40)] return "\n".join(grid) def main(filepath: str) -> Tuple[int, str]: commands = [line.split() for line in load_file.load_cleaned_lines(filepath)] signal_history = run_computer(commands) return (analyze_signal(signal_history), draw_screen(signal_history))
-
Comment on Day 8: Treetop Tree House in ~comp
Gyrfalcon Okay, I think I see the main difference in how we approached the problem. You looked at even the first part from the tree perspective, whereas I looked at that from a row and column wise...Okay, I think I see the main difference in how we approached the problem. You looked at even the first part from the tree perspective, whereas I looked at that from a row and column wise perspective. Even with that I still think I would have made a bunch of loops rather than mapping things into lambdas, but I think that's more an issue of not actually spending that much time in Python and not really having a good handle on functional approaches than anything else.
-
Comment on Day 6: Tuning Trouble in ~comp
Gyrfalcon Well I definitely appreciate you posting, even though I can't say I understand what is going on all that much better after reading you describe what it is.Well I definitely appreciate you posting, even though I can't say I understand what is going on all that much better after reading you describe what it is.
-
Comment on Day 9: Rope Bridge in ~comp
Gyrfalcon Late, long, and clunky, but correct solution! Ended up refactoring for part 2 to make things configurable which helped marginally, but not as much as one might hope, since that wasn't really the...Late, long, and clunky, but correct solution! Ended up refactoring for part 2 to make things configurable which helped marginally, but not as much as one might hope, since that wasn't really the part I'm not proud of anyway lol.
Part 1 and 2, Python
current_dir = os.path.realpath(os.path.dirname(__file__)) INPUT_FILE = "/".join([current_dir, "input.txt"]) TEST_FILE_1 = "/".join([current_dir, "test1.txt"]) TEST_RESULTS_1 = (13, 1) TEST_FILE_2 = "/".join([current_dir, "test2.txt"]) TEST_RESULTS_2 = (88, 36) def tail_move(head_pos, tail_pos: Tuple[int, int]) -> Tuple[int, int]: if head_pos[0] == tail_pos[0]: if head_pos[1] == tail_pos[1] + 2: return (tail_pos[0], tail_pos[1] + 1) if head_pos[1] == tail_pos[1] - 2: return (tail_pos[0], tail_pos[1] - 1) return tail_pos if head_pos[1] == tail_pos[1]: if head_pos[0] == tail_pos[0] + 2: return (tail_pos[0] + 1, tail_pos[1]) if head_pos[0] == tail_pos[0] - 2: return (tail_pos[0] - 1, tail_pos[1]) return tail_pos if ( (head_pos[0] == tail_pos[0] + 2 and head_pos[1] == tail_pos[1] + 1) or (head_pos[0] == tail_pos[0] + 1 and head_pos[1] == tail_pos[1] + 2) or (head_pos[0] == tail_pos[0] + 2 and head_pos[1] == tail_pos[1] + 2) ): return (tail_pos[0] + 1, tail_pos[1] + 1) if ( (head_pos[0] == tail_pos[0] - 2 and head_pos[1] == tail_pos[1] + 1) or (head_pos[0] == tail_pos[0] - 1 and head_pos[1] == tail_pos[1] + 2) or (head_pos[0] == tail_pos[0] - 2 and head_pos[1] == tail_pos[1] + 2) ): return (tail_pos[0] - 1, tail_pos[1] + 1) if ( (head_pos[0] == tail_pos[0] + 2 and head_pos[1] == tail_pos[1] - 1) or (head_pos[0] == tail_pos[0] + 1 and head_pos[1] == tail_pos[1] - 2) or (head_pos[0] == tail_pos[0] + 2 and head_pos[1] == tail_pos[1] - 2) ): return (tail_pos[0] + 1, tail_pos[1] - 1) if ( (head_pos[0] == tail_pos[0] - 2 and head_pos[1] == tail_pos[1] - 1) or (head_pos[0] == tail_pos[0] - 1 and head_pos[1] == tail_pos[1] - 2) or (head_pos[0] == tail_pos[0] - 2 and head_pos[1] == tail_pos[1] - 2) ): return (tail_pos[0] - 1, tail_pos[1] - 1) return tail_pos def run_commands(commands: List[List[str]], rope_length: int) -> Set[Tuple[int, int]]: rope_pos = [(0, 0) for _ in range(rope_length)] visited = {rope_pos[-1]} moves = { "R": lambda pos: (pos[0] + 1, pos[1]), "L": lambda pos: (pos[0] - 1, pos[1]), "U": lambda pos: (pos[0], pos[1] + 1), "D": lambda pos: (pos[0], pos[1] - 1), } for command in commands: for _ in range(int(command[1])): rope_pos[0] = moves[command[0]](rope_pos[0]) for idx in range(1, rope_length): rope_pos[idx] = tail_move(rope_pos[idx - 1], rope_pos[idx]) visited.add(rope_pos[-1]) return visited def main(filepath: str) -> Tuple[int, int]: commands = [line.split() for line in load_file.load_cleaned_lines(filepath)] return (len(run_commands(commands, 2)), len(run_commands(commands, 10))) if __name__ == "__main__": part1, part2 = main(INPUT_FILE) print(part1) print(part2)
-
Comment on Day 8: Treetop Tree House in ~comp
Gyrfalcon Could you share more about how you arrived at this solution? You allege that it is not optimal, which I can't say one way or the other, but I do find it elegant and concise - and something I never...Could you share more about how you arrived at this solution? You allege that it is not optimal, which I can't say one way or the other, but I do find it elegant and concise - and something I never would have come up with even if I had days to work on it.
-
Comment on Day 8: Treetop Tree House in ~comp
Gyrfalcon Well I certainly repeated myself in this code, and Python's "don't modify while iterating" concept is not one I am fond of, but it works. Part 1 and 2, Python Tree = namedtuple("Tree", ["height",...Well I certainly repeated myself in this code, and Python's "don't modify while iterating" concept is not one I am fond of, but it works.
Part 1 and 2, Python
Tree = namedtuple("Tree", ["height", "visible"]) def process_grid(lines: List[str]) -> List[List[Tree]]: return [[Tree(int(height), False) for height in line] for line in lines] def determine_visible(grid: List[List[Tree]]): # Left to right for row_idx in range(len(grid)): max_height: int = -1 for col_idx in range(len(grid[row_idx])): if grid[row_idx][col_idx].height > max_height: max_height = grid[row_idx][col_idx].height grid[row_idx][col_idx] = grid[row_idx][col_idx]._replace(visible=True) # Right to left for row_idx in range(len(grid)): max_height = -1 for col_idx in range(len(grid[row_idx]) - 1, -1, -1): if grid[row_idx][col_idx].height > max_height: max_height = grid[row_idx][col_idx].height grid[row_idx][col_idx] = grid[row_idx][col_idx]._replace(visible=True) # top to bottom for row_idx in range(len(grid)): max_height = -1 for col_idx in range(len(grid[row_idx])): if grid[col_idx][row_idx].height > max_height: max_height = grid[col_idx][row_idx].height grid[col_idx][row_idx] = grid[col_idx][row_idx]._replace(visible=True) # bottom to top for row_idx in range(len(grid)): max_height = -1 for col_idx in range(len(grid[row_idx]) - 1, -1, -1): if grid[col_idx][row_idx].height > max_height: max_height = grid[col_idx][row_idx].height grid[col_idx][row_idx] = grid[col_idx][row_idx]._replace(visible=True) def viewing_score(grid: List[List[Tree]], row: int, col: int) -> int: curr_tree = grid[row][col] up = 0 for row_idx in range(row - 1, -1, -1): if grid[row_idx][col].height >= curr_tree.height: up += 1 break up += 1 down = 0 for row_idx in range(row + 1, len(grid)): if grid[row_idx][col].height >= curr_tree.height: down += 1 break down += 1 left = 0 for col_idx in range(col - 1, -1, -1): if grid[row][col_idx].height >= curr_tree.height: left += 1 break left += 1 right = 0 for col_idx in range(col + 1, len(grid[row])): if grid[row][col_idx].height >= curr_tree.height: right += 1 break right += 1 return up * down * left * right def main(filepath: str) -> Tuple[int, int]: unprocessed_grid = load_file.load_cleaned_lines(filepath) grid = process_grid(unprocessed_grid) determine_visible(grid) return ( sum((tree.visible for row in grid for tree in row)), max( ( viewing_score(grid, row_idx, col_idx) for row_idx, row in enumerate(grid) for col_idx, tree in enumerate(row) ) ), )
-
Comment on Day 7: No Space Left On Device in ~comp
Gyrfalcon Well, today was definitely not a good day to try an object oriented approach while attempting to continue forcing static typing into Python, and you can see that in how long and clunky my code is....Well, today was definitely not a good day to try an object oriented approach while attempting to continue forcing static typing into Python, and you can see that in how long and clunky my code is. But, it works, and I'm going to keep telling myself that that is the only thing that matters.
Parts 1 and 2, Python
class FilesystemObject: def __init__(self, parent, name: str): self.name = name self.parent = parent # Want to hint this, but get not defined error? @property def size(self) -> int: raise NotImplementedError class Directory(FilesystemObject): def __init__( self, parent, # Want to hint this, but get not defined error? name: str, children: Optional[Dict[str, FilesystemObject]], ): if children is None: self.children: Dict[str, FilesystemObject] = {} else: self.children = children super().__init__(parent, name) def add_child(self, child: FilesystemObject): self.children[child.name] = child @property def size(self) -> int: return sum((item.size for item in self.children.values())) class File(FilesystemObject): def __init__(self, parent: Optional[Directory], name: str, size: int): self._size = size super().__init__(parent, name) @property def size(self) -> int: return self._size def parse_commands(commands: List[str]) -> Directory: root = Directory(None, "/", None) cwd = root ls_mode = False for command in commands[1:]: breakdown = command.split() if breakdown[0] == "$": ls_mode = False if breakdown[1] == "cd": if breakdown[2] == "..": cwd = cast(Directory, cwd.parent) continue if breakdown[2] == "/" and root is not None: cwd = root continue if breakdown[2] == "/" and root is None: root = Directory(cwd, "/", None) cwd = root continue cwd = cast(Directory, cwd.children[breakdown[2]]) elif breakdown[1] == "ls": ls_mode = ( True # I don't think I need this but if we expand this I might ) elif ls_mode: if breakdown[0] == "dir": cwd.add_child(Directory(cwd, breakdown[1], None)) continue cwd.add_child(File(cwd, breakdown[1], int(breakdown[0]))) else: raise NotImplementedError return root def find_small(current: FilesystemObject) -> List[int]: if isinstance(current, File): return [] if current.size <= 100000: out = [current.size] for child in cast(Directory, current).children.values(): out.extend(find_small(child)) return out out = [] for child in cast(Directory, current).children.values(): out.extend(find_small(child)) return out def find_bigger(current: FilesystemObject, minimum: int) -> List[int]: if isinstance(current, File): return [] if current.size >= minimum: out = [current.size] for child in cast(Directory, current).children.values(): out.extend(find_bigger(child, minimum)) return out return [] def main(filepath: str) -> Tuple[int, int]: inputs = load_file.load_cleaned_lines(filepath) root_dir = parse_commands(inputs) target = 30000000 - (70000000 - root_dir.size) return (sum(find_small(root_dir)), min(find_bigger(root_dir, target)))
-
Comment on Day 6: Tuning Trouble in ~comp
Gyrfalcon Do you have a link to where I could learn more about Python-ish? When I try to google it I just get a bunch of people talking about things that are like or similar to Python and not what you are...Do you have a link to where I could learn more about Python-ish? When I try to google it I just get a bunch of people talking about things that are like or similar to Python and not what you are using.
-
Comment on Day 5: Supply Stacks in ~comp
Gyrfalcon An interesting idea, but I don't think assertions are accounted for when mypy parses the code. Something like this: instructions = [] indices = (1, 3, 5) for instruction in lines[line_num + 1 :]:...An interesting idea, but I don't think assertions are accounted for when mypy parses the code. Something like this:
instructions = [] indices = (1, 3, 5) for instruction in lines[line_num + 1 :]: test = tuple([int(instruction.strip().split()[idx]) for idx in indices]) assert len(test) == 3 instructions.append(test)
...yields this complaint:
aoc2022/day5/solution.py:43: error: Incompatible return value type (got "Tuple[List[deque[str]], List[Tuple[int, ...]]]", expected "Tuple[List[deque[str]], List[Tuple[int, int, int]]]") [return-value]
I also tried hinting
test
asTuple[int, int, int]
but that got a type mismatch on assignment complaint. I think mypy will always assume that a tuple constructed from a loop or comprehension is indeterminate in size :/ -
Comment on Day 6: Tuning Trouble in ~comp
Gyrfalcon Well after yesterday saying that I had never done regular expressions in Python I saw a text matching challenge and tried it and then figured out that this is not, in fact, the sort of task that...Well after yesterday saying that I had never done regular expressions in Python I saw a text matching challenge and tried it and then figured out that this is not, in fact, the sort of task that regular expressions make easy. I ended up doing this a little differently than the other Python solutions I see so far today, not using either queues or sets, but getting to test drive
for else
syntax, which was neat. I also did it kind of a clunky, single use way for part one, and then wrote part 2 generally so I could replace my part 1 function, though I left it for posterity. I do think my solution has a useful benefit, in that if it finds, say that the last two characters in a long search window are the same, it will skip forward such that the window starts with what was previously the last character, since we know that all windows that include those two characters at the end will not be what we are looking for.Parts 1 and 2, Python
def find_packet_marker(message: str) -> int: end = 3 while end < len(message): if message[end - 3] in message[end - 2 : end + 1]: end += 1 continue if message[end - 2] in message[end - 1 : end + 1]: end += 2 continue if message[end - 1] == message[end]: end += 3 continue return end + 1 return -1 def find_marker(message: str, marker_size: int) -> int: end = marker_size - 1 while end < len(message): for offset in range(marker_size - 1, 0, -1): if message[end - offset] in message[end - (offset - 1) : end + 1]: end += marker_size - offset break else: return end + 1 return -1 def main(filepath: str) -> Tuple[int, int]: message = load_file.load_cleaned_lines(filepath)[0] return (find_marker(message, 4), find_marker(message, 14))
-
Comment on Day 5: Supply Stacks in ~comp
Gyrfalcon Going to be honest, I saw a chance to whip out deque and I just went for it even though nothing in part 1 indicated that it couldn't be handled with a regular Python list. It was probably actually...Going to be honest, I saw a chance to whip out
deque
and I just went for it even though nothing in part 1 indicated that it couldn't be handled with a regular Python list. It was probably actually a hinderance overall, but I still enjoyed getting to play with it. You may also notice that I didn't use regex, which is because I have not really used it in Python and continue to get away with that.On the feedback front, if anyone here is familiar with
mypy
and it's enforcement of static typing, is there any good way to fill or construct a tuple using a loop while enforcing its length? I kept trying to do that with the translated instructions in my input parsing function but eventually gave up and hand wrote the bit since it was only 3 elements anyway.Parts 1 and 2
def parse_input( lines: List[str], ) -> Tuple[List[deque[str]], List[Tuple[int, int, int]]]: line_num = 0 while lines[line_num] != "\n": line_num += 1 num_stacks = int(lines[line_num - 1].split()[-1]) crates: List[deque[str]] = [deque() for stack in range(num_stacks)] for layer in lines[line_num - 2 :: -1]: # doing this the lazy way because I think I'll get away with it for stack, location in enumerate(range(1, len(layer), 4)): if layer[location] == " ": continue crates[stack].append(layer[location]) instructions = [] for instruction in lines[line_num + 1 :]: # Is there a better way to do this while still enforcing tuple length? breakdown = instruction.strip().split() amount: int = int(breakdown[1]) src: int = int(breakdown[3]) - 1 dst: int = int(breakdown[5]) - 1 instructions.append((amount, src, dst)) return (crates, instructions) def apply_instruction(crates: List[deque[str]], instruction: Tuple[int, int, int]): for _ in range(instruction[0]): crates[instruction[2]].append(crates[instruction[1]].pop()) def apply_fancy_instruction( crates: List[deque[str]], instruction: Tuple[int, int, int] ): hand = [] for _ in range(instruction[0]): hand.append(crates[instruction[1]].pop()) for _ in range(instruction[0]): crates[instruction[2]].append(hand.pop()) def main(filepath: str) -> Tuple[str, str]: lines = load_file.load_lines(filepath) crates, instructions = parse_input(lines) crates_2 = deepcopy(crates) for instruction in instructions: apply_instruction(crates, instruction) apply_fancy_instruction(crates_2, instruction) return ( "".join((crate[-1] for crate in crates)), "".join((crate[-1] for crate in crates_2)), )
-
Comment on Day 4: Camp Cleanup in ~comp
Gyrfalcon When I first read the problem description, I went to sets, just like I did yesterday and like it seems like many people did here. Then, I got worried that this was a trick, and that I was going to...When I first read the problem description, I went to sets, just like I did yesterday and like it seems like many people did here. Then, I got worried that this was a trick, and that I was going to create some kind of monstrosity with huge sets if I went that path, so I just went with keeping the high and low of each assignment and having to think about the conditionals for overlapping, which tripped me up for a little bit on part 2.
Parts 1 and 2
def create_assignments(pair: str) -> Tuple[Tuple[int, int], Tuple[int, int]]: first, second = pair.split(",") first_low = int(first.split("-")[0]) first_high = int(first.split("-")[1]) second_low = int(second.split("-")[0]) second_high = int(second.split("-")[1]) return ((first_low, first_high), (second_low, second_high)) def are_completely_overlapping( assignments: Tuple[Tuple[int, int], Tuple[int, int]] ) -> bool: return ( assignments[0][0] <= assignments[1][0] and assignments[0][1] >= assignments[1][1] ) or ( assignments[1][0] <= assignments[0][0] and assignments[1][1] >= assignments[0][1] ) def are_overlapping(assignments: Tuple[Tuple[int, int], Tuple[int, int]]) -> bool: return ( assignments[0][1] >= assignments[1][0] and assignments[0][0] <= assignments[1][1] ) def main(filepath: str) -> Tuple[int, int]: pairs = load_file.load_cleaned_lines(filepath) assignments = [create_assignments(pair) for pair in pairs] return ( sum((are_completely_overlapping(assignment) for assignment in assignments)), sum((are_overlapping(assignment) for assignment in assignments)), )
-
Comment on Day 3: Rucksack Reorganization in ~comp
Gyrfalcon Happy with how this turned out, though I think I learned that I need to find a more elegant way to interact with Python's Set, especially given how handy I find it in general. Parts 1 and 2 import...Happy with how this turned out, though I think I learned that I need to find a more elegant way to interact with Python's
Set
, especially given how handy I find it in general.Parts 1 and 2
import os from typing import Tuple from string import ascii_lowercase, ascii_uppercase from aoc2022.common import load_file current_dir = os.path.realpath(os.path.dirname(__file__)) INPUT_FILE = "/".join([current_dir, "input.txt"]) TEST_FILE_1 = "/".join([current_dir, "test1.txt"]) TEST_RESULTS_1 = (157, 70) priorities = { character: priority + 1 for priority, character in enumerate(ascii_lowercase) } priorities.update( {character: priority + 27 for priority, character in enumerate(ascii_uppercase)} ) def compartment_commonality(rucksack: str) -> str: compartment_1 = set(rucksack[: len(rucksack) // 2]) compartment_2 = set(rucksack[len(rucksack) // 2 :]) return compartment_1.intersection(compartment_2).pop() def generate_groups(rucksacks: list[str]) -> list[list[str]]: grouped = [] for idx in range(0, len(rucksacks), 3): grouped.append(rucksacks[idx : idx + 3]) return grouped def find_badge(rucksacks: list[str]) -> str: sets = [set(rucksack) for rucksack in rucksacks] return sets[0].intersection(*sets).pop() def main(filepath: str) -> Tuple[int, int]: rucksacks = load_file.load_cleaned_lines(filepath) common_items = map(compartment_commonality, rucksacks) groups = generate_groups(rucksacks) badges = map(find_badge, groups) return ( sum((priorities[item] for item in common_items)), sum((priorities[badge] for badge in badges)), ) if __name__ == "__main__": part1, part2 = main(INPUT_FILE) print(part1) print(part2)
-
Comment on Day 2: Rock Paper Scissors in ~comp
Gyrfalcon I am actually happier with this than I thought I would be. I did most of the thinking and worked out the values for all the combinations, and just let Python crank on the calculating. I am also...I am actually happier with this than I thought I would be. I did most of the thinking and worked out the values for all the combinations, and just let Python crank on the calculating. I am also really happy with how I decided to do my testing, although I think if I tried harder I could probably make something that dynamically builds up the tests as I add days. Either way, it comes in handy. This code is also a little nicer because I actually ran and listened to
mypy
andblack
before posting my code! I am also going to leave out most of my fixture code, but if anyone is interested, just ask.Parts 1 and 2
scoring = { "A X": 4, "A Y": 8, "A Z": 3, "B X": 1, "B Y": 5, "B Z": 9, "C X": 7, "C Y": 2, "C Z": 6, } decoded_scoring = { "A X": 3, "A Y": 4, "A Z": 8, "B X": 1, "B Y": 5, "B Z": 9, "C X": 2, "C Y": 6, "C Z": 7, } def score_game(game: str, decoded: bool = False) -> int: return decoded_scoring[game] if decoded else scoring[game] def main(filepath: str) -> Tuple[int, int]: games = load_file.load_cleaned_lines(filepath) return ( sum([score_game(game) for game in games]), sum([score_game(game, True) for game in games]), )
And my new file loader that works in the way it probably should have from the beginning:
def load_cleaned_lines(filename: str) -> list[str]: with open(filename, "r") as fp: lines = fp.readlines() return [line.strip() for line in lines]
-
Comment on Day 1: Calorie Counting in ~comp
Gyrfalcon I had hoped to try out Rust this year, but I haven't gotten around to actually learning much of it so I settled on Python, since my new work uses it a lot and it would be good to brush up. I am...I had hoped to try out Rust this year, but I haven't gotten around to actually learning much of it so I settled on Python, since my new work uses it a lot and it would be good to brush up. I am also going hard on organizing code, adding at least semi real tests for the provided test cases, etc. Anyway, solution:
Parts 1 and 2
import os from aoc2022.common import load_file current_dir = os.path.realpath(os.path.dirname(__file__)) INPUT_FILE = "/".join([current_dir, "input.txt"]) TEST_FILE_1 = "/".join([current_dir, "test1.txt"]) TEST_RESULTS_1 = (24000, 45000) def parse_elves(lines: list[str]) -> list[list[int]]: elves = [] elf: list[int] = [] for line in lines: if line == "\n": elves.append(elf) elf = [] else: elf.append(int(line)) elves.append(elf) return elves def count_calories(elves: list[list[int]]) -> list[int]: return [sum(elf) for elf in elves] def main(filepath: str) -> int: lines = load_file.load_lines(filepath) elves = parse_elves(lines) calorie_totals = count_calories(elves) calorie_totals.sort(reverse=True) return (calorie_totals[0], sum(calorie_totals[:3])) if __name__ == "__main__": part1, part2 = main(INPUT_FILE) print(part1) print(part2)
And the
common
file which will hopefully fill out a bit as time goes on:def load_lines(filename: str) -> list[str]: with open(filename, "r") as fp: return fp.readlines()
-
Comment on Timasomo 2022: Showcase Thread in ~creative
Gyrfalcon Still Unfinished Shield This is more of an update than a showcase since I intend to finish this project and make a separate post at that time. I forgot in my calculations of whether or not I would...- Exemplary
Still Unfinished Shield
This is more of an update than a showcase since I intend to finish this project and make a separate post at that time. I forgot in my calculations of whether or not I would finish that my in-laws were coming to town, and that the time would change so that I wouldn't have light to work outside after work, and then I went ahead and bought Victoria 3 to distract myself even more. However, I got the green half the way I want, and learned a lot about how best to use the acrylic on this kind of surface, which you can see here.
I normally link to Beehaw down here, but there wasn't anything posted on the showcase thread over there, despite some early activity. The community there is a bit small still, but if you like Tildes and are interested in trying out a federated community I would say it is a good one!
-
Comment on Timasomo 2022: Final Update Thread in ~creative
Gyrfalcon My apologies for falling off the face of the earth for last week's update. I started a new job that week, and ended up on travel for most of this week for work, so progress has not been what I had...My apologies for falling off the face of the earth for last week's update. I started a new job that week, and ended up on travel for most of this week for work, so progress has not been what I had hoped. Realistically, I don't think I am going to be able to finish everything before Monday, but I might be able to get something respectable before the actual showcase thread next Saturday. Anyway, what I did accomplish:
- Made cuts on the main body of the shield and the handle. The shields outer and inner curves are definitely not perfect, and I somehow managed to cut the handle too long? But I think it won't be too noticeable in the finished product, and a too long piece can always be cut down.
- I made one attempt at attaching the linen facing, but went about it all wrong. I tried to spread glue over the full surface and lay it down all in one go, which I had some misgivings about but thought would work. When I went to add more glue on top of the linen to complete my composite, it bubbled horribly.
- I made a second attempt at attaching the linen, this time gluing down one section at a time, pulling the fabric taught as I laid it down on the glue, using an old library card to push out bubbles, and waiting about 60 seconds before moving on. This worked quite well, and I was able to add more glue for the top surface without issue.
- I trimmed the excess linen. I started with scissors for this, but because of the glue in the fabric, a box cutter ended up being the more appropriate tool.
- I applied my primer to the whole surface of the shield to make sure my paint sticks nicely.
- I applied a coat of green to approximately half of the shield. I think this will need at least one more coat to get everything reasonably even.
Pictures of my progress so far here.
I was not terribly successful on this last year so I have two ideas, both aiming to scale back a bit:
This will be made a little more complicated by having a week of business travel as well as a family visit at the end of the month, but I am hoping to accomplish something fun without setting too high of expectations for myself.