<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Hexes and Hacks]]></title><description><![CDATA[Magic-Infused Coding Adventures

Chronicling a technomancer's quest for knowledge.]]></description><link>https://hexesandhacks.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 20:09:58 GMT</lastBuildDate><atom:link href="https://hexesandhacks.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Dancing around YouTube's API]]></title><description><![CDATA[Did something that made me feel really cool.
I had this problem where I wanted to listen to entire YouTube channels on a shuffle; it's really helpful for passive practice listening to a foreign language. There often isn't always an easy built-in way ...]]></description><link>https://hexesandhacks.com/dancing-around-youtubes-api</link><guid isPermaLink="true">https://hexesandhacks.com/dancing-around-youtubes-api</guid><category><![CDATA[Learning Journey]]></category><category><![CDATA[general programming]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Alex]]></dc:creator><pubDate>Thu, 24 Aug 2023 18:34:21 GMT</pubDate><content:encoded><![CDATA[<p>Did something that made me feel really cool.</p>
<p>I had this problem where I wanted to listen to entire YouTube channels on a shuffle; it's really helpful for passive practice listening to a foreign language. There often isn't always an easy built-in way to do this, and a colleague of mine suggested I work on making a plugin that could extract the video URLs from a page when I proposed the problem I was trying to solve. I had a feeling that might not be necessary though, given what any user can interact with on YouTube that already exists.</p>
<p>Well, I found someone's existing JavaScript that made playlists from an entire channel's content; a semi-solution to the problem had been around for a while; basically restoring an old feature YouTube had hidden, but was still somewhat functional under the hood. Cool, but it had a problem.</p>
<p>I couldn't save it as my own playlist, and since it was kinda hacky, it didn't shuffle properly like a natural playlist. I knew I could copy my own playlists and add them to other playlists I've made, and from web developer experience I know all this really is is some kind of HTTP request. I thought there must be a way to replicate this request on another playlist page where that interface is usually unavailable.</p>
<p>Turns out there was. With some investigating by going through the interface for copying a playlist, I found the HTTP request in my network tab that mattered, and by copying it as a fetch request in my console, and swapping out the relevant playlist IDs which I could see were part of the playlist URLs, I could indeed use it to copy other playlists I normally couldn't into my own new playlist. When in the network tab I saw the POST request pass with a 200 success status response code and my playlist update with over 800 videos after a few test runs with smaller batches I was quite happy.</p>
<p>With that problem off my mind, now I can get back to studying.</p>
]]></content:encoded></item><item><title><![CDATA[What's actually hard about solving leetcode style questions]]></title><description><![CDATA[Today I was working through the following problem:
Given an array of unsorted numbers, find all unique triplets in it that add up to zero.
Example 1:
Output: [[-3, 1, 2], [-2, 0, 2], [-2, 1, 1], [-1, 0, 1]]
Explanation: There are four unique triplets...]]></description><link>https://hexesandhacks.com/whats-actually-hard-about-solving-leetcode-style-questions</link><guid isPermaLink="true">https://hexesandhacks.com/whats-actually-hard-about-solving-leetcode-style-questions</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[leetcode]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Alex]]></dc:creator><pubDate>Fri, 18 Aug 2023 04:38:30 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-today-i-was-working-through-the-following-problem">Today I was working through the following problem:</h2>
<p><em>Given an array of unsorted numbers, find all unique triplets in it that add up to zero.</em></p>
<p>Example 1:</p>
<pre><code class="lang-javascript">Output: [[<span class="hljs-number">-3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">-2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">-2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>], [<span class="hljs-number">-1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>]]
<span class="hljs-attr">Explanation</span>: There are four unique triplets whose sum is equal to zero. smallest sum.<span class="hljs-string">'</span>
</code></pre>
<p>Example 2:</p>
<pre><code class="lang-javascript">Output: [[<span class="hljs-number">-5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">-2</span>, <span class="hljs-number">-1</span>, <span class="hljs-number">3</span>]]
<span class="hljs-attr">Explanation</span>: There are two unique triplets whose sum is equal to zero.
</code></pre>
<p>The hard part of solving a problem like this these days isn't finding a solution.</p>
<p>Like most problems, when I initially approached this, I was making it more complicated than it was. After a while of trying to come up with a solution, and accounting for what the problem had to do, I knew somewhere two pointers would have to be involved, and that solutions like calculating every single possible combination, and storing them in a hashmap to then check against my current target while looping through the array would be far too time inefficient to work in a practical setting. When going down such routes, I arrived at problems that would have to involve something like a nested for loop inside a nested for loop. Hardly ideal.</p>
<p>As it usually goes with these kinds of problems, I've found it's usually just a result of lacking something in your toolset that has long since been figured out already, and it's not really something you can figure out on your own. That being the case, I just looked at a trusted solution to get the right idea once I realized I must be missing something. Unfamiliar questions and looking at fresh code is confusing enough, but I know just to trust my brain and come back to it later. Sure enough, the next day I understood the problem and solutions much better. That isn't the hard part, though.</p>
<p>Obviously, just copying the solution would be foolish if the point is to improve our skills and thinking for solving these kinds of problems, so this is why I took my time to passively come to understand the problem and solution after getting optimal mental input from a working solution. It felt much easier after a day or two of mulling over the problem after dedicating a bit of time to reading through it and thinking about it and other working solutions.</p>
<p>The really hard problem for us is being able to explain how these solutions work, and figuring out how to apply them. The techniques have been figured out, but it's up to us to be able to implement them in our own way after we learn them from ingenious solutions figured out over time in the history of computer science by the giants upon whose shoulders we stand.</p>
<p>Remembering the logic is simple enough once you have thought about it enough and let your brain do its thing, but the real struggle is when you start the implementation and actually try to explain how every edge case is accounted for in the moment. You have to think many steps ahead, and this is very difficult to explain as you're going.</p>
<p>I also find that I come up with edge cases I didn't imagine once I start coding a little bit, once I know how to lay out the logic that must work, and that's the hardest part that usually stops me. It's not always explicitly stated how that solution you thought you understood accounts for edge cases you only think of once you get into the thick of coding. In this case, it was this line of code:</p>
<pre><code class="lang-javascript">      <span class="hljs-keyword">while</span> (left &lt; right &amp;&amp; arr[left] === arr[left - <span class="hljs-number">1</span>]) {
        left++; <span class="hljs-comment">// skip same element to avoid duplicate triplets</span>
      }
      <span class="hljs-keyword">while</span> (left &lt; right &amp;&amp; arr[right] === arr[right + <span class="hljs-number">1</span>]) {
        right--; <span class="hljs-comment">// skip same element to avoid duplicate triplets</span>
      }
</code></pre>
<p>Full solution:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{
  searchTriplets(arr) {
    <span class="hljs-keyword">const</span> triplets = [];
    <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Write your code here</span>
    <span class="hljs-comment">// Sort the array</span>
    arr = arr.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b);
    <span class="hljs-comment">// Loop through the array, skipping index if it's the same as the previous one</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; arr.length; i++) {
      <span class="hljs-keyword">if</span> (arr[i] === arr[i - <span class="hljs-number">1</span>]) <span class="hljs-keyword">continue</span>;
    <span class="hljs-comment">// Use two pointers to to check every combo that adds up to the target that makes 0 with the current index</span>
      <span class="hljs-keyword">let</span> target = -arr[i];
      <span class="hljs-keyword">let</span> left = i + <span class="hljs-number">1</span>;
      <span class="hljs-keyword">let</span> right = arr.length - <span class="hljs-number">1</span>;
  <span class="hljs-keyword">while</span> (left &lt; right) {
    <span class="hljs-keyword">const</span> currentSum = arr[left] + arr[right];
    <span class="hljs-keyword">if</span> (currentSum === target) { <span class="hljs-comment">// found the triplet</span>
      triplets.push([-target, arr[left], arr[right]]);
      left++;
      right--;
      <span class="hljs-keyword">while</span> (left &lt; right &amp;&amp; arr[left] === arr[left - <span class="hljs-number">1</span>]) {
        left++; <span class="hljs-comment">// skip same element to avoid duplicate triplets</span>
      }
      <span class="hljs-keyword">while</span> (left &lt; right &amp;&amp; arr[right] === arr[right + <span class="hljs-number">1</span>]) {
        right--; <span class="hljs-comment">// skip same element to avoid duplicate triplets</span>
      }
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (target &gt; currentSum) {
      left++; <span class="hljs-comment">// we need a pair with a bigger sum</span>
    } <span class="hljs-keyword">else</span> {
      right--; <span class="hljs-comment">// we need a pair with a smaller sum</span>
    }
  }
    }
    <span class="hljs-keyword">return</span> triplets;
  }
}
</code></pre>
<p>This was a problem that I had foreseen while coding, and it actually stopped me in my tracks for a while. The only solution was to draw out an example array that had the situation I was imagining, which was something like this:</p>
<pre><code class="lang-javascript"> [<span class="hljs-number">-10</span>, <span class="hljs-number">-10</span>, <span class="hljs-number">0</span>, <span class="hljs-number">3</span>, <span class="hljs-number">10</span>, <span class="hljs-number">20</span> , <span class="hljs-number">30</span>]
</code></pre>
<p>My thinking was, and something that was not explicitly explained in the solutions I read, wouldn't the code potentially skip over a valid triplet, because it was assuming that, because it had already seen the value before it, it must be a duplicate? In this example, when at a value of i = 0, I thought the code would then skip the left pointer up to 0, then move the right pointer down after not seeing a solution either way, and the left pointer would never go back down because it would always be equal to the value before it.</p>
<p>This point, once I walked through the problem, made me realize the brilliance of the order of the checks in the code. This situation was accounted for because before checking for duplicate entries, the while loop begins with checking the sum right away. It's something I thought of ahead of time, but something that was quite difficult to see until walking it through.</p>
<p>Personally, I think explaining this and solving these small problems within the problem is harder than understanding the core logic behind the solutions in the first place, and it's essential for demonstrating true skill. When you think of an edge case and you aren't sure how it's been accounted for when the code gets so lengthy, it's really hard to see without just walking through the problems.</p>
<p>What did I realize from all of this? The importance of test cases. This made me realize that I should probably open starting my problems with edge case test cases planned ahead of time so I can code and just check if my solution passes them. If the core logic is not barking up the wrong tree so to speak, it's probably just a small edit that will fix any points of failure. That gets me out of being stuck while I'm coding, because I have a way to test set aside ahead of time. The really hard part is realizing this and realizing those edge cases early, and not freezing when one hits you mid-code. That's what you really want to prevent, as it can be a really crushing feeling that inhibits you when you should just keep going.</p>
<p>I always knew writing test cases was a good practice, but this kind of thing has actually demonstrated to me why, and I only learned it by attempting problems myself.</p>
]]></content:encoded></item><item><title><![CDATA[Staying in shape]]></title><description><![CDATA[As echoing a previous statement I made in another post, and that I've taken to heart, if it was worth learning, it's worth reviewing.
To emphasize this point, when I'm practicing code, I don't necessarily just submit what I'm doing and forget about i...]]></description><link>https://hexesandhacks.com/staying-in-shape</link><guid isPermaLink="true">https://hexesandhacks.com/staying-in-shape</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[learning]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[coding journey]]></category><dc:creator><![CDATA[Alex]]></dc:creator><pubDate>Thu, 10 Aug 2023 02:04:43 GMT</pubDate><content:encoded><![CDATA[<p>As echoing a previous statement I made in another post, and that I've taken to heart, if it was worth learning, it's worth reviewing.</p>
<p>To emphasize this point, when I'm practicing code, I don't necessarily just submit what I'm doing and forget about it once I find a working solution. Instead, I'll elect to take note of the solution and tuck it away, after making sure I thoroughly understood how and why it works, and what's good or bad about it. I'll then choose to forget about it and try and re-code it the next day without referencing what I found out the day before unless I really get stuck.</p>
<details>
  <summary><em>You will worry, and that's ok</em></summary>
You're going to feel worried you won't remember anything, and that you won't be able to solve or understand the problem again. That's fine. That's supposed to happen, and that ensures you're actually making progress towards truly learning the concept. Not just in being able to reiterate an explanation of it, but how to feel and utilize it. You will also be surprised by how much you actually do remember despite not putting any effort into it. Trust your brain. Remember how it was when you were a very small child and just did stuff and didn't even think about having to remember what you learned. You just did stuff, and it worked. The actual truth is that if you don't do it, you will definitely forget it. It's the same now as when you were a kid, it's just that constant hammering of bad habits from things like the pressure of the school system to memorize for upcoming exams have beaten that instinct for true learning out of you and even made you averse to it. Well, that's what I experienced anyway. I felt like I had to unlearn the wrong way to learn, and it was because of such systems. Maybe I'll do a post on that, too, sometime... The point to take away from this is to trust your brain. It does a lot for you in the background. I'm very grateful I studied a foreign language seriously over the past year because if you don't learn this, and don't learn to accept ambiguity and that it takes time and reviewing to actually be able to effectively work with something you've learned, and that you can't force the process and must let it happen passively, you'll fail. That reality hits you very fast if you try to learn a foreign language that's very distant from your native language. 
</details>

<p>How many times have I learned something, only to promptly forget it because I never really reviewed it? Too many times, honestly. This is instrumental in preventing that anxiety-inducing phenomenon and raising my confidence in problem-solving in general. Depending on how quickly the topic can be covered, or if I have good cheatsheets or otherwise notes made, too, I'll even use an SRS (spaced repetition system) app like Anki and add it to my reviews. Either way, I'm making sure I remind myself of it, at least somewhat regularly and efficiently. </p>
<p>I'm currently doing this with a course on advanced JavaScript and just today was really drilling in how things like scope, hoisting, arguments, and environments <em>actually</em> work in JavaScript under the hood. </p>
<p>Because of what I was reviewing today, I recalled fixing some of the first code I ever wrote, after realizing I hadn't declared my variables inside of a for loop. At the time, I knew it was bad conventions, but I didn't know why it still worked. What I was reviewing reinforced my knowledge of why it still worked, and the real reason as to why it's not a good practice. It was because of how, unless you're writing JavaScript code under 'use strict' conditions, there's a concept known as "leaking of global variables" where if you initialize a variable without actually declaring it within a function, JavaScript will declare it for you in the global scope. Nowadays I know this clearly isn't something we should be doing if we can help it, as it can cause memory leaks when those variables are not needed, or perhaps it can interfere with code trying to use the same variable names elsewhere.</p>
<p>These are all concepts I've understood to varying levels over the past few years, maybe I still understand now, but did I ever really make sure my knowledge of them was tightly secured? Not really, which is why having a solid review system is important. In reviewing them and in going into practice after doing so, I'll find that I can think about things a lot quicker and envision things that I wouldn't have otherwise. It just makes things easier and the confidence it builds goes a long way in extending what you're able to achieve. </p>
<p>What you'll find naturally coming from your mind will seem magical when you've fed it well.</p>
]]></content:encoded></item><item><title><![CDATA[Revisiting old problems]]></title><description><![CDATA[In my experience, even in the most seemingly trivial of problems, when you stop to explain them and put them into words anyone can understand, if you are creative enough and aware enough of what you're doing, your brain will naturally come across all...]]></description><link>https://hexesandhacks.com/revisiting-old-problems</link><guid isPermaLink="true">https://hexesandhacks.com/revisiting-old-problems</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[data structure and algorithms ]]></category><category><![CDATA[leetcode]]></category><category><![CDATA[interview questions]]></category><dc:creator><![CDATA[Alex]]></dc:creator><pubDate>Thu, 03 Aug 2023 02:11:30 GMT</pubDate><content:encoded><![CDATA[<p>In my experience, even in the most seemingly trivial of problems, when you stop to explain them and put them into words anyone can understand, if you are creative enough and aware enough of what you're doing, your brain will naturally come across all sorts of things of which can be talked about, unexpectedly, at length.</p>
<p>Just yesterday, I was working on a simple interview-style question to stay in shape with what I've been practicing over the past few months, feeling I should step up my knowledge of computer science and data structures and algorithms to make up for gaps in my skills. Anyone familiar with these kinds of questions, or perhaps with something like leetcode, has probably seen the "two sum" problem.</p>
<p>In the past, I definitely would have only imagined what I now know of as a brute-force or naive solution, with awful time complexity (maybe I'll write a post on that concept later) written it out, solved the problem, and walked away feeling like I didn't really actually learn anything, and wonder why I would even be doing these types of isolated and contrived problems.</p>
<p>Since then, I've gained a deeper understanding of the patterns behind these types of problems, and my brain has become at least somewhat familiar with recognizing them and being aware of when a solution can be optimized and when those patterns and coinciding coding techniques can be employed.</p>
<p>The problem was simple, and I had solved it three times before with three different solutions, and at one point thought through the pros and cons of each, however, knowing what I know now about learning, I knew that if something was worth learning, it would be worth reviewing. I swallowed my pride and the childish feeling of "I already know how to do this, it's a waste of time" and sat down to put my money where my mouth was, so to speak.</p>
<p>In doing so, I found myself naturally making connections I didn't find myself making when I learned how to solve this problem initially. I was challenging myself to, even if somewhat messily due to the nature of stream-of-consciousness thinking, explain my thought process in the moment and talk about the problems I could foresee. I was saying things like, "I chose to initialize these pointers here because, while it could work from other points, this is easier to think about and set conditions for", "Oh, I'm noticing my solution wouldn't work because of x, y, and z and I have to fix the way I wrote that", "While this works, at scale this could happen and it could be extremely costly..." and only briefly covered what the brute-force solution would be in general.</p>
<p>Throughout the whole process I demonstrated what my brain is doing in the background and became more conscious of it. I've found that over time, this is what really improves your skills. It's important to trust your brain. Give your brain good input. If you're doing that, you don't have to worry. Eventually it will all make sense, even if in the moment it doesn't feel like it.</p>
<p>Also, in the words of a buddy of mine who is also very much my senior in where we are in the stages of our careers, when we were discussing these kinds of problems and realizing that changing the data structure completely changed how we saw the problem: "Was it a hash map? It's always a hash map."</p>
]]></content:encoded></item><item><title><![CDATA[It's time]]></title><description><![CDATA[It might sound cliché to explain that the best way to learn something is to be able to explain it.
Well, it's true though.
That being the case, I've created this blog to chronicle whatever I'm learning, big or small, as well as philosophical thoughts...]]></description><link>https://hexesandhacks.com/its-time</link><guid isPermaLink="true">https://hexesandhacks.com/its-time</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Alex]]></dc:creator><pubDate>Thu, 03 Aug 2023 02:00:45 GMT</pubDate><content:encoded><![CDATA[<p>It might sound cliché to explain that the best way to learn something is to be able to explain it.</p>
<p>Well, it's true though.</p>
<p>That being the case, I've created this blog to chronicle whatever I'm learning, big or small, as well as philosophical thoughts on the very concept of learning itself. It's as important to life as it is to being a competent developer, after all.</p>
]]></content:encoded></item></channel></rss>