<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator uri="http://jekyllrb.com" version="4.3.4">Jekyll</generator>
  
  
  <link href="https://gareth.fyi/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://gareth.fyi/" rel="alternate" type="text/html" />
  <updated>2024-12-05T15:34:00+00:00</updated>
  <id>https://gareth.fyi/</id>

  
    <title type="html">Gareth, FYI</title>
  

  
    <subtitle>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</subtitle>
  

  

  
  
    <entry>
      
      <title type="html">Advent of Code: Tracking reports</title>
      
      
      <link href="https://gareth.fyi/2024/12/05/advent-of-code-2024-day-2/" rel="alternate" type="text/html" title="Advent of Code: Tracking reports" />
      
      <published>2024-12-05T00:00:00+00:00</published>
      <updated>2024-12-05T00:00:00+00:00</updated>
      <id>https://gareth.fyi/2024/12/05/advent-of-code-2024-day-2</id>
      <content type="html" xml:base="https://gareth.fyi/2024/12/05/advent-of-code-2024-day-2/">&lt;p&gt;There’s not a huge amount to say about Advent of Code day 2. The puzzle is straightforward, but the way I approached the difference between the parts is a little more interesting.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;day-2&quot;&gt;Day 2&lt;/h2&gt;

&lt;p&gt;As ever, I’m not going to repeat the whole problem here, check the &lt;a href=&quot;https://adventofcode.com/2024/day/2&quot;&gt;Advent of Code problem page&lt;/a&gt; and my &lt;a href=&quot;https://github.com/gareth/advent-of-code-2024/tree/main/day-02&quot;&gt;overall solution&lt;/a&gt; for full details.&lt;/p&gt;

&lt;p&gt;For the first part, I wrapped up the logic to calculate whether a “Report” was “safe” or not by detecting the various ways it could fail and checking if there was no error:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Report&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@levels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;levels&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;error&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# […]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;safe?&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second part of the problem iterates on the first, by changing the definition of “safe” to say that a report is safe if removing any one of its levels turns it into a safe report using the previous definition.&lt;/p&gt;

&lt;p&gt;If I was only interested in finding the answers to each problem, I would just edit the original source code. I guarantee the people solving these problems &lt;a href=&quot;https://adventofcode.com/2024/leaderboard/day/2&quot;&gt;within 2 minutes&lt;/a&gt; of them being released aren’t hanging around restructuring their code. But that’s not how I like to approach Advent of Code.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Both parts of the problem should stay executable - the second part shouldn’t break the first&lt;/li&gt;
  &lt;li&gt;The code for the second part should (if possible) highlight the difference between the first part and the second.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a useful approach to practice, because in a real-world system you often don’t have the luxury of being able to break code - other classes might depend on the existing functionality and shouldn’t change.&lt;/p&gt;

&lt;p&gt;So I treated day 2 like a simple refactoring: Our new report is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;safe?&lt;/code&gt; if it’s safe by the previous definition &lt;em&gt;or&lt;/em&gt; if we can make another report by removing one level.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FixableReport&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Report&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;safe?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixable?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fixable?&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;times&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;any?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;new_levels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;safe?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This isn’t anything particularly complicated, but it demonstrates how putting a minimal structure in place early can make changes easier in the future.&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="ruby" />
      
        <category term="advent-of-code" />
      

      

      
        <summary type="html">There’s not a huge amount to say about Advent of Code day 2. The puzzle is straightforward, but the way I approached the difference between the parts is a little more interesting.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Advent of Code: Getting started</title>
      
      
      <link href="https://gareth.fyi/2024/12/04/advent-of-code-2024-day-1/" rel="alternate" type="text/html" title="Advent of Code: Getting started" />
      
      <published>2024-12-04T00:00:00+00:00</published>
      <updated>2024-12-04T00:00:00+00:00</updated>
      <id>https://gareth.fyi/2024/12/04/advent-of-code-2024-day-1</id>
      <content type="html" xml:base="https://gareth.fyi/2024/12/04/advent-of-code-2024-day-1/">&lt;p&gt;It’s time for &lt;a href=&quot;https://adventofcode.com/2024&quot;&gt;Advent of Code&lt;/a&gt; again! I’m starting a couple of days late because my laptop got stolen, but the first few days should be easy enough to catch up on.&lt;/p&gt;

&lt;p&gt;My first solves are going to be in Ruby, but I hope I’ll have time to come back and try again in some other languages too afterwards.&lt;/p&gt;

