#but hey. semantics. these things are important mods for players to have!
Explore tagged Tumblr posts
flarebean · 4 months ago
Text
why does the trade picker have to be buggy wuggy with the update. i just want to distribute 60/60 elemental status mods, covert lethality, and other spy stuff at a fair price.
anyway, uncheck 'hide equipped' in the bottom right if the trade picker can't find a mod you own. the extra duplicates will still be missing, but you should be able to see a singular copy.
1 note · View note
oliverpdaniel · 5 years ago
Text
Advent of Code 2020: A (very timely and not late at all) Reflection on Days 15-25
...Um. Oops?
Honestly, everything has been happening so much lately, I'm not super frustrated that it's been a clean month between finishing these puzzles and commenting on them. During these weeks, along with finally finishing my first-ever Advent of Code (as did my roommate! Well done, buddy.), I also wrapped up my second semester in quarantine, including a few brutal final projects and exams. After a nail-biting few weeks of awaiting grades, I finally had the confidence to withdraw for the second semester, and to begin hunting for work. (If you're reading this and I'm not hired yet, hire me!)
Anyway, the obvious downside to the sheer magnitude of the delay is that most of these puzzles aren't super fresh in my head, and thus my commentaries may not be as detailed as I would like. Hey - if I ever get such a massive executive-dysfunction-killing buzz as I did over the winter break to finally clean and redecorate my room, maybe I'll revisit these too.
Day 15: Now we're seeing some REAL slowness! The primary data structure for both parts here was the dictionary, mapping "seen" (spoken) numbers to the last turn on which they were spoken. That being said, I don't know what I was thinking in Part 1, with code like this:
Code ``` for k in seen.keys(): seen[k] += 1 ```
As soon as I saw the spicy thirty million in Part 2, I knew my naive solution wouldn't even touch it. [1] I had to do my least favourite thing - off-by-one debugging, but I ultimately came up with a relatively clever insight:
Spoilers Storing not just the last turn on which a number was spoken, but the last *two* numbers (if they exist). Doing this allows for a three-case scenario, for some current number `curr`: 1. `seen[curr]` is empty or doesn't exist. This is the base case of a new number; output 0, as stated in the problem. 2. `seen[curr]` has 1 value. It's only been seen once, so we can calculate the number of turns since it was last seen. 3. `seen[curr]` has 2 values. This number has been seen twice, so we can simply subtract the first- and second-most recent turn numbers to get the gap between them!
This problem took a bit of fiddling, but runs okay. Python really shows its ugly side here, as even a fairly efficient solution like this one, using efficient data structures, takes quite a while on Part 2.
Day 16: Boy oh boy. I spent far too long on this one, and perhaps if there are any to revisit for a future post, it's this one. My solution for this one features no less than:
regex;
closure functions;
constraint satisfaction;
functions that return tuples of variable length; and
walrus operators.
I consider this problem a 'sweat' for future years; I learned a lot about what makes constraint-satisfaction engines tick, and how it's important to assign constraints to the smallest possible element of a search space (here a column, rather than an entire permutation of columns). I think there's a much more concise and semantic way of outlining this problem, that lets the solver do much more of the work than I did.
Day 17: Not much to say here; it's a cellular automaton with extra for loops. I'll share two cute things that I'm proud of:
Spoilers 1. I experimented with various thresholds for the size of the 'infinite' space, making specifically sure not to to index checks, so that I could have the smallest possible subspace to check over. I ended up settling on a value of `20` units in each direction from: 2. the origin I specified, which is simply `LIMIT // 2 - H // 2` (where `H` is just the dimension of the input grid).
My roommate complained that it took him a long time to parse and understand the problem; I'll confess that I barely read it. I guess that's the advantage of experience, in that I saw "Conway" and "space" and knew immediately what needed to be done.
I didn't do anything special for Part 2; it's just my Part 1 code, copied and pasted, with an extra for loop here and a variable there. sum(sum(sum(sum())))s for everyone!
Day 18: I think that, out of all 49 unique problems in this year's Advent of Code, I'm most proud of my solution to this one. It's (relatively) fast; the code is pretty easy to read and works for both parts (and more! [2]); and I came up with a solution before knowing the name for what I had built. (Update: it's a shift-reduce parser. Hooray for stacks!) One especially cute thing, that incidentally ended up defining my approach to a lot of the later problems, was
Spoilers creating a lookup table between a certain input symbol, here math operators, and an internal function, here the builtin `int` math functors. This allowed for a dead-simple evaluator function, for when the top of the stack was ready to be converted from an expression to a workable number. Also, I had the bright idea to recursively evaluate bracketed expressions, in such a way that an expression like `(((1 + 2)))` would quickly reduce down to `1 + 2` before the rest of the parser got to it.
Day 19: Aaaaaaaaargh! Herein begin the Two Days of Terror - the two hardest problems. Lucky I had returned from my partner's by now, as I think they would have been quite upset with how much I was ignoring them to code. After solving Part 1 in the morning I finally finished Part 2 at around 7pm, having forgotten to otherwise eat or attack my household responsibilities, and only after my roommate sat down with me and pair-programmed for a while. This one stung the most, because... I'm a linguist, for crying out loud! No generative grammar problem, especially ones over a finite search space like this, should be causing me such grief.
Day 20: I am still emotionally recovering from this problem. My roommate somehow managed to get both parts to run instantly, using the most cursed CSP setup I've ever seen. I still need to study his code better to understand just how he did it. Also, his usage of scientific Python packages finally shows its rewards, as convolution over a matrix is a friggin' builtin function. Grr.
Day 21: I consider this day an apology for the previous Days of Terror. Some fun, but not terribly difficult, set-fu. My relative inexperience with set theory shows its stripes here; I'm sure there are much more semantically sound ways of accomplishing what I tried to do here (e.g., manually removing an allergen from each ingredient's list of hypotheses once it was confirmed to go with a certain ingredient).
Day 22: Spicy spicy numbers! It would have served me much better to read the instructions before starting, as then I would have known that
Spoilers in Part 2, players don't take their entire deck with them. Since, y'know, that would just cause an infinite race to the bottom.
Day 23: Even spicier numbers! If you're going to be cute like me and establish 9 as a constant, make sure that you don't use it in Part 2 when constructing the initial circle, or you'll wonder why 9,999,990 of the cups aren't attached to anything.
Day 24: I couldn't sleep, so I solved this problem at 3 in the morning. Not going to lie, a little disappointing for a penultimate problem, especially Part 2. Part 1 required at least a modicum of cleverness to develop a meaningful coordinate system, but then Part 2 just felt like a relative rehash of the Conway Cubes problem. 3 cellular automaton problems out of 25 is a little bit much, considering how formulaic they can be.
Day 25: As true evidence of how much I learned over this Advent of Code, I was able to finish Day 25 on the couch without even bothering my partner. Utilizing what I had learned about pow made defining the transform (i.e., repeated multiplication and mod) incredibly easy. Though, I did get a little bit lucky, due to a small oversight in problem setting...
Spoilers Rather than having to generate and test a whole bunch of different pairs of loop sizes for the card and the door, it turns out that if you `zip` together two streams of all such valid loop sizes for the card and door, respectively, the correct size for both (i.e, the solution) appears at the same time; for me, just the second such pair of sizes.
Day 25 Part 2, as always, was a delight and a pleasure. If you've never clicked that final button before, crack open a text editor and start solving challenges until you can. It's deeply satisfying.
I cannot sufficiently express my gratitude to the entire AoC team, setters, testers, and maintainers alike, for all that they do. A daily stream of bite-sized (or, sometimes, sea-monster-sized) challenges is just what I need to keep me going, and my skills sharp, over the dreary holiday season. Especially in a year like this, it was just what I needed to keep me moving, motivated, and thinking about code. I can't wait for next year's challenges and, hopefully, I'll convince the roomies to do it with me again.
Sorry about the little delay, and the relative lack of detail. But, the enemy of perfect is good enough. If you're reading these at some point in the distal future, I hope you've enjoyed watching my journey through these problems, and maybe learned a little bit about what it means to think like a programmer. Thanks for tuning in!
[1]: I tried it anyway; it obviously didn't work. And, once my roommate turned me onto tqdm, I was able to see just how long before the Heat Death of the Universe for it to run. It was about 3 days. Lol.
[2]: The way I constructed the code, it would be extremely easy to add in the remaining integer operations.
0 notes