xavdid's recent activity
-
Comment on Day 11: Plutonian Pebbles in ~comp.advent_of_code
-
Comment on Day 10: Hoof It in ~comp.advent_of_code
xavdid Python: Step-by-step explanation | full code Because today was simpler, we had the chance to focus on a clean DFS implementation. It also may take the cake for "least changes between parts 1 and...Python: Step-by-step explanation | full code
Because today was simpler, we had the chance to focus on a clean DFS implementation. It also may take the cake for "least changes between parts 1 and 2", which is always a nice break. Ultimately, I could put everything in a function and call it twice for each
0
position, summing the totals independently.This definitely feels like the calm before the storm!
-
Comment on Day 9: Disk Fragmenter in ~comp.advent_of_code
xavdid Python: Step-by-step explanation | full code Part 1 with a dict was quick, since I could keep pointers that walked up and down the keys until they crossed. Part 2 I switched to a small dataclass,...Python: Step-by-step explanation | full code
Part 1 with a dict was quick, since I could keep pointers that walked up and down the keys until they crossed.
Part 2 I switched to a small dataclass, which worked well. It's slower, (about 3.5s) but it's clean. I can still walk backwards down the list, but I have to search from the front every time for the first gap. For the checksum, I got to use
chain.from_iterable
to flatten a list of lists, which is always fun. -
Comment on What do you use for 2fa? in ~tech
xavdid I always see this talking point and have never agreed with it. As with everything in security, it's all a matter of tradeoffs. The main goal of 2FA is to put less weight on passwords, which tend...Including TOTP secrets in a password manager that syncs (or anything that syncs) is fundamentally breaking 2FA. It might be a reasonable tradeoff for you in your situation, but it defeats the point of 2FA.
I always see this talking point and have never agreed with it. As with everything in security, it's all a matter of tradeoffs. The main goal of 2FA is to put less weight on passwords, which tend to get reused and/or leaked. So to that end, it doesn't really matter where your secret is stored; the fact that it's enabled at all buys you a decent amount of security. If you know that my tildes password is
hunter2
, that doesn't get you into my account regardless of where my 2FA secret is stored.If your risk profile is more concerned with someone getting access to your vault, then sure, putting all your eggs in one basket isn't probably great. But if we assume your password vault is secure (which is probably true for anything that's not LastPass), then it's probably the safest place you can store a 2FA secret (as opposed to yet another app that has to get maintained and secured indefinitely).
If you've got security clearance and your password manager is under active attack from a state actor, then it might make sense to keep 2FA secrets offline and on your person. But for most people, enabling it at all goes a long way and it's important that there not be extra impediments towards storing it safely.
Here's more good reading on this topic: https://www.reddit.com/r/1Password/comments/1247mho/help_with_changing_from_1password_2fa_to_third/jdyker6/
-
Comment on Day 8: Resonant Collinearity in ~comp.advent_of_code
xavdid Python: Step-by-step explanation | full code This ended up being simpler than expected. For every pair of matching points we find their slope. Then we step that slope once (or until we hit the...Python: Step-by-step explanation | full code
This ended up being simpler than expected. For every pair of matching points we find their slope. Then we step that slope once (or until we hit the edge of the grid) for each point. Once again, having 2-tuples that are easy to add and subtract greatly simplifies these grid problems.
aside: I know that Python's
complex
type also makes this easy, but I find that a little harder to reason about, so I stick with my tuples & methods. -
Comment on What games have you been playing, and what's your opinion on them? in ~games
xavdid Playing Tales of Kenzera: ZAU, which is pretty fun. It's billed as a metroidvania, but it's really more of a 2D puzzle platformer. The environments are vibrant and the abilities are fun. Combat is...Playing Tales of Kenzera: ZAU, which is pretty fun. It's billed as a metroidvania, but it's really more of a 2D puzzle platformer. The environments are vibrant and the abilities are fun. Combat is a little clunky, but largely satisfying. There are some cool traversal abilities too, which I've been enjoying. A nice story as well.
I think this would have been a slam dunk on the PS2. Consequently, some of its designs feel a little dated. But I'm having a good time for what it is!
-
Comment on Day 7: Bridge Repair in ~comp.advent_of_code
xavdid Thank you for saying so! I'm glad you're enjoying them. Nope, I'm just a bad speller and was writing both late and in VSCode 😅 I'll get that fixed! TIL! I'll update that as well. Appreciate the...I always love reading these write-ups when they show up in my RSS reader. :)
Thank you for saying so! I'm glad you're enjoying them.
unless that was deliberate to be whimsical
Nope, I'm just a bad speller and was writing both late and in VSCode 😅 I'll get that fixed!
has the algorithm name wrong
TIL! I'll update that as well. Appreciate the feedback.
Those changes will all go live when the next post is published.
-
Comment on Day 7: Bridge Repair in ~comp.advent_of_code
xavdid Python: Step-by-step explanation | full code I stuck with my theme of "just do it literally", which largely keeps working. I solved part 1 recursively with a list of numbers and ops, adding the...Python: Step-by-step explanation | full code
I stuck with my theme of "just do it literally", which largely keeps working. I solved part 1 recursively with a list of numbers and
op
s, adding the result to the front of the list until I had only a single number left.I did the same thing for part 2 and got ~22s of runtime. Rather than refactor, I used
multiprocessing
to parallelize the whole thing, getting me down to ~4s for both parts. Still slower than I'd like, but within reasonable bounds for minimal effort. -
Comment on Day 6: Guard Gallivant in ~comp.advent_of_code
xavdid For part 2, you don't need to check every possible location. You only care about places the guard walked during a full go of part 1. That alone got me down from ~30 seconds to ~7.5 seconds in Python!For part 2, you don't need to check every possible location. You only care about places the guard walked during a full go of part 1. That alone got me down from ~30 seconds to ~7.5 seconds in Python!
-
Comment on Day 6: Guard Gallivant in ~comp.advent_of_code
xavdid Python: Step-by-step explanation | full code Part 1 I did naively (gotta get those in while I can 😅). For part 2, I went on a bit of a refactoring journey to adapt my part 1 code for loop...Python: Step-by-step explanation | full code
Part 1 I did naively (gotta get those in while I can 😅). For part 2, I went on a bit of a refactoring journey to adapt my part 1 code for loop detection (which meant tracking both location and direction) and then speeding it up by only checking the paths the guard actually walked.
Nothing too complicated, but it made for a nice writeup explaining the journey of refactoring safely and ensuring every intermediate step still passed part 1. Runs in
7.5 seconds on Python
3.12.7`, which I'm pleased enough about to not keep iterating on it. -
Comment on Day 5: Print Queue in ~comp.advent_of_code
xavdid Python: Step-by-step explanation | full code List comprehensions and all made short work of part 1 again. For part 2 I was ready to bust out a Kahn's implementation when I saw that, of all things,...Python: Step-by-step explanation | full code
List comprehensions and
all
made short work of part 1 again. For part 2 I was ready to bust out a Kahn's implementation when I saw that, of all things, Python'sgraphlib
contains aTopologicalSorter
class (and only that class)! Using as much of the stdlib is one of my goals, so it seemed silly not to use it if it's available.Resolving dependency was something I've had strong feelings about ever since I described my perfect task app, so it's fun to see a similar problem pop up in AoC.
-
Comment on Day 4: Ceres Search in ~comp.advent_of_code
xavdid Python: Step-by-step explanation | full code My grid parsing and neighbors function came in clutch today. For part 1, I could find every X, see if it has a neighboring M, and calculate the...Python: Step-by-step explanation | full code
My grid parsing and
neighbors
function came in clutch today. For part 1, I could find everyX
, see if it has a neighboringM
, and calculate the direction we stepped, and step 2 more times to check forA
andS
.For part 2, I tweaked
neighbors
to be able to do diagonals only. It was the same basic approach though: start withA
, find a diagonalM
, and then go the opposite way from theA
to check forS
. If there are exactly 2 of those, we're good to go!Mostly today's writeup covered how my grid system works. I end up using it a ton, so it's nice to have a cogent description of it somewhere.
I do wonder if I should make an actual
NamedTuple
class for myGridPoint
s instead of just a type alias. Is mostly compatible, but will also let me add and subtract via method overrides instead of needing dedicated aadd_points(a: GridPoint, b: GridPoint) -> GridPoint
function. Ah well; that sounds like work for the off season! -
Comment on Favorite "A Christmas Carol" adaptation? in ~movies
xavdid My favorite weird thing about this movie is at one point Gonzo turns straight to camera and says "and Tiny Tim, who did NOT die" (potato timestamped video). I always thought it was just the...It's very faithful to the Dickens
My favorite weird thing about this movie is at one point Gonzo turns straight to camera and says "and Tiny Tim, who did NOT die" (potato timestamped video). I always thought it was just the Muppets emphasizing that the kid pulled through. But it turns out that's straight from the text, including the emphasis!
-
Comment on Day 3: Mull It Over in ~comp.advent_of_code
xavdid Python Step-by-step explanation | full code I love regex! Using capture groups and re.findall made part 1 a 1-liner, which is nice. For today's writeup, I ended up with a (very) basic explanation...Python
Step-by-step explanation | full code
I love regex! Using capture groups and
re.findall
made part 1 a 1-liner, which is nice.For today's writeup, I ended up with a (very) basic explanation of regex for people totally unfamiliar with it. So if it's something you've always been interested in, this might be a good place to jump in!
-
Comment on Day 2: Red-Nosed Reports in ~comp.advent_of_code
xavdid Step-by-step explanation | full code My key today was realizing a strictly increasing list is the same as a strictly decreasing one, just reversed. Otherwise, pretty straightforward today thanks...Step-by-step explanation | full code
My key today was realizing a strictly increasing list is the same as a strictly decreasing one, just reversed. Otherwise, pretty straightforward today thanks to Python's
any
andall
functions! Nice way to practice writing pure helper functions foris_safe
andis_strictly_increasing
. -
Comment on Favorite quick play tabletop game recommendations in ~games.tabletop
xavdid Thirded! It explains in 1 minute and is super fun to play. It's been our go-to for warm up games or games at the end of the night.Someone else mentioned Scout so I'll second that!
Thirded! It explains in 1 minute and is super fun to play. It's been our go-to for warm up games or games at the end of the night.
-
Comment on Day 1: Historian Hysteria in ~comp.advent_of_code
xavdid You already edited, but for others, it's from my project template. Specifically, that tells the input parsing function to treat the input as a list of strings:...You already edited, but for others, it's from my project template.
Specifically, that tells the input parsing function to treat the input as a list of strings: xavdid/advent-of-code-python-template | base.py#L142-L152. Other options are one big string, an int, or a list of ints.
-
Comment on Day 1: Historian Hysteria in ~comp.advent_of_code
xavdid I always use Python so I can get some reps in writing clear, maintainable code (which is understandably uncommon for AoC). I also write a step-by-step solution to my approach so everyone can...I always use Python so I can get some reps in writing clear, maintainable code (which is understandably uncommon for AoC). I also write a step-by-step solution to my approach so everyone can understand each day. Takes a lot of time (especially in later days), but I enjoy it.
Anyway, my day 1 post is here (which also links to my full solution): https://advent-of-code.xavd.id/writeups/2024/day/1/
Parsing the "vertical" lists was tricky, so I did it simply to start:
l, r = [], [] for line in self.input: a, b = line.split() l.append(int(a)) r.append(int(b)) l.sort() r.sort()
But, after some playing with it, I got it down to a more svelte 2 liner:
pairs = [map(int, l.split()) for l in self.input] l, r = [sorted(col) for col in zip(*pairs)]
zip
returns tuples, butsorted
turns any iterable into a list, so we get some of the type transformation we'd have to do otherwise for free.A
collections.Counter
made part 2 simple and clean.Great to be back in it!
-
Comment on Day 1: Historian Hysteria in ~comp.advent_of_code
xavdid Thank you! I'm not sure how scheduled topics work- can we set up another one? It would be fun to have our own solution threads againThank you!
I'm not sure how scheduled topics work- can we set up another one? It would be fun to have our own solution threads again
-
Comment on What games have you been playing, and what's your opinion on them? in ~games
xavdid Yes! I'm excited about the sequel. There's a demo out, but I'll probably just wait for the full release. I'm not sure when you played it, but it got 3 free "DLC" chapters which sort of acted as a...Yes! I'm excited about the sequel. There's a demo out, but I'll probably just wait for the full release.
I'm not sure when you played it, but it got 3 free "DLC" chapters which sort of acted as a final conclusion / epilogue. They did a great job tying more of the story threads together into one big conclusion. But, you're right that it was too easy - I had tons of money and could keep 5 dice at all times with minimal effort. But I still ran out of time on some of the final things 😅
Python: Step-by-step explanation | full code
I did part 1 naively just for fun. Wrote a function that took a number and returned the next number(s).
For part 2 I was looking for a cycle (and found one; every
0
follows the same path). But I couldn't figure out how to turn that into an answer, since it didn't seem predictable enough. But then I realized order didn't matter and each instance of a number transformed the same as every other (e.g. every0
becomes a1
). So instead of a big list, I used a dict where the key was the stone and the value was the number of times that stone showed up. That'll scale basically forever, which I think was the point of the puzzle. Also, got to reuse my transformation function from part 1!