&lt;p&gt;I’ll upload my progress to &lt;a href=&quot;https://github.com/gareth/advent-of-code-2024&quot;&gt;my AoC Github repository&lt;/a&gt;, but let’s talk about any interesting highlights!&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;solving-an-advent-of-code-problem&quot;&gt;Solving an Advent of Code problem&lt;/h2&gt;

&lt;p&gt;Every day in December Advent of Code publishes a new puzzle. Each puzzle comes in two parts: the first part introduces a concept with a little story and a problem to solve, and then the second part adds some kind of complication that requires the problem to be solved a different way - with some alterate or additional processing.&lt;/p&gt;

&lt;p&gt;That’s interesting, because the puzzles feel like they’re deliberately designed to say to you “You thought you understand the requirements? We’ll now we’re changing them!” - the kind of situation that comes up &lt;em&gt;all the time&lt;/em&gt; in software engineering.&lt;/p&gt;

&lt;p&gt;I want to keep my solutions for the first and second parts of each puzzle separate, so although I’m going to copy my “part 1” code into a different “part 2” file as a starting point, I’m sure it will be useful to extract code and share it between those two files at some point.&lt;/p&gt;

&lt;h2 id=&quot;day-1&quot;&gt;Day 1&lt;/h2&gt;

&lt;p&gt;(I’m not repeating the entire puzzle here, &lt;a href=&quot;https://adventofcode.com/2024/day/1&quot;&gt;catch up for yourself&lt;/a&gt; on the AoC site)&lt;/p&gt;

&lt;p&gt;So it looks like the 2024 event is following the same formula as normal:&lt;/p&gt;

&lt;p&gt;We’re given the first part of the problem and some “sample” input, and we’re told the correct solution for the sample input to verify that we understand what’s going on. Then we’re given a much larger input and told to give the corresponding correct answer. Simple!&lt;/p&gt;

&lt;h3 id=&quot;structuring-the-repository&quot;&gt;Structuring the repository&lt;/h3&gt;

&lt;p&gt;I’m setting up some basic structure to make this easy to run. Every puzzle is generally self-contained, so it gets its own directory, and then each part of the puzzle gets its own runnable Ruby file&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
└── day-01
    ├── a.rb
    ├── b.rb
    ├── input
    └── input.sample
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that in place, I can run either part of the puzzle with either form of input - that lets me check the sample solution with the same code I’m calculating the final solution:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ruby day-01/a.rb day-01/input
[…]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;handling-file-input&quot;&gt;Handling file input&lt;/h3&gt;

&lt;p&gt;I used to think it was complicated to handle input files passed to a Ruby script like this. I always got tied up in manipulating the &lt;a href=&quot;https://ruby-doc.org/3.3.6/Object.html#ARGV&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ARGV&lt;/code&gt; array&lt;/a&gt; using an option parser library like Ruby’s standard &lt;a href=&quot;https://ruby-doc.org/3.3.6/optparse/tutorial_rdoc.html&quot;&gt;OptionParser library&lt;/a&gt;, but actually it’s much simpler to handle than that.&lt;/p&gt;

&lt;p&gt;The Ruby &lt;a href=&quot;https://ruby-doc.org/3.3.6/ARGF.html&quot;&gt;ARGF class&lt;/a&gt; is designed exactly for this purpose - it behaves like an input stream containing the contents of every file passed to the script. Instead of manually calling something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File.open(argument).read&lt;/code&gt; for every file you’re passed, a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ARGF.read&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Similarly, the top-level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kernel#gets&lt;/code&gt; method will automatically return lines from all of the passed files in order.&lt;/p&gt;

&lt;p&gt;And as a bonus, both of these methods automatically fall back to reading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STDIN&lt;/code&gt; if a) there are no files passed to the script, or b) the filename &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt; is passed. These are basic CLI conventions and it’s apparently really easy to make a ruby script conform to them!&lt;/p&gt;

&lt;p&gt;If your program needs to support flags and arguments &lt;em&gt;as well as&lt;/em&gt; input files then you’ll need to be a little more clever about it, but for AoC our handling is trivial.&lt;/p&gt;

&lt;h3 id=&quot;finally-solving-the-puzzle&quot;&gt;(Finally) solving the puzzle&lt;/h3&gt;

&lt;h4 id=&quot;part-1&quot;&gt;Part 1&lt;/h4&gt;

&lt;p&gt;Let’s see how that file handling works by processing the puzzle’s input, which is two lists presented side by side:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;3   4
4   3
2   5
1   3
3   9
3   3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As mentioned, we can read each input line whether that’s from a file or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STDIN&lt;/code&gt; by repeatedly calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gets&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\s+/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_i&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since each Advent of Code puzzle uses fixed input, we can skip some of the validation that we’d want to put in for anything handling dynamic user input - we know every line will have two integer values. Maybe later puzzles will make that trickier?&lt;/p&gt;

&lt;p&gt;Once we have the lists extracted, we can sort each of them and compare the differences&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array#zip&lt;/code&gt; is the perfect way to pair up corresponding values from two arrays, and the block form of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array#sum&lt;/code&gt; makes it easy to add up the corresponding differences:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;abs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;My original solution used the much less clear &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array#inject&lt;/code&gt; method to build up the total using an aggregator/memo field, but I think everyone will agree that the above solution is so much clearer.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;abs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 🤮&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;part-2&quot;&gt;Part 2&lt;/h4&gt;

&lt;p&gt;For part 2, we’re not calculating the difference of each pair of numbers any more, we have to multiply each entry in the left hand list by the number of times it appears on the right hand side.&lt;/p&gt;

&lt;p&gt;We can count the number of times each number appears in the right hand list by taking advantage of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object#itself&lt;/code&gt; which just returns the object you call it on. That might sound pretty useless, but when you use it in conjunction with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enumerable#group_by&lt;/code&gt; then you end up with the object itself as the &lt;strong&gt;key&lt;/strong&gt;, and an array of all of the matches as the &lt;strong&gt;values&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;itself&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:itself&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
     &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
     &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
     &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The number we actually need to multiply is the &lt;em&gt;lengths&lt;/em&gt; of these arrays, so we can chain on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hash#transform_values&lt;/code&gt; call to replace each array with its size:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;multipliers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;group_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:itself&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transform_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;multipliers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s it! Our answers match and we win our first two stars for the year!&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="ruby" />
      
        <category term="advent-of-code" />
      

      

      
        <summary type="html">It’s time for Advent of Code again! I’m starting a couple of days late because my laptop got stolen, but the first few days should be easy enough to catch up on. My first solves are going to be in Ruby, but I hope I’ll have time to come back and try again in some other languages too afterwards. I’ll upload my progress to my AoC Github repository, but let’s talk about any interesting highlights!</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Identifying numbers</title>
      
      
      <link href="https://gareth.fyi/2024/11/16/identifying-numbers/" rel="alternate" type="text/html" title="Identifying numbers" />
      
      <published>2024-11-16T15:59:00+00:00</published>
      <updated>2024-11-16T15:59:00+00:00</updated>
      <id>https://gareth.fyi/2024/11/16/identifying-numbers</id>
      <content type="html" xml:base="https://gareth.fyi/2024/11/16/identifying-numbers/">&lt;p&gt;Fun learning about CSS today.&lt;/p&gt;

&lt;p&gt;Since HTML5, element IDs can start with numbers. But in the CSS selectors spec, and therefore in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;document.querySelector&lt;/code&gt;, identifiers &lt;em&gt;can’t&lt;/em&gt;. So how do you target an element with a numeric ID?&lt;/p&gt;

&lt;!--more--&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;123&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#123&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;red&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* No */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;CSS has a single method of escaping characters for identifiers, and it’s not one of the common ones: you can replace a character with a \ followed by the unicode codepoint for that character in hexadecimal.&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;#\123&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;red&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* No */&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&quot;123&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;red&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* No */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The Unicode codepoints for the digit characters run from 0x30 to 0x39, which means the escape sequence for a leading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\31&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But if you try escaping this way, you’ll find you still aren’t all of the way there yet.&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;#\3123&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;red&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* No */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is because CSS thinks you’re escaping the codepoint 3123 here (“ㄣ”). Instead, you have to either a) pad the Unicode codepoint to 6 hexadecimal characters, or b) add a space after the escape sequence to finish the escape:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;#\00003123&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;green&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* YES */&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#\31&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;green&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* YES */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s right, if you want to target id=”123” in CSS (or in Javascript’s querySelector) you end up with this ABOMINATION(!) At that point, if you need this (because you’re generating IDs) you should just add a prefix.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;123&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Hello, world!&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#\31&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;green&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Javascript’s CSSOM library (in browsers by default) has a CSS.escape method which deals with this:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;CSS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;escape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// =&amp;gt;  &quot;\31 23&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But actually trying to use this in practice makes your Javascript feel as clunky as your CSS is.&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="css" />
      
        <category term="html5" />
      
        <category term="wat" />
      

      

      
        <summary type="html">Fun learning about CSS today. Since HTML5, element IDs can start with numbers. But in the CSS selectors spec, and therefore in document.querySelector, identifiers can’t. So how do you target an element with a numeric ID?</summary>
      

      
      
    </entry>
  
  
</feed>
