<?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[Cristiana's Dev Blog]]></title><description><![CDATA[Cristiana's Dev Blog]]></description><link>https://blog.cristiana.tech</link><generator>RSS for Node</generator><lastBuildDate>Tue, 19 May 2026 06:01:23 GMT</lastBuildDate><atom:link href="https://blog.cristiana.tech/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Advent of Code 2021: Day 14]]></title><description><![CDATA[This blog post is fourteenth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 14. This challenge was about optimizing an algorithm that generates exponentially larger and larger strings. I found ...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-14</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-14</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Tue, 14 Dec 2021 21:36:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639513648576/vq2KQVZGw.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is fourteenth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/14">Day 14</a>. This challenge was about optimizing an algorithm that generates exponentially larger and larger strings. I found it tricky and had to try multiple solutions until I reached the optimized solution described in this blog post.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-optimally-solving-part-one-and-two">Optimally Solving Part One and Two</h2>
<p>Given a template of polymers represented through letters and a set of rules, we must insert a new polymer between each pair of the initial template according to the rules. This insertion represents a single first step that produces the template for the next step. Part one requires running the insertion algorithm ten times, whereas part two is 40 times. Then, we must determine the least and most common polymer and subtract their occurrence number. </p>
<p>My initial solution was manipulating arrays of characters to insert new elements according to the set of given rules. However, this solution only worked for part one and was not optimized for exponentially growing arrays (sized 2^40) which eventually exceeded the limits (2^32). After attempting a recursive algorithm on each initial pair, I got a similar result.</p>
<p>The strategy that solved this challenge was to store pairs in an occurrence hash map. Each insertion step would determine the occurrence of new pairs based on the previous occurrence map. Finally, we can derive the polymer occurrence from the pair occurrence. </p>
<p>We can break down the solution as follows:</p>
<ul>
<li>read polymer template and insertion rules</li>
<li>create a pair occurrence map for the template</li>
<li>update pair occurrence map 10/40 times</li>
<li>find polymer occurrence map</li>
<li>subtract the least from the most common polymer</li>
</ul>
<h3 id="heading-read-polymer-template-and-insertion-rules">Read polymer template and insertion rules</h3>
<p>The template and pair insertion rules are separated by an empty line, thus we can the <code>split</code> function with the <code>\n\n</code> separator to get these two sections from the input.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [template, pairInsertionRulesData] = data.split(<span class="hljs-string">'\n\n'</span>)
</code></pre>
<p>We process each line from the input and add the corresponding rule to the <code>pairInsertionRules</code> hash map. We use the pair as key and polymer to be inserted as value.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pairInsertionRules = {}
pairInsertionRulesData.split(<span class="hljs-string">'\n'</span>).forEach(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [pair, result] = line.split(<span class="hljs-string">' -&gt; '</span>)
  pairInsertionRules[pair] = result
})
}
</code></pre>
<h3 id="heading-create-a-pair-occurrence-map-for-the-template">Create a pair occurrence map for the template</h3>
<p>The initial template from the example is <code>NNCB</code> and has the following pair occurrence hash map:</p>
<pre><code class="lang-js">{
  <span class="hljs-string">'NN'</span>: <span class="hljs-number">1</span>,
  <span class="hljs-string">'NC'</span>: <span class="hljs-number">1</span>,
  <span class="hljs-string">'CB'</span>: <span class="hljs-number">1</span>
}
</code></pre>
<p>We can create the pair occurrence map using the following algorithm:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getPairOccurenceMap = <span class="hljs-function">(<span class="hljs-params">template</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> pairs = {}
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; template.length - <span class="hljs-number">1</span>; ++i) {
    addToOccurenceMap(pairs, <span class="hljs-string">`<span class="hljs-subst">${template.charAt(i)}</span><span class="hljs-subst">${template.charAt(i + <span class="hljs-number">1</span>)}</span>`</span>)
  }

  <span class="hljs-keyword">return</span> pairs
}
</code></pre>
<p>I extracted the logic for adding a key / value to an occurrence map into <code>addToOccurenceMap</code> function. This is useful in some of the next steps.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> addToOccurenceMap = <span class="hljs-function">(<span class="hljs-params">occurenceMap, key, value = <span class="hljs-number">1</span></span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (occurenceMap[key]) {
    occurenceMap[key] += value
  } <span class="hljs-keyword">else</span> {
    occurenceMap[key] = value
  }
}
</code></pre>
<h3 id="heading-update-pair-occurrence-map-1040-times">Update pair occurrence map 10/40 times</h3>
<p>As mentioned earlier in this article, the strategy is to update the pair occurrence map rather than build a very large array or string exceeding the maximum limits. Thus, for part one we update 10 times and for part two 40 times.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10</span>; ++i) {
  pairOccurenceMap = updatePairOccurenceMap(pairOccurenceMap,  pairInsertionRules)
}
</code></pre>
<p>To build the new pair occurrence map, we iterate through each pair using the <code>Object.keys</code> function. Using the pair as an index, we can determine the pair's occurrences from <code>pairOccurenceMap</code> and the new polymer to insert from the <code>pairInsertionRules</code>. </p>
<p>If a rule exists for the pair, then the new pair occurrence map will contain two new pairs rather than the original pair. For example, if the rule <code>NC -&gt; B</code> for the pair <code>NC</code> exists, the new pair occurrence map will have pairs <code>NB</code> and <code>CB</code> instead of <code>NC</code>. Otherwise, if a rule does not exist, we add the original pair to the new occurrence map. </p>
<p>To build the new pairs we can use the string template literals <code>${pair.charAt(0)}${polymer}</code> for the left side pair and <code>${polymer}${pair.charAt(1)}</code> for the right side pair.</p>
<p>We add the value representing the occurrences of the original pair to each new pair.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> updatePairOccurenceMap = <span class="hljs-function">(<span class="hljs-params">pairOccurenceMap, pairInsertionRules</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> newPairOccurenceMap = {}

  <span class="hljs-built_in">Object</span>.keys(pairOccurenceMap).forEach(<span class="hljs-function">(<span class="hljs-params">pair</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> occurences = pairOccurenceMap[pair]
    <span class="hljs-keyword">const</span> polymer = pairInsertionRules[pair]
    <span class="hljs-keyword">if</span> (polymer) {
      addToOccurenceMap(newPairOccurenceMap, <span class="hljs-string">`<span class="hljs-subst">${pair.charAt(<span class="hljs-number">0</span>)}</span><span class="hljs-subst">${polymer}</span>`</span>, occurences)
      addToOccurenceMap(newPairOccurenceMap, <span class="hljs-string">`<span class="hljs-subst">${polymer}</span><span class="hljs-subst">${pair.charAt(<span class="hljs-number">1</span>)}</span>`</span>, occurences)
    } <span class="hljs-keyword">else</span> {
      addToOccurenceMap(newPairOccurenceMap, pair, occurences)
    }
  })
  <span class="hljs-keyword">return</span> newPairOccurenceMap
}
</code></pre>
<h3 id="heading-find-polymer-occurrence-map">Find polymer occurrence map</h3>
<p>We can determine the polymer occurrence map based on the pair occurrence map and the first and last letter of the initial template. Each polymer, except the first and last one in the initial template, is counted twice in pairs. Thus, we must add the first and last polymers one more time, then divide each polymer occurrence by 2 to determine the correct polymer occurrence.</p>
<pre><code class="lang-js">onst getPolymerOccurenceMap = <span class="hljs-function">(<span class="hljs-params">pairOccurenceMap, template</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> occurenceMap = {}
  <span class="hljs-built_in">Object</span>.keys(pairOccurenceMap).forEach(<span class="hljs-function"><span class="hljs-params">pair</span> =&gt;</span> {
    addToOccurenceMap(occurenceMap, pair.charAt(<span class="hljs-number">0</span>), pairOccurenceMap[pair])
    addToOccurenceMap(occurenceMap, pair.charAt(<span class="hljs-number">1</span>), pairOccurenceMap[pair])
  })

  occurenceMap[template.charAt(<span class="hljs-number">0</span>)]++
  occurenceMap[template.charAt(template.length - <span class="hljs-number">1</span>)]++

  <span class="hljs-built_in">Object</span>.keys(occurenceMap).forEach(<span class="hljs-function"><span class="hljs-params">key</span> =&gt;</span> {
    occurenceMap[key] = <span class="hljs-built_in">Math</span>.floor(occurenceMap[key] / <span class="hljs-number">2</span>)
  })
  <span class="hljs-keyword">return</span> occurenceMap
}
</code></pre>
<h3 id="heading-subtract-the-least-from-the-most-common-polymer">Subtract the least from the most common polymer</h3>
<p>We can calculate the least and most common polymers by iterating through the keys of the polymer occurence map.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getLeastAndMostCommon = <span class="hljs-function">(<span class="hljs-params">occurenceMap</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> leastCommon
  <span class="hljs-keyword">let</span> mostCommon

  <span class="hljs-built_in">Object</span>.keys(occurenceMap).forEach(<span class="hljs-function">(<span class="hljs-params">polymer</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (!leastCommon || occurenceMap[leastCommon] &gt; occurenceMap[polymer]) {
      leastCommon = polymer
    }
    <span class="hljs-keyword">if</span> (!mostCommon || occurenceMap[mostCommon] &lt; occurenceMap[polymer]) {
      mostCommon = polymer
    }
  })

  <span class="hljs-keyword">return</span> { leastCommon, mostCommon }
}
</code></pre>
<p>Then we can subtract the occurence of the least most common polymers:</p>
<pre><code class="lang-js">polymerOccurenceMap[mostCommon] - polymerOccurenceMap[leastCommon]
</code></pre>
<p>The final solution for Day 14 is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/tree/main/src/day-14-extended-polymerization">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 14 was tricky and required optimally determining the least and most common letter occurrences in an exponentially growing string. An occurrence hash map storing pairs helped define the next set of occurrences, prevented storing a massive string and made it possible to solve the challenge.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 13]]></title><description><![CDATA[This blog post is thirteenth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 13.
All solutions are in this GitHub repository.
Solving Part One
Given a list of x, y coordinates representing dots ...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-13</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-13</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Mon, 13 Dec 2021 18:06:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639414171875/9AWYLqjz6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is thirteenth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/13">Day 13</a>.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>Given a list of <code>x</code>, <code>y</code> coordinates representing dots on a transparent Origami paper along with folding instructions, we must determine the number of visible dots after the first fold.</p>
<p>I broke down the solution as follows:</p>
<ul>
<li>read input into a dot coordinate hash map</li>
<li>read the first instruction</li>
<li>update dots after folding left</li>
<li>update dots after folding up</li>
<li>count dots</li>
</ul>
<h3 id="heading-read-input-into-a-dot-coordinate-hash-map">Read input into a dot coordinate hash map</h3>
<p>In terms of the data structure for the Origami paper, I opted for a hash map that stores dot coordinates. An alternative data structure is a matrix of characters <code>.</code> and <code>#</code>. However, since the problem doesn't specify constraints about the paper size and since the matrix size changes at each step, I deemed this approach more difficult to implement.</p>
<p>The first step of reading the input is separating the dot coordinates from the instructions using the empty line separator <code>\n\n</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [dotsString, instructionsString] = data.split(<span class="hljs-string">'\n\n'</span>)
</code></pre>
<p>Next, we add each dot to the hash map using the <code>x,y</code> string as a key and <code>{x, y}</code> as value.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dots = {}
dotsString.split(<span class="hljs-string">'\n'</span>).map(<span class="hljs-function">(<span class="hljs-params">dot</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [x, y] = dot.split(<span class="hljs-string">','</span>).map(<span class="hljs-function">(<span class="hljs-params">n</span>) =&gt;</span> <span class="hljs-built_in">parseInt</span>(n))
  dots[dot] = { x, y }
})
</code></pre>
<p>For example, given the <code>1,7</code> coordinates, we store:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dots = {
  <span class="hljs-string">'1,7'</span>: {
    <span class="hljs-attr">x</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">y</span>: <span class="hljs-number">7</span>
  }
}
</code></pre>
<h3 id="heading-read-the-first-instruction">Read the first instruction</h3>
<p>We can get the first line among instructions using the <code>split</code> function and the 0 index.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> firstInstruction = instructionsString.split(<span class="hljs-string">'\n'</span>)[<span class="hljs-number">0</span>]
</code></pre>
<p>To interpret the folding instruction we need the axis (<code>x</code> or <code>y</code>) and the line coordinate. Thus, we can remove the <code>fold along</code> string.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [axis, lineString] = firstInstruction
  .replace(<span class="hljs-string">'fold along '</span>, <span class="hljs-string">''</span>)
  .split(<span class="hljs-string">'='</span>)

<span class="hljs-keyword">const</span> line = <span class="hljs-built_in">parseInt</span>(lineString)
</code></pre>
<p>According to the problem, axis <code>x</code> is a vertical line, thus we must fold the paper to the left, whereas given axis <code>y</code> is a horizontal line, we must fold the paper up. We define the <code>foldLeft</code> and <code>foldUp</code> functions next.</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (axis === <span class="hljs-string">'x'</span>) {
  foldLeft(dots, line)
} <span class="hljs-keyword">else</span> {
  foldUp(dots, line)
}
</code></pre>
<h3 id="heading-update-dots-after-folding-left">Update dots after folding left</h3>
<p>We must inspect each dot coordinate. We can use the <code>Object.key</code> function to iterate through the elements of the dot hash map. We need to determine whether a dot is on the right half of the paper relative to the folding line. This condition is met when the <code>x</code> coordinate of the dot is larger than the <code>x</code> coordinate representing the line (<code>x &gt; line</code>).</p>
<p>Each dot on the right half of the paper changes its <code>x</code> coordinate after folding the paper by twice the difference between itself and the line. We can express this as <code>const newX = x - 2 * (line - x)</code>
For example, the folding line <code>x=7</code> updates the <code>x</code> coordinate of dot <code>9,1</code> from <code>9</code> to <code>9 - 2 * (9 - 7) = 5</code> resulting in dot <code>5,1</code>. We can simplify the expression to <code>const newX = 2 * line - x</code>.</p>
<p>Once we have determined the new coordinates, we can add the new dot to the hash map and delete the dot with old coordinates.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> foldLeft = <span class="hljs-function">(<span class="hljs-params">dots, line</span>) =&gt;</span> {
  <span class="hljs-built_in">Object</span>.keys(dots)
  .forEach(<span class="hljs-function">(<span class="hljs-params">key</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { x, y } = dots[key]
    <span class="hljs-keyword">if</span> (x &gt; line) {
      <span class="hljs-keyword">const</span> newX = <span class="hljs-number">2</span> * line - x
      dots[getKey(newX, y)] = { <span class="hljs-attr">x</span>: newX, y }
      <span class="hljs-keyword">delete</span> dots[key]
    }
  })
}
</code></pre>
<h3 id="heading-update-dots-after-folding-up">Update dots after folding up</h3>
<p>To fold up, we can use the same algorithm as for folding to the left, except we update the <code>y</code> coordinate instead of <code>x</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> foldUp = <span class="hljs-function">(<span class="hljs-params">dots, line</span>) =&gt;</span> {
  <span class="hljs-built_in">Object</span>.keys(dots)
    .forEach(<span class="hljs-function">(<span class="hljs-params">key</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> { x, y } = dots[key]
      <span class="hljs-keyword">if</span> (y &gt; line) {
        <span class="hljs-keyword">const</span> newY = <span class="hljs-number">2</span> * line - y
        dots[getKey(x, newY)] = { x, <span class="hljs-attr">y</span>: newY }
        <span class="hljs-keyword">delete</span> dots[key]
      }
    })
}
</code></pre>
<h3 id="heading-count-dots">Count dots</h3>
<p>We can rely on the <code>Object.keys</code> function to count the number of visible dots after folding the Origami paper.</p>
<pre><code class="lang-js"><span class="hljs-built_in">Object</span>.keys(dots).length
</code></pre>
<p>The final solution for part one is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-13-transparent-origami/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>Part two was about following all folding instructions, printing the final Origami result and revealing eight uppercase characters - the expected output.</p>
<p>To solve part two we can build on top of part one with the following additions:</p>
<ul>
<li>fold paper according to all instructions</li>
<li>print folded Origami paper</li>
</ul>
<h3 id="heading-fold-paper-according-to-all-instructions">Fold paper according to all instructions</h3>
<p>Unlike in part one, we must iterate through and follow all folding instructions one by one.</p>
<pre><code class="lang-js"> instructionsString.split(<span class="hljs-string">'\n'</span>).forEach(<span class="hljs-function">(<span class="hljs-params">instruction</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [axis, lineString] = instruction.replace(<span class="hljs-string">'fold along '</span>, <span class="hljs-string">''</span>).split(<span class="hljs-string">'='</span>)
  <span class="hljs-keyword">const</span> line = <span class="hljs-built_in">parseInt</span>(lineString)
  <span class="hljs-keyword">if</span> (axis === <span class="hljs-string">'x'</span>) {
    foldLeft(dots, line)
  } <span class="hljs-keyword">else</span> {
    foldUp(dots, line)
  }
})
</code></pre>
<h3 id="heading-print-folded-origami-paper">Print folded Origami paper</h3>
<p>Once we have the final coordinates of dots on the folded Origami paper, we are able to print it.
We need to know the size of the folded Origami paper to be able to print it. Thus, we must find the maximum <code>x</code> and <code>y</code> coordinates.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [maxX, maxY] = <span class="hljs-built_in">Object</span>.keys(dots).reduce(
  <span class="hljs-function">(<span class="hljs-params">[maxX, maxY], key</span>) =&gt;</span> [
    <span class="hljs-built_in">Math</span>.max(maxX, dots[key].x),
    <span class="hljs-built_in">Math</span>.max(maxY, dots[key].y),
  ],
  [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
)
</code></pre>
<p>Next, for each two coordinate between 0 and the size of the paper, we print either a <code>#</code> if a dot exists with those coordinates, or a space character <code> </code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> y = <span class="hljs-number">0</span>; y &lt;= maxY; y++) {
  <span class="hljs-keyword">let</span> line = <span class="hljs-string">''</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>; x &lt;= maxX; x++) {
    <span class="hljs-keyword">const</span> character = dots[getKey(x, y)] ? <span class="hljs-string">'#'</span> : <span class="hljs-string">' '</span>
    line += character
  }
  <span class="hljs-built_in">console</span>.log(line)
}
</code></pre>
<p>The final solution for part two is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-13-transparent-origami/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 13 was about folding a transparent Origami paper, updating coordinates of dots on the paper and revealing a final eight-character message.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 12]]></title><description><![CDATA[This blog post is twelfth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described on Day 12.
All solutions are in this GitHub repository.
Solving Part One
Given a set of connections between underground caves, ...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-12</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-12</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Sun, 12 Dec 2021 13:12:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639307727234/_b6yZP61D.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is twelfth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described on <a target="_blank" href="https://adventofcode.com/2021/day/12">Day 12</a>.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>Given a set of connections between underground caves, we must find all possible paths between the <code>start</code> and <code>end</code> caves and output the number of found paths. We can visit large caves (named using uppercase letters) multiple times, whereas we can only visit small caves (names using lowercase letters) once.</p>
<p>The strategy for solving part one was a recursive algorithm that returns the number of paths from a given cave to the <code>end</code> cave. At each recursion step, we visit each linked cave of the current cave and recursively return the number of paths from the linked cave to the <code>end</code> cave.</p>
<p>In terms of data structure, I opted for representing the cave graph using an <a target="_blank" href="https://en.wikipedia.org/wiki/Adjacency_list">Adjacency List</a>. In other words, a key-value map, where the keys are the cave names and each value is an array corresponding to linked caves. For example, the input from the problem description would produce the following key-value map:</p>
<pre><code class="lang-js">{
  <span class="hljs-attr">start</span>: [ <span class="hljs-string">'A'</span>, <span class="hljs-string">'b'</span> ],
  <span class="hljs-attr">A</span>: [ <span class="hljs-string">'start'</span>, <span class="hljs-string">'c'</span>, <span class="hljs-string">'b'</span>, <span class="hljs-string">'end'</span> ],
  <span class="hljs-attr">b</span>: [ <span class="hljs-string">'start'</span>, <span class="hljs-string">'A'</span>, <span class="hljs-string">'d'</span>, <span class="hljs-string">'end'</span> ],
  <span class="hljs-attr">c</span>: [ <span class="hljs-string">'A'</span> ],
  <span class="hljs-attr">d</span>: [ <span class="hljs-string">'b'</span> ],
  <span class="hljs-attr">end</span>: [ <span class="hljs-string">'A'</span>, <span class="hljs-string">'b'</span> ]
}
</code></pre>
<p>This data structure works well for iterating through adjacent caves.</p>
<p>I broke down the solution as follows:</p>
<ul>
<li>build the adjacency list from the input file</li>
<li>get number of paths from the start cave recursively</li>
<li>prevent visiting small caves twice</li>
</ul>
<h3 id="heading-build-the-adjacency-list-from-the-input-file">Build the adjacency list from the input file</h3>
<p>The first step to solving part one is reading each line representing a connection between two caves and adding this information to the adjacency list.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> links = {}
<span class="hljs-keyword">const</span> lines = data.split(<span class="hljs-string">'\n'</span>)
lines.forEach(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [caveA, caveB] = line.split(<span class="hljs-string">'-'</span>)
  addLink(links, caveA, caveB)
  addLink(links, caveB, caveA)
})
</code></pre>
<p>The <code>addLink</code> function adds a connected cave (e.g. <code>caveB</code>) to the corresponding list (e.g. <code>caveA</code> list) or creates a new list if the cave does not exist.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> addLink = <span class="hljs-function">(<span class="hljs-params">links, caveA, caveB</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (links[caveA]) {
    links[caveA].push(caveB)
  } <span class="hljs-keyword">else</span> {
    links[caveA] = [caveB]
  }
}
</code></pre>
<h3 id="heading-get-number-of-paths-from-the-start-cave-recursively">Get number of paths from the start cave recursively</h3>
<p>The first call of the recursive <code>getPaths</code> function begins from the <code>start</code> cave. It passes the following parameters:</p>
<ul>
<li>the adjacent list <code>links</code> used for finding connected caves</li>
<li>an array of visited caves containing the <code>start</code> cave</li>
<li>the cave from which to count paths to the <code>end</code> cave</li>
</ul>
<pre><code class="lang-js">getPaths(links, [<span class="hljs-string">"start"</span>], <span class="hljs-string">"start"</span>)
</code></pre>
<p>The outline for getting the number of paths recursively is the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getPaths = <span class="hljs-function">(<span class="hljs-params">links, visitedSmallCaves, cave</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (cave === <span class="hljs-string">"end"</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>
  }

  <span class="hljs-keyword">let</span> generatedPaths = <span class="hljs-number">0</span>
  links[cave].forEach(<span class="hljs-function"><span class="hljs-params">linkedCave</span> =&gt;</span> {
    <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> if small cave not visited </span>
    generatedPaths += getPaths(links, visitedSmallCaves, linkedCave)
  })
  <span class="hljs-keyword">return</span> generatedPaths
}
</code></pre>
<p>The recursion stop condition is when we reach the <code>end</code> cave. Thus we can return <code>1</code> representing a path found. Alternatively, we might return <code>0</code> if we reach a dead-end (e.g. a small cave connected to already visited small caves).</p>
<p>Each recursion step, we iterate through the connected caves and sum the possible paths to the <code>end</code> cave. </p>
<p>Keep in mind that the outlined algorithm doesn't yet consider visited small caves. Thus, if you run it as is, it will go back and forth between the same two caves until the program throws a stack overflow exception. We'll take a look at visited caves next.</p>
<h3 id="heading-prevent-visiting-small-caves-twice">Prevent visiting small caves twice</h3>
<p>To check whether a cave is small we need to verify whether it has lowercase characters</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isSmallCave = <span class="hljs-function">(<span class="hljs-params">cave</span>) =&gt;</span> cave.toLowerCase() === cave
</code></pre>
<p>Then we can update the <code>visitedSmallCaves</code> like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> newVisitedArray = isSmallCave(linkedCave) 
  ? [...visitedSmallCaves, linkedCave]
  : visitedSmallCaves
</code></pre>
<p>We are then able to check whether we have visited a small cave using the <code>include</code> function like so:</p>
<pre><code class="lang-js">visitedSmallCaves.includes(linkedCave)
</code></pre>
<p>Thus, the updated <code>getPath</code> function contains the following:</p>
<pre><code>links[cave].forEach(linkedCave <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>visitedSmallCaves.includes(linkedCave)) {
    const newVisitedArray <span class="hljs-operator">=</span> isSmallCave(linkedCave) ? [...visitedSmallCaves, linkedCave] : visitedSmallCaves
    generatedPaths <span class="hljs-operator">+</span><span class="hljs-operator">=</span> getPaths(links, newVisitedArray, linkedCave)
  }
})
</code></pre><p>The final solution for part one is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-12-passage-pathing/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>Part two changes the visiting rules by allowing one to visit a single small cave twice, except the <code>start</code> and <code>end</code> caves, which one can only visit once.</p>
<p>The strategy for solving part two was adding an item called <code>twice</code> to the <code>visitedSmallCaves</code> array after visiting a small cave twice. </p>
<p>I updated the recursive <code>getPath</code> function in order to separate the visiting logic to two separate functions: <code>hasVisitedCave</code> and <code>getVisitedCaves</code>.</p>
<pre><code class="lang-js">  links[cave].forEach(<span class="hljs-function"><span class="hljs-params">linkedCave</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (!hasVisitedCave(visitedSmallCaves, linkedCave)) {
      generatedPaths += getPaths(links, getVisitedCaves(visitedSmallCaves, linkedCave), linkedCave)
    }
  })
</code></pre>
<p>The <code>hasVisitedCave</code> function includes the new rules and allows visiting a single small cave that are not names <code>start</code> twice.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> hasVisitedCave = <span class="hljs-function">(<span class="hljs-params">visited, cave</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (cave === <span class="hljs-string">"start"</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
  }
  <span class="hljs-keyword">return</span> visited.includes(cave) &amp;&amp; visited.includes(<span class="hljs-string">"twice"</span>)
}
</code></pre>
<p>The <code>getVisitedCaves</code> function skips adding large caves, adds the <code>twice</code> element to the array once a small cave has been visited twice and adds small caves that have not been visited before.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getVisitedCaves = <span class="hljs-function">(<span class="hljs-params">visited, cave</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> isSmall = isSmallCave(cave)
  <span class="hljs-keyword">if</span> (!isSmall) {
    <span class="hljs-keyword">return</span> visited
  }
  <span class="hljs-keyword">if</span> (visited.includes(cave)) {
    <span class="hljs-keyword">return</span> [...visited, <span class="hljs-string">"twice"</span>]
  }
  <span class="hljs-keyword">return</span> [...visited, cave]
}
</code></pre>
<p>The final solution for part two is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-12-passage-pathing/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 12 was about finding all paths between two caves recursively. A graph implemented using an Adjacency List helped store connected caves.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 11]]></title><description><![CDATA[This blog post is eleventh in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 11. This day had many similarities to Day 9, and I solved the challenge using similar methods.
All solutions are in thi...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-11</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-11</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Sat, 11 Dec 2021 14:24:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639224288993/caUNHl-sL.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is eleventh in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/11">Day 11</a>. This day had many similarities to <a target="_blank" href="https://adventofcode.com/2021/day/9">Day 9</a>, and I solved the challenge using similar methods.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>Part one aims to count the number of flashes a group of bioluminescent dumbo octopuses produce. </p>
<p>We can break down the solution as follows:</p>
<ul>
<li>read the input into a matrix</li>
<li>outline algorithm for counting flashes for 100 steps</li>
<li>increment energy levels of all octopuses</li>
<li>initialize a binary flash map</li>
<li>recursively mark flashes and update matrix</li>
<li>sum elements of the binary flash map</li>
<li>reset energy levels for flashing octopuses</li>
</ul>
<p>Initializing and traversing a matrix of numbers is done in the same way as described in my previous blog post <a target="_blank" href="https://blog.cristiana.tech/advent-of-code-2021-day-9">Advent of Code 2021: Day 9</a>. I suggest you check it out as I won't write about it again here.</p>
<h3 id="heading-outline-algorithm-for-counting-flashes-for-100-steps">Outline algorithm for counting flashes for 100 steps</h3>
<p>We can use a <code>for</code> loop to count flashes for 100 steps.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> flashesCount = <span class="hljs-number">0</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100</span>; i++) {
  flashesCount += countFlashes(matrix, rows, cols)
}

<span class="hljs-keyword">return</span> flashesCount
</code></pre>
<p>The <code>countFlashes</code> function outlines the changes in energy levels at each step and counts the corresponding flashes. As described in the problem, we must first increment the energy level of each octopus. Then, each octopus with an energy level higher than <code>9</code> flashes, which triggers increments energy levels of neighbouring octopuses. We can use a binary flash map to store and count the octopuses that flash in each step.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> countFlashes = <span class="hljs-function">(<span class="hljs-params">matrix, rows, cols</span>) =&gt;</span> {
  <span class="hljs-comment">// increment energy level</span>
  <span class="hljs-comment">// initialize binary flash map</span>
  <span class="hljs-comment">// recursively flash octopuses with energy level higher than 9</span>
  <span class="hljs-comment">// reset energy level</span>
  <span class="hljs-comment">// sum binary flash map</span>
}
</code></pre>
<h3 id="heading-increment-energy-levels-of-all-octopuses">Increment energy levels of all octopuses</h3>
<p>The first part of our algorithm is incrementing each number in the matrix by <code>1</code>. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> countFlashes = <span class="hljs-function">(<span class="hljs-params">matrix, rows, cols</span>) =&gt;</span> {
  incrementEnergyLevel(matrix)
  <span class="hljs-comment">// initialize binary flash map</span>
  <span class="hljs-comment">// recursively flash octopuses with energy level higher than 9</span>
  <span class="hljs-comment">// reset energy level</span>
  <span class="hljs-comment">// sum binary flash map</span>
}
</code></pre>
<p>We can achieve this by traversing the matrix using nested <code>forEach</code> functions.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> incrementEnergyLevel = <span class="hljs-function">(<span class="hljs-params">matrix</span>) =&gt;</span> {
  matrix.forEach(<span class="hljs-function">(<span class="hljs-params">row, i</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">energyLevel, j</span>) =&gt;</span> {
      matrix[i][j]++
    })
  })
}
</code></pre>
<h3 id="heading-recursively-mark-flashes-and-update-matrix">Recursively mark flashes and update matrix</h3>
<p>We can initialize a binary flash map to indicate which octopuses flash at each step. The binary flash map is a matrix of the same size as the octopuses matrix. We initialize each element with 0 and mark flashing octopuses with 1.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> flashMap = initializeFlashMap(rows, cols)
</code></pre>
<p>We can then traverse the matrix of octopuses to find the ones with an energy level higher than 9. Once found, we mark that octopus and potentially neighbouring octopuses as flashing using the recursive <code>flash</code> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> countFlashes = <span class="hljs-function">(<span class="hljs-params">matrix, rows, cols</span>) =&gt;</span> {
  incrementEnergyLevel(matrix)

  <span class="hljs-keyword">const</span> flashMap = initializeFlashMap(rows, cols)
  matrix.forEach(<span class="hljs-function">(<span class="hljs-params">row, i</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">energyLevel, j</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (energyLevel &gt; <span class="hljs-number">9</span>) {
        flash(matrix, flashMap, rows, cols, i, j)
      }
    })
  })
  <span class="hljs-comment">// reset energy level</span>
  <span class="hljs-comment">// sum binary flash map</span>
}
</code></pre>
<p>The recursive <code>flash</code> function marks the current octopus as flashing by setting <code>flashMap[i][j] = 1</code>. Then goes through each neighbour to determine whether it also needs to flash. The stop condition for this recursion is when we reach an element that has already flashed.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> flash = <span class="hljs-function">(<span class="hljs-params">matrix, flashMap, rows, cols, i, j</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (flashMap[i][j] === <span class="hljs-number">1</span>) {
    <span class="hljs-keyword">return</span>
  }
  flashMap[i][j] = <span class="hljs-number">1</span>
  <span class="hljs-keyword">const</span> neighbours = getNeighbours(rows, cols, i, j)
  neighbours.forEach(<span class="hljs-function">(<span class="hljs-params">{ ni, nj }</span>) =&gt;</span> {
    matrix[ni][nj]++
    <span class="hljs-keyword">if</span> (matrix[ni][nj] &gt; <span class="hljs-number">9</span>) {
      flash(matrix, flashMap, rows, cols, ni, nj)
    }
  })
}
</code></pre>
<h4 id="heading-find-neighbours">Find neighbours</h4>
<p>To find the neighbours of an octopus, I used the following relative indices as shown in the diagram.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639231413376/ne-4izdK3J.png" alt="MatrixNeighboursIndices.png" /></p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getNeighbours = <span class="hljs-function">(<span class="hljs-params">rows, cols, i, j</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> neighbours = []
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> ni = i - <span class="hljs-number">1</span>; ni &lt;= i + <span class="hljs-number">1</span>; ni++) {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> nj = j - <span class="hljs-number">1</span>; nj &lt;= j + <span class="hljs-number">1</span>; nj++) {
      <span class="hljs-keyword">if</span> (ni === i &amp;&amp; nj === j) {
        <span class="hljs-keyword">continue</span>
      }
      neighbours.push({ ni, nj })
    }
  }
  <span class="hljs-keyword">return</span> neighbours
}
</code></pre>
<p>The algorithm, however, does not take into account elements on the edge of the matrix. We can use <code>Math</code> functions to adjust the limits of the <code>for</code> loops to accommodate edges.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getNeighbours = <span class="hljs-function">(<span class="hljs-params">rows, cols, i, j</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> neighbours = []
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> ni = <span class="hljs-built_in">Math</span>.max(<span class="hljs-number">0</span>, i - <span class="hljs-number">1</span>); ni &lt;= <span class="hljs-built_in">Math</span>.min(rows - <span class="hljs-number">1</span>, i + <span class="hljs-number">1</span>); ni++) {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> nj = <span class="hljs-built_in">Math</span>.max(<span class="hljs-number">0</span>, j - <span class="hljs-number">1</span>); nj &lt;= <span class="hljs-built_in">Math</span>.min(cols - <span class="hljs-number">1</span>, j + <span class="hljs-number">1</span>); nj++) {
      <span class="hljs-keyword">if</span> (ni === i &amp;&amp; nj === j) {
        <span class="hljs-keyword">continue</span>
      }
      neighbours.push({ ni, nj })
    }
  }
  <span class="hljs-keyword">return</span> neighbours
}
</code></pre>
<h3 id="heading-sum-elements-of-the-binary-flash-map">Sum elements of the binary flash map</h3>
<p>We can traverse the binary flash matrix using <code>forEach</code> function to sum each element. Since flashing octopuses are marked with <code>1</code> and all other octopuses with <code>0</code>, this function counts the number of flashing octopuses.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sumFlashMap = <span class="hljs-function">(<span class="hljs-params">flashMap</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> sum = <span class="hljs-number">0</span>
  flashMap.forEach(<span class="hljs-function">(<span class="hljs-params">row</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">flash</span>) =&gt;</span> {
      sum += flash
    })
  })
  <span class="hljs-keyword">return</span> sum
}
</code></pre>
<h3 id="heading-reset-energy-levels-for-flashing-octopuses">Reset energy levels for flashing octopuses</h3>
<p>To reset the energy levels for flashing octopuses we need to traverse the octopus matrix and set the octopuses with energy larger than <code>9</code> to <code>0</code>. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> resetEnergyLevel = <span class="hljs-function">(<span class="hljs-params">matrix</span>) =&gt;</span> {
  matrix.forEach(<span class="hljs-function">(<span class="hljs-params">row, i</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">energyLevel, j</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (energyLevel &gt; <span class="hljs-number">9</span>) {
        matrix[i][j] = <span class="hljs-number">0</span>
      }
    })
  })
}
</code></pre>
<p>The final solution for part one is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-11-dumbo-octopus/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>Part two was about finding the step when all octopuses flash simultaneously. Since we already implemented a function that counts flashes on each step, we can run the program and increment the step until all 100 octopuses flash.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> step = <span class="hljs-number">1</span>
<span class="hljs-keyword">while</span> (countFlashes(matrix, rows, cols) !== <span class="hljs-number">100</span>) {
  step++
}
<span class="hljs-keyword">return</span> step
</code></pre>
<p>The final solution for part two is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-11-dumbo-octopus/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 11 was about traversing a matrix of octopuses, increasing their energy level with each step, recursively flashing octopuses and their neighbours, and finally, determining when all octopuses flash simultaneously.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 10]]></title><description><![CDATA[This blog post is the tenth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 10.
All solutions are in this GitHub repository.
Solving Part One
Given a set of lines with opening and closing bracke...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-10</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-10</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Fri, 10 Dec 2021 21:17:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639175852316/z5P-7O0Y4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is the tenth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/10">Day 10</a>.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>Given a set of lines with opening and closing brackets, we must find syntax errors and calculate their score.</p>
<p>My strategy for solving this challenge is using a FILO (First In, Last Out) data structure that stores open brackets. We add new open brackets to the array. If a bracket is closed correctly, we pop the last open bracket from the array. Otherwise, if the closing bracket does not correspond to the previous open bracket, we have found a syntax error, and we can calculate its score.</p>
<p>We can break down the solution like so:</p>
<ul>
<li>outline the algorithm that sums syntax error scores</li>
<li>add open brackets to the FILO data structure</li>
<li>remove open brackets when the corresponding closing bracket matches</li>
<li>calculate illegal bracket score when the corresponding closing bracket does not match</li>
</ul>
<h3 id="heading-outline-the-algorithm-that-sums-syntax-error-scores">Outline the algorithm that sums syntax error scores</h3>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> lines = data.split(<span class="hljs-string">'\n'</span>)
<span class="hljs-keyword">return</span> lines.reduce(<span class="hljs-function">(<span class="hljs-params">sum, line</span>) =&gt;</span> sum + getErrorScore(line), <span class="hljs-number">0</span>)
</code></pre>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getErrorScore = <span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> brackets = line.split(<span class="hljs-string">''</span>)
  <span class="hljs-keyword">let</span> score = <span class="hljs-number">0</span>
  brackets.some(<span class="hljs-function"><span class="hljs-params">bracket</span> =&gt;</span> {
    <span class="hljs-comment">// If there is a syntax error overwrite score</span>
  })

  <span class="hljs-keyword">return</span> score
}
</code></pre>
<h3 id="heading-add-open-brackets-to-the-filo-data-structure">Add open brackets to the FILO data structure</h3>
<p>To check whether we reached an open bracket we can use the <code>include</code> function on the open brackets array like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isOpeningBracket = <span class="hljs-function">(<span class="hljs-params">bracket</span>) =&gt;</span> [<span class="hljs-string">"{"</span>, <span class="hljs-string">"["</span>, <span class="hljs-string">"("</span>, <span class="hljs-string">"&lt;"</span>].includes(bracket)
</code></pre>
<p>We can then use the <code>isOpeningBracket</code> function to determine whether to add a new item to the <code>openBrackets</code> FILO data structure.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getErrorScore = <span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> brackets = line.split(<span class="hljs-string">''</span>)
  <span class="hljs-keyword">const</span> openBrackets = []
  <span class="hljs-keyword">let</span> score = <span class="hljs-number">0</span>
  brackets.some(<span class="hljs-function"><span class="hljs-params">bracket</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (isOpeningBracket(bracket)) {
      openBrackets.push(bracket)
    }
    <span class="hljs-comment">// If there is a syntax error overwrite score</span>
  })
  <span class="hljs-keyword">return</span> score
}
</code></pre>
<h3 id="heading-remove-open-brackets-when-the-corresponding-closing-bracket-matches">Remove open brackets when the corresponding closing bracket matches</h3>
<p>We can define matching brackets like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> matchingBrackets = {
  <span class="hljs-string">"("</span>: <span class="hljs-string">")"</span>,
  <span class="hljs-string">"["</span>: <span class="hljs-string">"]"</span>,
  <span class="hljs-string">"{"</span>: <span class="hljs-string">"}"</span>,
  <span class="hljs-string">"&lt;"</span>: <span class="hljs-string">"&gt;"</span>
}
</code></pre>
<p>We can use the following function to check whether a closing bracket matches an existing open bracket. We also check whether the opening bracket exists because a closing bracket written before any opening bracket represents a syntax error.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isCorrectClosingBracket = <span class="hljs-function">(<span class="hljs-params">openingBracket, closingBracket</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (!openingBracket) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  } 
  <span class="hljs-keyword">return</span> matchingBrackets[openingBracket] === closingBracket
}
</code></pre>
<p>We can use the <code>pop</code> function to remove the last element in the FILO structure.</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (isOpeningBracket(bracket)) {
  openBrackets.push(bracket)
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(isCorrectClosingBracket(openBrackets[openBrackets.length - <span class="hljs-number">1</span>], bracket)) {
  openBrackets.pop()
}
</code></pre>
<h3 id="heading-calculate-illegal-bracket-score-when-the-corresponding-closing-bracket-does-not-match">Calculate illegal bracket score when the corresponding closing bracket does not match</h3>
<p>The illegal bracket has a defined score as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> illegalBracketScoring = {
  <span class="hljs-string">")"</span>: <span class="hljs-number">3</span>,
  <span class="hljs-string">"]"</span>: <span class="hljs-number">57</span>,
  <span class="hljs-string">"}"</span>: <span class="hljs-number">1197</span>,
  <span class="hljs-string">"&gt;"</span>: <span class="hljs-number">25137</span>
}
</code></pre>
<p>We can pop the last element of the <code>openBrackets</code> regardless of whether the closed bracket is correct or not. Thus, we can rewrite the conditions from the <code>getErrorScore</code> function as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> score = <span class="hljs-number">0</span>
brackets.some(<span class="hljs-function"><span class="hljs-params">bracket</span> =&gt;</span> {
  <span class="hljs-keyword">if</span> (isOpeningBracket(bracket)) {
    openBrackets.push(bracket)
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(!isCorrectClosingBracket(openBrackets.pop(), bracket)) {
    score = illegalBracketScoring[bracket]
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> 
  }
})
<span class="hljs-keyword">return</span> score
</code></pre>
<p>The final solution for part one is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-10-syntax-scoring/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>Part two is about filtering the corrupted lines identified in part one and focusing on the incomplete lines. The goal is to find the missing brackets of incomplete lines and calculate a score corresponding to each completed line. We must sort all scores to return the expected score in the middle.</p>
<p>We can reuse a great deal of the solutions from part one with a few additions:</p>
<ul>
<li>filter corrupted lines using the error score</li>
<li>use opening brackets to calculate the completion score</li>
<li>find the middle completion score</li>
</ul>
<h3 id="heading-filter-corrupted-lines-using-the-error-score">Filter corrupted lines using the error score</h3>
<p>We can reuse the <code>getErrorScore</code> function from part one, with a few adjustments:</p>
<ul>
<li>remove the score calculation since it is unnecessary for part two</li>
<li>return a boolean <code>hasError</code> set to <code>true</code> when the line has a syntax error</li>
<li>return the array of open brackets</li>
<li>rename function to <code>getOpeningBrackets</code> to better fit the goal of part two</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getOpeningBrackets = <span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> brackets = line.split(<span class="hljs-string">''</span>)
  <span class="hljs-keyword">const</span> openingBrackets = []
  <span class="hljs-keyword">const</span> hasError = brackets.some(<span class="hljs-function">(<span class="hljs-params">bracket</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (isOpeningBracket(bracket)) {
      openingBrackets.push(bracket)
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!isCorrectClosingBracket(openingBrackets.pop(), bracket)) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
    }
  })

  <span class="hljs-keyword">return</span> [hasError, openingBrackets]
}
</code></pre>
<p>We can call the <code>getOpeningBrackets</code> function to filter the lines with syntax errors. The <code>reduce</code> function returns the array of completed line scores by adding a calculated score for each line without a syntax error.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> completedLineScores = lines.reduce(<span class="hljs-function">(<span class="hljs-params">completed, line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [hasError, openingBrackets] = getOpeningBrackets(line)
  <span class="hljs-keyword">if</span> (hasError) {
    <span class="hljs-keyword">return</span> completed
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> [...completed, getCompletionScore(openingBrackets)]
  }
}, [])
</code></pre>
<h3 id="heading-use-opening-brackets-to-calculate-the-completion-score">Use opening brackets to calculate the completion score</h3>
<p>Each closing bracket has the following score:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> completionScoring = {
  <span class="hljs-string">')'</span>: <span class="hljs-number">1</span>,
  <span class="hljs-string">']'</span>: <span class="hljs-number">2</span>,
  <span class="hljs-string">'}'</span>: <span class="hljs-number">3</span>,
  <span class="hljs-string">'&gt;'</span>: <span class="hljs-number">4</span>,
}
</code></pre>
<p>We must traverse open brackets in reverse order to find the matching closing bracket and calculate its corresponding score.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getCompletionScore = <span class="hljs-function">(<span class="hljs-params">openingBrackets</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> openingBrackets
    .reverse()
    .reduce(
      <span class="hljs-function">(<span class="hljs-params">score, bracket</span>) =&gt;</span>
        score * <span class="hljs-number">5</span> + completionScoring[matchingBrackets[bracket]],
      <span class="hljs-number">0</span>
    )
}
</code></pre>
<h3 id="heading-find-the-middle-completion-score">Find the middle completion score</h3>
<p>Once we have sorted the array of scores, we can determine the middle score using the middle of the array length as index.</p>
<pre><code class="lang-js">completedLineScores.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b)
<span class="hljs-keyword">const</span> middleIndex = <span class="hljs-built_in">Math</span>.floor(completedLineScores.length / <span class="hljs-number">2</span>)
<span class="hljs-keyword">return</span> completedLineScores[middleIndex]
</code></pre>
<p>The final solution for part two is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-10-syntax-scoring/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 10 was about processing lines of brackets, filtering lines with syntax errors and completing lines without errors. A FILO (First In, Last Out) data structure helped match open and close brackets.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 9]]></title><description><![CDATA[This blog post is ninth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 9.
All solutions are in this GitHub repository.
Solving Part One
The goal of part one is to find the low points of the giv...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-9</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-9</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Thu, 09 Dec 2021 21:11:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639164904885/1M3SI4Ah9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is ninth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/9">Day 9</a>.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>The goal of part one is to find the low points of the given matrix of heights. Then we must calculate the risk level by summing the heights of low points and adding 1 for each low point.</p>
<p>We can break down the solution as follows:</p>
<ul>
<li>read the input into a matrix</li>
<li>traverse the matrix</li>
<li>check if a height is a low point by comparing it to each neighbour</li>
<li>calculate the risk level</li>
</ul>
<h3 id="heading-read-the-input-into-a-matrix">Read the input into a matrix</h3>
<p>Storing elements into a matrix is a good choice since the problem requires checking neighbouring elements. The <code>split</code> function adds the data into rows and columns. The <code>parseInt</code> function converts each digit from a string to a number.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> heightMatrix = data
  .split(<span class="hljs-string">'\n'</span>)
  .map(<span class="hljs-function">(<span class="hljs-params">row</span>) =&gt;</span> row.split(<span class="hljs-string">''</span>).map(<span class="hljs-function">(<span class="hljs-params">height</span>) =&gt;</span> <span class="hljs-built_in">parseInt</span>(height)))
</code></pre>
<h3 id="heading-traverse-the-matrix">Traverse the matrix</h3>
<p>We can traverse the matrix using nested <code>for</code> loops or <code>forEach</code> functions. </p>
<pre><code class="lang-js">heightMatrix.forEach(<span class="hljs-function">(<span class="hljs-params">row, i</span>) =&gt;</span> {
  row.forEach(<span class="hljs-function">(<span class="hljs-params">height, j</span>) =&gt;</span> {
    <span class="hljs-comment">// compare height with neighbours</span>
  })
})
</code></pre>
<h3 id="heading-check-if-a-height-is-a-low-point-by-comparing-it-to-each-neighbour">Check if a height is a low point by comparing it to each neighbour</h3>
<p>The following diagram illustrates the indices of the four neighbours of an element in a matrix.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639166537396/6cwZ__p0U.png" alt="Matrix element neighbour indices" />
We can determine if a height is a low point by comparing it to each neighbour. If it is higher or equal to any neighbouring heights, it is not a low point (<code>return false</code>). Otherwise, we found a low point (<code>return true</code>).</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isLowPoint = <span class="hljs-function">(<span class="hljs-params">matrix, i, j</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (matrix[i][j] &gt;= matrix[i - <span class="hljs-number">1</span>][j]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }
  <span class="hljs-keyword">if</span> (matrix[i][j] &gt;= matrix[i + <span class="hljs-number">1</span>][j]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }
  <span class="hljs-keyword">if</span> (matrix[i][j] &gt;= matrix[i][j - <span class="hljs-number">1</span>]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }
  <span class="hljs-keyword">if</span> (matrix[i][j] &gt;= matrix[i][j + <span class="hljs-number">1</span>]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
}
</code></pre>
<p>The algorithm, however, does not account for elements on the edge of the matrix. Consider the number of rows and columns defined according to the height matrix lengths:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> rows = heightMatrix.length
<span class="hljs-keyword">const</span> cols = heightMatrix[<span class="hljs-number">0</span>].length
</code></pre>
<p>Elements on the edge of the matrix don't have all neighbours, so we must add the following rules:</p>
<ul>
<li>on the first row <code>i === 0</code>, so we should not check the top neighbour <code>i - 1</code> unless <code>i - 1 &gt;= 0</code></li>
<li>on the last row <code>i === rows - 1</code>, so we should not check the bottom neighbour <code>i + 1</code> unless <code>i + 1 &lt; rows</code></li>
<li>on the first column <code>j === 0</code>, so we should not check the left neighbour <code>j - 1</code> unless <code>j- 1 &gt;= 0</code></li>
<li>on the last column <code>j === cols - 1</code>, so we should not check the right neighbour <code>j + 1</code> unless <code>j + 1 &lt; cols</code></li>
</ul>
<p>So, we can rewrite the checks of the <code>isLowPoint</code> function as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isLowPoint = <span class="hljs-function">(<span class="hljs-params">matrix, rows, cols, i, j</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (i - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span> &amp;&amp; matrix[i][j] &gt;= matrix[i - <span class="hljs-number">1</span>][j]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }
  <span class="hljs-keyword">if</span> (i + <span class="hljs-number">1</span> &lt; rows &amp;&amp; matrix[i][j] &gt;= matrix[i + <span class="hljs-number">1</span>][j]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }
  <span class="hljs-keyword">if</span> (j - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span> &amp;&amp; matrix[i][j] &gt;= matrix[i][j - <span class="hljs-number">1</span>]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }
  <span class="hljs-keyword">if</span> (j + <span class="hljs-number">1</span> &lt; cols &amp;&amp; matrix[i][j] &gt;= matrix[i][j + <span class="hljs-number">1</span>]) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
}
</code></pre>
<h3 id="heading-calculate-the-risk-level">Calculate the risk level</h3>
<p>Finally, we can calculate the risk level by adding each newly found low point height and incrementing the total risk level by 1.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> riskLevel = <span class="hljs-number">0</span>

heightMatrix.forEach(<span class="hljs-function">(<span class="hljs-params">row, i</span>) =&gt;</span> {
  row.forEach(<span class="hljs-function">(<span class="hljs-params">height, j</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (isLowPoint(heightMatrix, rows, cols, i, j)) {
      riskLevel += <span class="hljs-number">1</span> + height
    }
  })
})
</code></pre>
<p>The final solution for part one is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-09-smoke-basin/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>The goal of part two is to calculate the size of each basin surrounding a low point. Basins are a group of neighbouring heights delimited by heights of <code>9</code> since <code>9</code> is not part of any basin. We need to multiply the three largest basin sizes to solve the challenge.</p>
<p>I wrote a solution using the following top-down approach:</p>
<ul>
<li>add basin size for each low point into an array</li>
<li>sort the array to find and multiply the three largest basin sizes</li>
<li>create a binary basin map</li>
<li>calculate basin size based on binary basin map</li>
<li>mark basin map recursively</li>
</ul>
<h1 id="heading-add-basin-size-for-each-low-point-into-an-array">Add basin size for each low point into an array</h1>
<p>I adjusted the solution from part one to calculate and add basin size to an array whenever we find a low point.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> basinSizes = []
heightMatrix.forEach(<span class="hljs-function">(<span class="hljs-params">row, i</span>) =&gt;</span> {
  row.forEach(<span class="hljs-function">(<span class="hljs-params">height, j</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (isLowPoint(heightMatrix, rows, cols, i, j)) {
      basinSizes.push(findBasinSize(heightMatrix, rows, cols, i, j))
    }
  })
})
</code></pre>
<p>We can then outline the <code>findBasinSize</code> function like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> findBasinSize = <span class="hljs-function">(<span class="hljs-params">matrix, rows, cols, i, j</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> basinMap = initializeBasinMap(rows, cols)
  markBasin(matrix, basinMap, rows, cols, i, j)
  <span class="hljs-keyword">return</span> calculateBasinSize(basinMap)
}
</code></pre>
<h1 id="heading-sort-the-array-to-find-and-multiply-the-three-largest-basin-sizes">Sort the array to find and multiply the three largest basin sizes</h1>
<p>We can sort the array of basin sizes in descending order to find the three largest sizes. We can then return the product of those sizes.</p>
<pre><code class="lang-js">basinSizes.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> b - a)
<span class="hljs-keyword">return</span> basinSizes[<span class="hljs-number">0</span>] * basinSizes[<span class="hljs-number">1</span>] * basinSizes[<span class="hljs-number">2</span>]
</code></pre>
<h1 id="heading-create-a-binary-basin-map">Create a binary basin map</h1>
<p>The binary basin map is a matrix of the same size as the height matrix. We initialize each element with <code>0</code> and mark the ones belonging to the basin with <code>1</code>. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> initializeBasinMap = <span class="hljs-function">(<span class="hljs-params">rows, cols</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> basinMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(rows)
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> k = <span class="hljs-number">0</span>; k &lt; rows; k++) {
    basinMap[k] = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(cols).fill(<span class="hljs-number">0</span>)
  }
  <span class="hljs-keyword">return</span> basinMap
}
</code></pre>
<h1 id="heading-mark-basin-map-recursively">Mark basin map recursively</h1>
<p>We can write a recursive algorithm that starts from the low point, marks it on the basin map, then traverses all neighbours and marks them on the basin map. The recursion stop condition is when reaching an element with height <code>9</code> or an element already marked on the map.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> markBasin = <span class="hljs-function">(<span class="hljs-params">matrix, basinMap, rows, cols, i, j</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (matrix[i][j] === <span class="hljs-number">9</span> || basinMap[i][j] === <span class="hljs-number">1</span>) {
    <span class="hljs-keyword">return</span>
  }
  basinMap[i][j] = <span class="hljs-number">1</span>

  <span class="hljs-keyword">if</span> (i - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span>) {
    markBasin(matrix, basinMap, rows, cols, i - <span class="hljs-number">1</span>, j)
  }
  <span class="hljs-keyword">if</span> (i + <span class="hljs-number">1</span> &lt; rows) {
    markBasin(matrix, basinMap, rows, cols, i + <span class="hljs-number">1</span>, j)
  }
  <span class="hljs-keyword">if</span> (j - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span>) {
    markBasin(matrix, basinMap, rows, cols, i, j - <span class="hljs-number">1</span>)
  }
  <span class="hljs-keyword">if</span> (j + <span class="hljs-number">1</span> &lt; cols) {
    markBasin(matrix, basinMap, rows, cols, i, j + <span class="hljs-number">1</span>)
  }
}
</code></pre>
<p>The first call contains the low point indices</p>
<pre><code class="lang-js">markBasin(matrix, basinMap, rows, cols, i, j)
</code></pre>
<h1 id="heading-calculate-basin-size-based-on-binary-basin-map">Calculate basin size based on binary basin map</h1>
<p>Once we have marked each height belonging to the current basin map, we can sum all the basin map values to find the basin's size.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> calculateBasinSize = <span class="hljs-function">(<span class="hljs-params">basinMap</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> size = <span class="hljs-number">0</span>
  basinMap.forEach(<span class="hljs-function">(<span class="hljs-params">row</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> {
      size += value
    })
  })
  <span class="hljs-keyword">return</span> size
}
</code></pre>
<p>The final solution for part two is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-09-smoke-basin/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 9 was about traversing a matrix of heights, finding low points by comparing each element to its neighbours in the matrix and recursively finding a basin of adjacent heights.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 8]]></title><description><![CDATA[This blog post is eighth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 8. The challenge was about decoding four-digit numbers represented using a seven-segment display. The difficulty in solvi...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-8</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-8</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Wed, 08 Dec 2021 01:17:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638999437175/W9_e7L4fO.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is eighth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/8">Day 8</a>. The challenge was about decoding four-digit numbers represented using a seven-segment display. The difficulty in solving this problem increased compared to the previous days and I struggled a bit to find the solution in part two. However, this was my favourite challenge so far.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-understanding-the-problem">Understanding the Problem</h2>
<p>The problem is about decoding digits represented using a seven-segment display. Each segment has a name from <code>a</code> to <code>g</code>. By default, if we name the segments in order, the digits from <code>0</code> to <code>9</code> are represented by the segments <code>abcefg</code>, <code>cf</code>, <code>acdeg</code>, <code>acdfg</code>, <code>bcdf</code>, <code>abdfg</code>, <code>abdefg</code>, <code>acf</code>, <code>abcdefg</code> and <code>abcdfg</code> .</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639002311752/0ukKvoV-2.png" alt="SevenSegmentDisplayDigits.png" /></p>
<p>The problem is we don't know which letter corresponds to which segment. We must deduct it from a set of ten unique segment patterns representing digits from 0 to 9 given in random order. For example, given the pattern </p>
<pre><code><span class="hljs-attribute">acedgfb</span> cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab
</code></pre><p>we must find a way to deduce the name of each segment. The segment mapping from the example is illustrated below. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639003452992/m1Dl-mEAl.png" alt="SevenSegmentDisplay.png" /></p>
<p>The pattern from the example represents the following digits:</p>
<pre><code><span class="hljs-attribute">acedgfb</span>: <span class="hljs-number">8</span> <span class="hljs-attribute">cdfbe</span>: <span class="hljs-number">5</span> <span class="hljs-attribute">gcdfa</span>: <span class="hljs-number">2</span> <span class="hljs-attribute">fbcad</span>: <span class="hljs-number">3</span> <span class="hljs-attribute">dab</span>: <span class="hljs-number">7</span> <span class="hljs-attribute">cefabd</span>: <span class="hljs-number">9</span> <span class="hljs-attribute">cdfgeb</span>: <span class="hljs-number">6</span> <span class="hljs-attribute">eafb</span>: <span class="hljs-number">4</span> <span class="hljs-attribute">cagedb</span>: <span class="hljs-number">0</span> <span class="hljs-attribute">ab</span>: <span class="hljs-number">1</span>
</code></pre><h2 id="heading-understanding-the-input">Understanding the Input</h2>
<p>We are given multiple lines, each containing ten unique signal patterns, a delimiter and four output values. For example, </p>
<pre><code><span class="hljs-attribute">acedgfb</span> cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf
</code></pre><h2 id="heading-solving-part-one">Solving Part One</h2>
<p>The goal is to count the number of four-digit output values representing either <code>1</code>, <code>4</code>, <code>7</code> and <code>8</code>. The problem description hints that these digits have a unique number of segments. Indeed only <code>1</code> has two segments,  only <code>4</code> has four segments, only <code>7</code> has three segments and only <code>8</code> has seven segments.</p>
<p>To solve part one we must:</p>
<ul>
<li>read the output values</li>
<li>check if any output value has a unique length</li>
<li>sum all output values with unique length</li>
</ul>
<h3 id="heading-read-the-output-values">Read the output values</h3>
<p>Since we only need the output value for part one, we can extract them from each line using the delimiter <code>|</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> lines = data.split(<span class="hljs-string">'\n'</span>)
<span class="hljs-keyword">const</span> outputValues = lines.map(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> line.split(<span class="hljs-string">' | '</span>)[<span class="hljs-number">1</span>])
</code></pre>
<p>Then to extract each digit into an array we can use the space as separator.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> digits = outputValue.split(<span class="hljs-string">" "</span>)
</code></pre>
<h3 id="heading-check-if-any-output-value-has-a-unique-length">Check if any output value has a unique length</h3>
<p>Since <code>1</code>, <code>4</code>, <code>7</code>, <code>8</code> are represented using <code>2</code>, <code>4</code>, <code>3</code>, <code>7</code> segments respectively, we can check whether the length of the digit is one of those numbers. The <code>includes</code> function is useful for performing this check.</p>
<pre><code class="lang-js">[<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>].includes(digit.length)
</code></pre>
<h3 id="heading-count-all-output-values-with-unique-length">Count all output values with unique length</h3>
<p>We can use the <code>reduce</code> function to count output values respecting the condition previously defined. </p>
<pre><code class="lang-js">digits.reduce(<span class="hljs-function">(<span class="hljs-params">digitCount, digit</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> ([<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>].includes(digit.length)) {
    <span class="hljs-keyword">return</span> digitCount + <span class="hljs-number">1</span>
  }
  <span class="hljs-keyword">return</span> digitCount
}, <span class="hljs-number">0</span>)
</code></pre>
<p>Then, we can use the <code>reduce</code> function again to sum digits from all lines.</p>
<pre><code class="lang-js"><span class="hljs-keyword">return</span> outputValues.reduce(<span class="hljs-function">(<span class="hljs-params">digitCount, outputValue</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> digits = outputValue.split(<span class="hljs-string">" "</span>)

  <span class="hljs-keyword">return</span> digitCount + digits.reduce(<span class="hljs-function">(<span class="hljs-params">count, digit</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span>([<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">7</span>].includes(digit.length)) {
      <span class="hljs-keyword">return</span> count + <span class="hljs-number">1</span>
    }
    <span class="hljs-keyword">return</span> count
  },<span class="hljs-number">0</span>)
}, <span class="hljs-number">0</span>)
</code></pre>
<p>The final solution for part one is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-08-seven-segment-search/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>The second part of the problem was the tricky one. 
The goal of the second part was to decode all output values, from a four-digit number and sum all four-digit numbers.</p>
<p>I used a top-down approach where I wrote higher-level functions first and, thus defined the overall structure of the program, then defined the lower-level functions and went into detail. Here is how I broke down the problem:</p>
<ul>
<li>sum all output numbers</li>
<li>decode output number<ul>
<li>find segment mapping</li>
<li>reveal corresponding digits using segment map</li>
<li>find output value based on revealed digits</li>
</ul>
</li>
</ul>
<p>The trickiest part was finding the segment mapping, in other words, identifying the name of each segment. The strategy was:</p>
<ul>
<li>calculating segment occurrences in all ten unique patterns</li>
<li>identifying the segments with unique occurrences</li>
<li>identifying digits with unique segment length</li>
<li>use a process of elimination </li>
</ul>
<h3 id="heading-sum-all-output-numbers">Sum all output numbers</h3>
<p>We can outline the solution as follows. We define the <code>getOutput</code> function afterwards. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> solve = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> lines = data.split(<span class="hljs-string">'\n'</span>)
  <span class="hljs-keyword">return</span> lines.reduce(<span class="hljs-function">(<span class="hljs-params">sum, line</span>) =&gt;</span> sum + getOutput(line), <span class="hljs-number">0</span>)
}
</code></pre>
<h3 id="heading-decode-output-number">Decode output number</h3>
<p>We can further outline the solution:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getOutput = <span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [segmentPatternsString, outputValuesString] = line.split(<span class="hljs-string">' | '</span>)
  <span class="hljs-keyword">const</span> segmentMap = findSegmentNamesMap(segmentPatternsString)
  <span class="hljs-keyword">const</span> correspondingSevenSegmentDisplay = getSevenSegmentDisplay(segmentMap)

  <span class="hljs-keyword">return</span> getOutputDigits(outputValuesString, correspondingSevenSegmentDisplay)
}
</code></pre>
<p>Let's look at an example line. Given the line </p>
<pre><code><span class="hljs-attribute">acedgfb</span> cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf
</code></pre><p>the <code>segmentPatternsString</code> is </p>
<pre><code><span class="hljs-attribute">acedgfb</span> cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab
</code></pre><p> and <code>outputValuesString</code> is </p>
<pre><code><span class="hljs-attribute">cdfeb</span> fcadb cdfeb cdbaf
</code></pre><p>The <code>findSegmentNamesMap</code> function returns the following mapping:</p>
<pre><code class="lang-js">{
  <span class="hljs-attr">a</span>: <span class="hljs-string">'d'</span>,
  <span class="hljs-attr">b</span>: <span class="hljs-string">'e'</span>,
  <span class="hljs-attr">c</span>: <span class="hljs-string">'a'</span>,
  <span class="hljs-attr">d</span>: <span class="hljs-string">'f'</span>,
  <span class="hljs-attr">e</span>: <span class="hljs-string">'g'</span>,
  <span class="hljs-attr">f</span>: <span class="hljs-string">'b'</span>,
  <span class="hljs-attr">g</span>: <span class="hljs-string">'c'</span>,
}
</code></pre>
<p>The <code>getSevenSegmentDisplay</code> function maps each digit based on the default seven segment display.
So, the default seven-segment display</p>
<pre><code class="lang-js">[ <span class="hljs-string">'abcefg'</span>, <span class="hljs-string">'cf'</span>, <span class="hljs-string">'acdeg'</span>, <span class="hljs-string">'acdfg'</span>, <span class="hljs-string">'bcdf'</span>, <span class="hljs-string">'abdfg'</span>, <span class="hljs-string">'abdefg'</span>, <span class="hljs-string">'acf'</span>, <span class="hljs-string">'abcdefg'</span>, <span class="hljs-string">'abcdfg'</span>]
</code></pre>
<p>becomes the following based on the segment names map</p>
<pre><code class="lang-js">[<span class="hljs-string">'abcdeg'</span>, <span class="hljs-string">'ab'</span>, <span class="hljs-string">'acdfg'</span>, <span class="hljs-string">'abcdf'</span>, <span class="hljs-string">'abef'</span>, <span class="hljs-string">'bcdef'</span>, <span class="hljs-string">'bcdefg'</span>, <span class="hljs-string">'abd'</span>, <span class="hljs-string">'abcdefg'</span>, <span class="hljs-string">'abcdef'</span>]
</code></pre>
<p>Notice the letters are sorted alphabetically. This makes identifying the output digits easier.
The <code>getOutputDigits</code> maps the <code>outputValuesString</code> to <code>5353</code>.</p>
<h3 id="heading-find-segment-mapping">Find segment mapping</h3>
<p>We can start by initializing the segment name map:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> findSegmentNamesMap = <span class="hljs-function">(<span class="hljs-params">segmentPatternsString</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> segmentMap = { <span class="hljs-attr">a</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">b</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">c</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">d</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">e</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">f</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">g</span>: <span class="hljs-string">''</span> }

  <span class="hljs-keyword">return</span> segmentMap
}
</code></pre>
<h4 id="heading-identifying-the-segments-with-unique-occurrences">Identifying the segments with unique occurrences</h4>
<p>Using the default segment names we have the digits from <code>0</code> to <code>9</code> represented as:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sevenSegmentDisplay = [ <span class="hljs-string">'abcefg'</span>, <span class="hljs-string">'cf'</span>, <span class="hljs-string">'acdeg'</span>, <span class="hljs-string">'acdfg'</span>, <span class="hljs-string">'bcdf'</span>, <span class="hljs-string">'abdfg'</span>, <span class="hljs-string">'abdefg'</span>, <span class="hljs-string">'acf'</span>, <span class="hljs-string">'abcdefg'</span>, <span class="hljs-string">'abcdfg'</span>]
</code></pre>
<p>and each letter occurs as follows</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> abcdefgOccurence = { <span class="hljs-attr">a</span>: <span class="hljs-number">8</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">6</span>, <span class="hljs-attr">c</span>: <span class="hljs-number">8</span>, <span class="hljs-attr">d</span>: <span class="hljs-number">7</span>, <span class="hljs-attr">e</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">f</span>: <span class="hljs-number">9</span>, <span class="hljs-attr">g</span>: <span class="hljs-number">7</span> }
</code></pre>
<p>Thus, the <code>b</code>, <code>e</code> and <code>f</code> segments occur a unique number of times. We can use this information to determine the segment name mapping for these values.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> findSegmentNamesMap = <span class="hljs-function">(<span class="hljs-params">segmentPatternsString</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> segmentMap = { <span class="hljs-attr">a</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">b</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">c</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">d</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">e</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">f</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">g</span>: <span class="hljs-string">''</span> }

  <span class="hljs-keyword">const</span> letterOccurence = calculateLetterOccurence(segmentPatternsString)
  segmentMap.b = findLetter(letterOccurence, abcdefgOccurence.b)
  segmentMap.e = findLetter(letterOccurence, abcdefgOccurence.e)
  segmentMap.f = findLetter(letterOccurence, abcdefgOccurence.f)

  <span class="hljs-keyword">return</span> segmentMap
}
</code></pre>
<h4 id="heading-identifying-segments-based-on-digits-with-unique-segment-length">Identifying segments based on digits with unique segment length</h4>
<p>Part one hinted at using the length of digits. We can deduce <code>a</code>, <code>c</code> and <code>d</code>.</p>
<p>To find the segment corresponding to <code>a</code>, we can identify numbers <code>1</code> and <code>7</code> in the <code>segmentPatternsString</code>. We are looking for the letter not present in <code>1</code>. For example, given <code>ab</code> and <code>abd</code> we can determine that <code>d</code> is the name corresponding to segment <code>a</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> findA = <span class="hljs-function">(<span class="hljs-params">segmentPatternsString</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> one = findDigitBySignalsLength(segmentPatternsString, <span class="hljs-number">2</span>)
  <span class="hljs-keyword">const</span> seven = findDigitBySignalsLength(segmentPatternsString, <span class="hljs-number">3</span>)

  <span class="hljs-keyword">let</span> a = seven
  one.split(<span class="hljs-string">''</span>).forEach(<span class="hljs-function">(<span class="hljs-params">letter</span>) =&gt;</span> {
    a = a.replace(letter, <span class="hljs-string">''</span>)
  })
  <span class="hljs-keyword">return</span> a
}
</code></pre>
<p>To find the segment corresponding to <code>c</code>, we can identify the number <code>1</code> in the <code>segmentPatternsString</code> and eliminate the previously found segment corresponding to <code>f</code>.  For example, given <code>ab</code> and the previously found <code>b</code> corresponding to <code>f</code>, we can deduce that <code>a</code> is the name corresponding to <code>c</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> findC = <span class="hljs-function">(<span class="hljs-params">segmentPatternsString, letterF</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> one = segmentPatternsString
    .split(<span class="hljs-string">' '</span>)
    .find(<span class="hljs-function">(<span class="hljs-params">digit</span>) =&gt;</span> digit.length === <span class="hljs-number">2</span>)
  <span class="hljs-keyword">return</span> one.replace(letterF, <span class="hljs-string">''</span>)
}
</code></pre>
<p>To find the segment corresponding to <code>d</code>, we can identify the number<code>4</code> in the <code>segmentPatternsString</code> and eliminate the previously found segment corresponding to <code>b</code>, <code>c</code> and <code>f</code>.  For example, given <code>eafb</code>, and the previously found <code>e</code> corresponding to <code>b</code>, <code>a</code> corresponding to <code>c</code> and <code>b</code> corresponding to <code>f</code>, we can deduce that <code>f</code> is the name corresponding to <code>d</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> findD = <span class="hljs-function">(<span class="hljs-params">segmentPatternsString, signalMap</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> four = findDigitBySignalsLength(segmentPatternsString, <span class="hljs-number">4</span>)
  <span class="hljs-keyword">return</span> four
    .replace(signalMap.b, <span class="hljs-string">''</span>)
    .replace(signalMap.c, <span class="hljs-string">''</span>)
    .replace(signalMap.f, <span class="hljs-string">''</span>)
}
</code></pre>
<h4 id="heading-use-a-process-of-elimination">Use a process of elimination</h4>
<p>After mapping <code>a</code>, <code>b</code>, <code>c</code>, <code>d</code>, <code>e</code> and <code>f</code>, we can determine the segment corresponding to <code>g</code> by process of elimination.</p>
<pre><code>const findG <span class="hljs-operator">=</span> (signalMap) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  let allLetters <span class="hljs-operator">=</span> <span class="hljs-string">'abcdefg'</span>
  Object.keys(signalMap).forEach(
    (key) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> (allLetters <span class="hljs-operator">=</span> allLetters.replace(signalMap[key], <span class="hljs-string">''</span>))
  )
  <span class="hljs-keyword">return</span> allLetters
}
</code></pre><p>The final solution for part two is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-08-seven-segment-search/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 8 was really challenging and entailed decoding numbers by identifying unique occurrences, segment lengths and by process of elimination.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 7]]></title><description><![CDATA[This blog post is seventh in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 7. Given many horizontal positions for submarines navigated by crabs, we must align them using the least amount of fuel....]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-7</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-7</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[learning]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Tue, 07 Dec 2021 07:24:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638857369842/sozCubMCf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is seventh in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/7">Day 7</a>. Given many horizontal positions for submarines navigated by crabs, we must align them using the least amount of fuel. Yes, it is another entertaining story!</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>The alignment position must be between the minimum and maximum horizontal submarine positions. We can then calculate the needed fuel for each alignment position between these thresholds. </p>
<p>We can break down the solution as follows:</p>
<ul>
<li>read positions from input</li>
<li>find the minimum and maximum positions</li>
<li>calculate the fuel corresponding to each alignment</li>
<li>find the minimum fuel</li>
</ul>
<h3 id="heading-read-positions-from-input">Read positions from input</h3>
<p>The <code>readInput</code> function created on <a target="_blank" href="https://blog.cristiana.tech/advent-of-code-2021-day-1">Day 1</a> is useful for getting the file <code>data</code> as string. We can then map this data to a number array. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> positions = data.split(<span class="hljs-string">','</span>).map(<span class="hljs-function">(<span class="hljs-params">n</span>) =&gt;</span> <span class="hljs-built_in">Number</span>(n))
</code></pre>
<h3 id="heading-find-the-minimum-and-maximum-positions">Find the minimum and maximum positions</h3>
<p>Since solving Advent of Code challenges, I have noticed the <code>reduce</code> function is very handy for many calculations based on elements in an array. Finding the minimum and maximum number in an array is one of those cases. I also relied on <code>Math.min</code> and <code>Math.max</code> to avoid writing conditional statements, thus additional lines of code. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [minAlignPos, maxAlignPos] = positions.reduce(
  <span class="hljs-function">(<span class="hljs-params">[min, max], pos</span>) =&gt;</span> [<span class="hljs-built_in">Math</span>.min(min, pos), <span class="hljs-built_in">Math</span>.max(max, pos)],
  [positions[<span class="hljs-number">0</span>], positions[<span class="hljs-number">0</span>]]
)
</code></pre>
<h3 id="heading-calculate-the-fuel-corresponding-to-each-alignment">Calculate the fuel corresponding to each alignment</h3>
<p>We can iterate through each alignment between the maximum and minimum positions using a for loop.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> alignPos = minAlignPos; alignPos &lt;= maxAlignPos; alignPos++) {
  <span class="hljs-keyword">const</span> fuel = calculateFuel(positions, alignPos)
}
</code></pre>
<p>We can use the reduce function again to calculate the fuel required for aligning all positions. We must sum the differences between each position and the alignment position.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> calculateFuel = <span class="hljs-function">(<span class="hljs-params">positions, alignPos</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> positions.reduce(<span class="hljs-function">(<span class="hljs-params">fuel, pos</span>) =&gt;</span> fuel + <span class="hljs-built_in">Math</span>.abs(pos - alignPos), <span class="hljs-number">0</span>)
}
</code></pre>
<h3 id="heading-find-the-minimum-fuel">Find the minimum fuel</h3>
<p>After calculating the fuel for each alignment, we can determine the minimum fuel needed by comparing each fuel amount with the <code>minFuel</code> variable and updating it accordingly.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> minFuel

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> alignPos = minAlignPos; alignPos &lt;= maxAlignPos; alignPos++) {
  <span class="hljs-keyword">const</span> fuel = calculateFuel(positions, alignPos)
  <span class="hljs-keyword">if</span> (!minFuel || fuel &lt; minFuel) {
    minFuel = fuel
  }
}

<span class="hljs-keyword">return</span> minFuel
</code></pre>
<p>The final solution for part one is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-07-the-treachery-of-whales/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>In part two, the problem describes a different way of calculating the fuel. Instead of a constant amount of fuel, the required fuel increases with 1 unit each step. Thus, aligning <code>n</code> steps would require <code>1 + 2 + 3 + ... + n</code> amount of fuel. We can use Gauss's summation and calculate the steps as follows <code>n * ( n + 1 ) / 2</code>.</p>
<pre><code>const calculateFuelForSteps <span class="hljs-operator">=</span> (n) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> (n <span class="hljs-operator">*</span> (n <span class="hljs-operator">+</span> <span class="hljs-number">1</span>)) <span class="hljs-operator">/</span> <span class="hljs-number">2</span>

const calculateFuel <span class="hljs-operator">=</span> (positions, alignPos) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  <span class="hljs-keyword">return</span> positions.reduce(
    (fuel, pos) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> fuel <span class="hljs-operator">+</span> calculateFuelForSteps(Math.abs(pos <span class="hljs-operator">-</span> alignPos)),
    <span class="hljs-number">0</span>
  )
}
</code></pre><p>The final solution for part two is in my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-07-the-treachery-of-whales/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We found the most fuel-efficient way of aligning a set of crab submarines given their horizontal positions. I had fun reading and solving the challenge of Day 7 and am looking forward to Day 8!</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 6]]></title><description><![CDATA[This blog post is sixth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 6. The challenge was creating and optimizing an algorithm for calculating the lanternfish population after a number of day...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-6</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-6</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Mon, 06 Dec 2021 18:43:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638698321376/Kbvl1v5qu.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is sixth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/6">Day 6</a>. The challenge was creating and optimizing an algorithm for calculating the lanternfish population after a number of days.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>We have an initial set of fish with given internal times until they multiply. 
According to the problem, after creating a new fish, each fish resets their internal time to 6 days since they need a week to make a new fish. A new fish starts with an internal time of 9 days until multiplying the first time. The challenge is to calculate the amount of fish after 80 days.</p>
<p>We can solve the problem with the following steps:</p>
<ul>
<li>read the input</li>
<li>update the state of each fish after a day</li>
<li>add new fish</li>
<li>repeat for 80 days and count fish</li>
</ul>
<h3 id="heading-read-the-input">Read the input</h3>
<p>The input contains comma-separated numbers, which represent the state of each fish. 
We can use an array to store each fish as a number.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> fish = data.split(<span class="hljs-string">','</span>).map(<span class="hljs-function">(<span class="hljs-params">n</span>) =&gt;</span> <span class="hljs-built_in">Number</span>(n))
</code></pre>
<h3 id="heading-update-the-state-of-each-fish-after-a-day">Update the state of each fish after a day</h3>
<p>Without considering new fish for now, after a day, each fish's internal time decreases by one until it reaches 0, at which point it resets to 6.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> newFishPopulation = fish.map(<span class="hljs-function">(<span class="hljs-params">f</span>) =&gt;</span> 
{
  <span class="hljs-keyword">if</span> (f === <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-number">6</span>
  }
  <span class="hljs-keyword">return</span> f - <span class="hljs-number">1</span>
})
</code></pre>
<h3 id="heading-add-new-fish">Add new fish</h3>
<p>We can count the amount of fish that reset to 6 and add that amount to the list of new fish population.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getNewFishPopulation = <span class="hljs-function">(<span class="hljs-params">fish</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> newFishCount = <span class="hljs-number">0</span>
  <span class="hljs-keyword">const</span> newFishPopulation = fish.map(<span class="hljs-function">(<span class="hljs-params">f</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (f === <span class="hljs-number">0</span>) {
      newFishCount++
      <span class="hljs-keyword">return</span> <span class="hljs-number">6</span>
    }
    <span class="hljs-keyword">return</span> f - <span class="hljs-number">1</span>
  })
  newFishPopulation.push(...Array(newFishCount).fill(<span class="hljs-number">8</span>))
  <span class="hljs-keyword">return</span> newFishPopulation
}
</code></pre>
<h3 id="heading-repeat-for-80-days-and-count-fish">Repeat for 80 days and count fish</h3>
<p>The challenge is to find the amount of fish after 80 days, so we can write a for loop which would update the fish array every day.</p>
<pre><code class="lang-js"> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> day = <span class="hljs-number">1</span>; day &lt;= <span class="hljs-number">80</span>; day++) {
  fish = getNewFishPopulation(fish)
 }
 <span class="hljs-keyword">return</span> fish.length
</code></pre>
<p>You can see the final solution for part one on my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-06-lanternfish/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>Part two is about optimizing the algorithm to calculate the fish population after 256 days. The solution from part one is not efficient in terms of memory. It exceeds the maximum number of elements allowed in an array, thus throwing the following range error.</p>
<pre><code>fish.<span class="hljs-built_in">push</span>(...Array(newFishCount).fill(<span class="hljs-number">8</span>))
         <span class="hljs-operator">^</span>
RangeError: Maximum call stack size exceeded
</code></pre><p>While thinking about this problem, it occurred to me that fish with the same state produces the same amount of ancestors. For example, two fishes left with three days until reproduction create the same amount of ancestors after 80 or any amount of days. 
Thus, it would be enough to keep track of the amount of fish in a given state each day. So I opted for an occurrence array with nine elements, where each index represents the state of days until reproduction and stores the amount of fish with that corresponding state.</p>
<p>We can break the problem like this:</p>
<ul>
<li>initialize occurrence array from input</li>
<li>shift occurrence array one position</li>
<li>add fish corresponding to state 6</li>
<li>add new fish</li>
<li>repeat for 256 days and count fish</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { URL, fileURLToPath } <span class="hljs-keyword">from</span> <span class="hljs-string">'url'</span>
<span class="hljs-keyword">import</span> { readInput } <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/readInput.js'</span>

<span class="hljs-keyword">const</span> sumFish = <span class="hljs-function">(<span class="hljs-params">occurenceArray</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> occurenceArray.reduce(<span class="hljs-function">(<span class="hljs-params">sum, fishCount</span>) =&gt;</span> sum + fishCount, <span class="hljs-number">0</span>)
}

<span class="hljs-keyword">const</span> solve = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> fish = data.split(<span class="hljs-string">','</span>).map(<span class="hljs-function">(<span class="hljs-params">n</span>) =&gt;</span> <span class="hljs-built_in">Number</span>(n))
  <span class="hljs-keyword">const</span> fishOccurence = <span class="hljs-built_in">Array</span>(<span class="hljs-number">9</span>).fill(<span class="hljs-number">0</span>)

  fish.forEach(<span class="hljs-function">(<span class="hljs-params">f</span>) =&gt;</span> fishOccurence[f]++)

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> day = <span class="hljs-number">1</span>; day &lt;= <span class="hljs-number">256</span>; day++) {
    <span class="hljs-keyword">const</span> newFishCount = fishOccurence.shift()
    fishOccurence[<span class="hljs-number">6</span>] += newFishCount
    fishOccurence.push(newFishCount)
  }
  <span class="hljs-keyword">return</span> sumFish(fishOccurence)
}

<span class="hljs-keyword">const</span> inputPath = fileURLToPath(<span class="hljs-keyword">new</span> URL(<span class="hljs-string">'./input.txt'</span>, <span class="hljs-keyword">import</span>.meta.url))

<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> readInput(inputPath)

<span class="hljs-built_in">console</span>.log(solve(data))
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 6 offered a challenge in terms of optimizing an algorithm. Although it stored duplicate elements, a simple solution worked well for part one. However, part two required using an occurrence array instead.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 5]]></title><description><![CDATA[This blog post is fifth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 5. The challenges were about finding overlapping points given a set of lines.
All solutions are in this GitHub repository....]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-5</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-5</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Sun, 05 Dec 2021 11:23:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638698266264/27bqUZEGy.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is fifth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/5">Day 5</a>. The challenges were about finding overlapping points given a set of lines.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>The input contains a set of lines defined using x, y coordinates of two points in the following format <code>x1,y1 =&gt; x2,y2</code>. The goal is to find how many points consisting of integer coordinates overlap. The first part requires only checking points overlapping horizontal or vertical lines.</p>
<p>We can break the problem as follows:</p>
<ul>
<li>read lines from the input file</li>
<li>find vertical and horizontal lines</li>
<li>store points in a hash map</li>
<li>count overlapping points</li>
</ul>
<h3 id="heading-read-lines-from-the-input-file">Read lines from the input file</h3>
<p>We can reuse the <code>readInput</code> function written on Day 1. If you haven't already, give <a target="_blank" href="https://blog.cristiana.tech/advent-of-code-2021-day-1">Advent of Code: Day 1</a> a read!
After extracting the data as a string, we split it into lines using the newline separator. Then, we map each line to an array containing the coordinates as numbers. So the line <code>x1,y1 -&gt; x2,y2</code> is mapped to <code>[x1, y1, x2, y2]</code></p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> lines = data.split(<span class="hljs-string">'\n'</span>).map(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span>
  line
    .replace(<span class="hljs-string">' -&gt; '</span>, <span class="hljs-string">','</span>)
    .split(<span class="hljs-string">','</span>)
    .map(<span class="hljs-function">(<span class="hljs-params">n</span>) =&gt;</span> <span class="hljs-built_in">Number</span>(n))
)
</code></pre>
<h3 id="heading-find-vertical-and-horizontal-lines">Find vertical and horizontal lines</h3>
<p>We can then iterate through the lines and destructure the coordinates.</p>
<pre><code class="lang-js">lines.forEach(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [x1, y1, x2, y2] = line

})
</code></pre>
<p>We must only consider points from vertical or horizontal lines in the first part of the problem. Vertical lines have the exact x coordinates, whereas horizontal lines have the same y coordinates.</p>
<pre><code>const isVertical <span class="hljs-operator">=</span> x1 <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> x2
const isHorizontal <span class="hljs-operator">=</span> y1 <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> y2
</code></pre><p>We can find the points on a vertical line using either x1 or x2 coordinate and all numbers between y1 and y2. Since we don't know which one is higher, we can calculate the minimum and maximum using <code>Math.min(y1, y2)</code> and <code>Math.max(y1, y2)</code> respectively. Then, using a for loop we can determine all integer values from the minimum to the maximum value. </p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (isVertical) {
  <span class="hljs-keyword">const</span> minY = <span class="hljs-built_in">Math</span>.min(y1, y2)
  <span class="hljs-keyword">const</span> maxY = <span class="hljs-built_in">Math</span>.max(y1, y2)
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> y = minY; y &lt;= maxY; y++) {
    addPointToHashMap(pointHashMap, x1, y)
  }
}
</code></pre>
<p>Using the same approach, we can determine the points on horizontal lines.</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (isHorizontal) {
  <span class="hljs-keyword">const</span> minX = <span class="hljs-built_in">Math</span>.min(x1, x2)
  <span class="hljs-keyword">const</span> maxX = <span class="hljs-built_in">Math</span>.max(x1, x2)
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = minX; x &lt;= maxX; x++) {
    addPointToHashMap(pointHashMap, x, y1)
  }
}
</code></pre>
<h3 id="heading-store-points-in-a-hash-map">Store points in a hash map</h3>
<p>Since the problem does not define maximum coordinate value, storing the points using a two-dimensional matrix is not the most efficient memory-wise. Instead, I opted for a hash map where keys are strings in <code>x,y</code> format and values are the number of overlapping points.</p>
<p>We initialize the point hash map with an empty object.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pointHashMap = {}
</code></pre>
<p>Then, we create new keys and initialize them with 1 when we find a new point, or increase the value of that point when the point already exists in the map.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> addPointToHashMap = <span class="hljs-function">(<span class="hljs-params">hashMap, x, y</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> key = <span class="hljs-string">`<span class="hljs-subst">${x}</span>,<span class="hljs-subst">${y}</span>`</span>
  <span class="hljs-keyword">if</span> (hashMap[key]) {
    hashMap[key]++
  } <span class="hljs-keyword">else</span> {
    hashMap[key] = <span class="hljs-number">1</span>
  }
}
</code></pre>
<h3 id="heading-count-overlapping-points">Count overlapping points</h3>
<p>Finally, we need to count overlapping points, in other words, points with a value larger than <code>2</code>.</p>
<p>The <code>Object.keys(hashMap)</code> function gives an iterable array of the points. We can then use the <code>Array.reduce</code> function to calculate the total amount of overlapping points.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> countOverlappingPoints = <span class="hljs-function">(<span class="hljs-params">hashMap</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> points = <span class="hljs-built_in">Object</span>.keys(hashMap)
  <span class="hljs-keyword">return</span> points.reduce(<span class="hljs-function">(<span class="hljs-params">total, point</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (hashMap[point] &gt; <span class="hljs-number">1</span>) {
      <span class="hljs-keyword">return</span> total + <span class="hljs-number">1</span>
    }
    <span class="hljs-keyword">return</span> total
  }, <span class="hljs-number">0</span>)
}
</code></pre>
<p>We call the function with the previously defined <code>pointHashMap</code>.</p>
<pre><code class="lang-js">countOverlappingPoints(pointHashMap)
</code></pre>
<p>You can see the final solution for part one on my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-05-hydrothermal-venture/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>In part two, we must consider all lines. Fortunately, the problem gives an input constraint where all lines are horizontal, vertical or diagonal at precisely 45 degrees.</p>
<p>We can reuse most of the solution from part one, with the following additions:</p>
<ul>
<li>find diagonal lines</li>
<li>find the points on diagonal lines</li>
</ul>
<h3 id="heading-find-diagonal-lines">Find diagonal lines</h3>
<p>Given the input constraint, all lines that are not horizontal neither vertical must be diagonal.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isDiagonal = !isHorizontal &amp;&amp; !isVertical
</code></pre>
<h3 id="heading-find-the-points-on-diagonal-lines">Find the points on diagonal lines</h3>
<p>According to the problem, </p>
<blockquote>
<p>An entry like 1,1 -&gt; 3,3 covers points 1,1, 2,2, and 3,3.
An entry like 9,7 -&gt; 7,9 covers points 9,7, 8,8, and 7,9.</p>
</blockquote>
<p>So if we get the ranges of numbers between each coordinate <code>x1 -&gt; x2</code> and <code>y1 -&gt; y2</code>, we can determine the points on the diagonals.</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (isDiagonal) {
  <span class="hljs-keyword">const</span> xRange = range(x1, x2)
  <span class="hljs-keyword">const</span> yRange = range(y1, y2)
  xRange.forEach(<span class="hljs-function">(<span class="hljs-params">x, index</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> y = yRange[index]
    addPointToHashMap(pointHashMap, x, y)
  })
}
</code></pre>
<p>Given two x or y coordinates (e.g. <code>x1 = 9</code>, <code>x2 = 7</code>), we can generate an array of steps (e.g. <code>0, 1, 2</code>) corresponding to each number in the range. Then depending on whether coordinates increase or decrease, we can build the range as follows. For example, the coordinates <code>x1 = 9</code> and <code>x2 = 7</code> decrease. Thus, we decrease the number with each step (<code>c1 - p</code>).</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> range = <span class="hljs-function">(<span class="hljs-params">c1, c2</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> pointsCount = <span class="hljs-built_in">Math</span>.abs(c1 - c2) + <span class="hljs-number">1</span>
  <span class="hljs-keyword">return</span> [...Array(pointsCount).keys()].map(<span class="hljs-function">(<span class="hljs-params">p</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (c1 &lt; c2) {
      <span class="hljs-keyword">return</span> c1 + p
    }
    <span class="hljs-keyword">return</span> c1 - p
  })
}
</code></pre>
<p>You can see the final solution for part two on my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-05-hydrothermal-venture/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 5 was about finding overlapping points from a set of given lines. A hash map helped store points and determine how many lines overlap.  JavaScript functions like <code>Math.abs</code>, <code>Math.min</code>, <code>Math.max</code> as well as <code>Object.keys</code> and <code>Array.reduce</code> were quite handy.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 4]]></title><description><![CDATA[This blog post is fourth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 4. The stories never stop surprising me. This one, in particular, is about playing bingo with a giant squid! Consider me ...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-4</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-4</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Sat, 04 Dec 2021 14:29:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638617558288/jOs-IVjxcY.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is fourth in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/4">Day 4</a>. The stories never stop surprising me. This one, in particular, is about playing bingo with a giant squid! Consider me entertained 😎</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>We need to find the first winning bingo board and calculate the board's score. A winning bingo board contains an entire row or column of extracted random numbers.</p>
<p>The strategy of breaking down the problem into smaller, more manageable chunks worked well for day 3, so let's explore the steps for solving the fourth challenge:</p>
<ul>
<li>read the input file</li>
<li>mark bingo numbers on each board</li>
<li>check if a row is complete</li>
<li>check if a column is complete</li>
<li>calculate the score</li>
</ul>
<h3 id="heading-read-the-input-file">Read the input file</h3>
<p>The input contains the extracted random numbers on the first line, followed by 5 x 5 boards of numbers separated by empty lines.  We can extract the bingo numbers and boards as strings using the double Newline separator.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [bingoNumbersAsString, ...boardsAsString] = data.split(<span class="hljs-string">'\n\n'</span>)
</code></pre>
<p>We can extract the array of bingo numbers by using the <code>,</code> as a separator and parsing each number.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bingoNumbers = bingoNumbersAsString
    .split(<span class="hljs-string">','</span>)
    .map(<span class="hljs-function">(<span class="hljs-params">numberAsString</span>) =&gt;</span> <span class="hljs-built_in">Number</span>(numberAsString))
</code></pre>
<p>Next, we must store board numbers in a data structure. I opted to keep each board as an array of 25 objects containing the number and a <code>marked</code> boolean. </p>
<pre><code class="lang-js">{
  <span class="hljs-attr">number</span>: <span class="hljs-number">4</span>,
  <span class="hljs-attr">marked</span>: <span class="hljs-literal">false</span>,
}
</code></pre>
<p>The <code>marked</code> property is set to <code>false</code> by default and <code>true</code> whenever the number matches the played bingo number. A matrix with objects of the same structure would have worked well too. However, I thought it would be easier to traverse an array to find the matching bingo number rather than a matrix.</p>
<p>Here is the mapping of the input to the desired data structure.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> boards = boardsAsString.map(<span class="hljs-function">(<span class="hljs-params">boardAsString</span>) =&gt;</span>
  boardAsString
    .replaceAll(<span class="hljs-string">'\n'</span>, <span class="hljs-string">' '</span>)
    .split(<span class="hljs-string">' '</span>)
    .filter(<span class="hljs-built_in">Boolean</span>)
    .map(<span class="hljs-function">(<span class="hljs-params">numberAsString</span>) =&gt;</span> ({
      <span class="hljs-attr">number</span>: <span class="hljs-built_in">Number</span>(numberAsString),
      <span class="hljs-attr">marked</span>: <span class="hljs-literal">false</span>,
    }))
)
</code></pre>
<p>All new lines are concatenated separated by a space using <code>.replaceAll('\n', ' ')</code>, then <code>.split(' ')</code> creates an array using the space character as a separator. Since some of the numbers have additional spaces, some of the items in the array are empty strings.  The <code>.filter(Boolean)</code> function removes all the empty strings from the array. Finally, each number is parsed and mapped into the data structure.</p>
<h3 id="heading-mark-bingo-numbers-on-each-board">Mark bingo numbers on each board</h3>
<p>We can use the <code>forEach</code> function to iterate through bingo numbers and boards. However, <code>forEach</code> goes through all elements, whereas we should stop whenever we find a winning board. The <code>some</code> function returns true when finding a winning board.</p>
<pre><code class="lang-js">bingoNumbers.some(<span class="hljs-function">(<span class="hljs-params">bingoNumber</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> boards.some(<span class="hljs-function">(<span class="hljs-params">board</span>) =&gt;</span> {
      <span class="hljs-comment">// mark the bingo number on the board</span>
      <span class="hljs-comment">// determine if it is a winning board</span>
      <span class="hljs-keyword">return</span> isWinner
    })
</code></pre>
<p>To find and mark the bingo number on a board we can use the <code>find</code> function and set the marked property to <code>true</code> when the board contains the number.</p>
<pre><code class="lang-js">bingoNumbers.some(<span class="hljs-function">(<span class="hljs-params">bingoNumber</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> boards.some(<span class="hljs-function">(<span class="hljs-params">board</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> bingoNumberOnBoard = board.find(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.number === bingoNumber)
      <span class="hljs-keyword">if</span> (!bingoNumberOnBoard) {
        <span class="hljs-keyword">return</span>
      }
      bingoNumberOnBoard.marked = <span class="hljs-literal">true</span>
      <span class="hljs-comment">// determine if it is a winning board</span>
      <span class="hljs-keyword">return</span> isWinner
    })
</code></pre>
<p>To determine whether the board is winning, we must check if the row or column of the marked number is now complete. Both checks require the index of the <code>bingoNumberOnBoard</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bingoNumberIndexOnBoard = board.findIndex(item) =&gt; item === bingoNumberOnBoard)
</code></pre>
<h3 id="heading-check-if-a-row-is-complete">Check if a row is complete</h3>
<p>Given that each board is 5 x 5, we can use the index of the bingo number in the array to determine indices of the elements of the row. 
Each board has the following indices:</p>
<pre><code> <span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">2</span>  <span class="hljs-number">3</span>  <span class="hljs-number">4</span>
 <span class="hljs-number">5</span>  <span class="hljs-number">6</span>  <span class="hljs-number">7</span>  <span class="hljs-number">8</span>  <span class="hljs-number">9</span>
<span class="hljs-number">10</span> <span class="hljs-number">11</span> <span class="hljs-number">12</span> <span class="hljs-number">13</span> <span class="hljs-number">14</span>
<span class="hljs-number">15</span> <span class="hljs-number">16</span> <span class="hljs-number">17</span> <span class="hljs-number">18</span> <span class="hljs-number">19</span>
<span class="hljs-number">20</span> <span class="hljs-number">21</span> <span class="hljs-number">22</span> <span class="hljs-number">23</span> <span class="hljs-number">24</span>
</code></pre><p>We can determine the indices of the row of the bingo number with the formula <code>rowIndex * 5 + columnIndex</code>. The <code>rowIndex</code> is the quotient of the bingo number index divided by <code>5</code> and the column indices are always <code>0</code>, <code>1</code>, <code>2</code>, <code>3</code>, <code>4</code> . For example, for  the index 13, the row index is <code>13 ÷ 5</code> which is <code>2</code>, thus the indices are <code>2 * 5 + 0</code> (<code>10</code>), <code>2 * 5 + 1</code> (<code>11</code>), <code>2 * 5 + 2</code> (<code>12</code>), <code>2 * 5 + 3</code> (<code>13</code>) and <code>2 * 5 + 4</code> (<code>14</code>).</p>
<p>Then, we only need to count how many marked elements there are on the row and return <code>true</code> if there are <code>5</code> marked elements and <code>false</code> otherwise.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> checkRow = <span class="hljs-function">(<span class="hljs-params">board, bingoNumberIndexOnBoard</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> rowIndex = <span class="hljs-built_in">Math</span>.floor(bingoNumberIndexOnBoard / <span class="hljs-number">5</span>)
  <span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">markedTotal, columnIndex</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> boardIndex = rowIndex * <span class="hljs-number">5</span> + columnIndex
    <span class="hljs-keyword">if</span> (board[boardIndex].marked) {
      <span class="hljs-keyword">return</span> markedTotal + <span class="hljs-number">1</span>
    }
    <span class="hljs-keyword">return</span> markedTotal
  }
  <span class="hljs-keyword">const</span> markedTotal = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>].reduce(reducer, <span class="hljs-number">0</span>)
  <span class="hljs-keyword">return</span> markedTotal === <span class="hljs-number">5</span>
}
</code></pre>
<p>In the <code>solve</code> function we can call the <code>checkRow</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isRow = checkRow(board, bingoNumberIndexOnBoard)
</code></pre>
<h3 id="heading-check-if-a-column-is-complete">Check if a column is complete</h3>
<p>The column check is calculated in a similar manner to the row, except we determine the indices slightly differently. The row indices are always <code>0</code>, <code>1</code>, <code>2</code>, <code>3</code>, <code>4</code> and the column index is the remainder of the bingo number index divided by <code>5</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> checkColumn = <span class="hljs-function">(<span class="hljs-params">board, bingoNumberIndexOnBoard</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> columnIndex = bingoNumberIndexOnBoard % <span class="hljs-number">5</span>
  <span class="hljs-keyword">const</span> reducer = <span class="hljs-function">(<span class="hljs-params">markedTotal, rowIndex</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> boardIndex = rowIndex * <span class="hljs-number">5</span> + columnIndex
    <span class="hljs-keyword">if</span> (board[boardIndex].marked) {
      <span class="hljs-keyword">return</span> markedTotal + <span class="hljs-number">1</span>
    }
    <span class="hljs-keyword">return</span> markedTotal
  }
  <span class="hljs-keyword">const</span> markedTotal = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>].reduce(reducer, <span class="hljs-number">0</span>)
  <span class="hljs-keyword">return</span> markedTotal === <span class="hljs-number">5</span>
}
</code></pre>
<p>In the <code>solve</code> function we can call the <code>checkColumn</code> function like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isColumn = checkColumn(board, bingoNumberIndexOnBoard)
</code></pre>
<h3 id="heading-calculate-the-score">Calculate the score</h3>
<p>The score is calculated by summing all the unmarked numbers and multiplying the sum with the bingo number. We can use the <code>reduce</code> function as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> calculateScore = <span class="hljs-function">(<span class="hljs-params">board, bingoNumber</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> boardScore = board.reduce(<span class="hljs-function">(<span class="hljs-params">boardScore, item</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (item.marked) {
      <span class="hljs-keyword">return</span> boardScore
    }
    <span class="hljs-keyword">return</span> boardScore + item.number
  }, <span class="hljs-number">0</span>)
  <span class="hljs-keyword">return</span> boardScore * bingoNumber
}
</code></pre>
<p>In the <code>solve</code> function we can call the <code>calculateScore</code> function if we found a winning board:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> isWinner = isRow || isColumn
<span class="hljs-keyword">if</span> (isWinner) {
  score = calculateScore(board, bingoNumber)
}
</code></pre>
<p>You can see the final solution for part one on my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-04-giant-squid/one.js">GitHub repository</a>.</p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>We need to find the last winning bingo board. We can reuse most of the code defined in part one, such as reading input, checking whether a row or column is complete and calculating the score.</p>
<p>Here is how we could break down the differences:</p>
<ul>
<li>iterate through all bingo numbers</li>
<li>mark and skip winning boards</li>
</ul>
<h3 id="heading-iterate-through-all-bingo-numbers">Iterate through all bingo numbers</h3>
<p>The main difference from part one is that instead of stopping after finding the first winning board, we must go through all bingo numbers until all boards have at least one complete row or column. Thus, <code>forEach</code> works well in this case.</p>
<pre><code class="lang-js">bingoNumbers.forEach(<span class="hljs-function">(<span class="hljs-params">bingoNumber</span>) =&gt;</span> {
  boards.forEach(<span class="hljs-function">(<span class="hljs-params">board</span>) =&gt;</span> {
     <span class="hljs-comment">// ...</span>
  })
})
</code></pre>
<h3 id="heading-mark-and-skip-winning-boards">Mark and skip winning boards</h3>
<p>We must keep track of winning boards to prevent continued markings and secondary winning. We can add a <code>won</code> property to each board.</p>
<pre><code class="lang-js">boards = boards.map(<span class="hljs-function">(<span class="hljs-params">board</span>) =&gt;</span> ({
  <span class="hljs-attr">won</span>: <span class="hljs-literal">false</span>,
  board
}))
</code></pre>
<p>We must refactor the code to account for this data structure change. In addition, we skip marking numbers on winning boards and set the <code>won</code> property to <code>true</code> whenever we find a new winning board.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> lastWinningScore = <span class="hljs-number">0</span>

bingoNumbers.forEach(<span class="hljs-function">(<span class="hljs-params">bingoNumber</span>) =&gt;</span> {
  boards.forEach(<span class="hljs-function">(<span class="hljs-params">boardObject</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { board, won } = boardObject
    <span class="hljs-keyword">if</span> (won) {
        <span class="hljs-keyword">return</span>
      }
    <span class="hljs-comment">// ...</span>

    <span class="hljs-keyword">if</span> (isWinner) {
      boardObject.won = <span class="hljs-literal">true</span>
      lastWinningScore = calculateScore(board, bingoNumber)
    }
  })
})
</code></pre>
<p>You can see the final solution for part two on my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-04-giant-squid/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We wrote some code that simulates playing bingo. We determined the first and last winning boards, and we got to use a variety of JavaScript array functions, such as <code>some</code>, <code>forEach</code>, <code>reduce</code>, <code>map</code>, etc. As usual, I had fun with this challenge, and I am looking forward to day 5.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 3]]></title><description><![CDATA[This blog post is third in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 3.
All solutions are in this GitHub repository.
Solving Part One
The input file consists of binary numbers on separate lin...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-3</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-3</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Fri, 03 Dec 2021 17:04:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638458352993/qtst4fC89.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is third in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/3">Day 3</a>.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>The input file consists of binary numbers on separate lines. We must find the so-called gamma rate and epsilon rate, multiply them and return the resulting number in decimal format. Gamma rate is a binary number where each bit represents the most common bit in its position among all given numbers. Similarly, the epsilon rate contains the least common bit for each position.</p>
<p>We can break this problem into smaller tasks:</p>
<ul>
<li>read lines from the input file</li>
<li>find how many bits each number has</li>
<li>find the most common bit for a given position </li>
<li>find the least common bit for a given position</li>
<li>concatenate found bits</li>
<li>parse the binary string to decimal</li>
</ul>
<h3 id="heading-read-lines-from-the-input-file">Read lines from the input file</h3>
<p>I wrote about the <code>readInput</code> function in my <a target="_blank" href="https://blog.cristiana.tech/advent-of-code-2021-day-1">Advent of Code: Day 1</a> blog post. If you haven't already, give it a read!</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { URL, fileURLToPath } <span class="hljs-keyword">from</span> <span class="hljs-string">'url'</span>
<span class="hljs-keyword">import</span> { readInput } <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/readInput.js'</span>

<span class="hljs-keyword">const</span> inputPath = fileURLToPath(<span class="hljs-keyword">new</span> URL(<span class="hljs-string">'./input.txt'</span>, <span class="hljs-keyword">import</span>.meta.url))
<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> readInput(inputPath)
</code></pre>
<p>We can then get each line containing a binary number by splitting the input data using the new line character <code>\n</code></p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> lines = data.split(<span class="hljs-string">'\n'</span>)
</code></pre>
<h3 id="heading-find-how-many-bits-each-number-has">Find how many bits each number has</h3>
<p>One of the constraints of this problem is that each number is represented using the same number of bits. Thus, we can calculate the length of the first line to find how many bits each number has.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> numberOfBits = lines[<span class="hljs-number">0</span>].length
</code></pre>
<p>Now for each position, we must find the most and least common bits</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; numberOfBits; i++) {
  <span class="hljs-comment">// find most common bit for position i</span>
  <span class="hljs-comment">// find least common bit for position i</span>
}
</code></pre>
<h3 id="heading-find-the-most-common-bit-for-a-given-position">Find the most common bit for a given position</h3>
<p>We must iterate through each line and investigate the bit at the given position. To get the bit on a given position of a line we can use <code>line.charAt(index)</code>. We can then count the occurrences of <code>0</code> and <code>1</code> and compare them in the end to determine the most common bit.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getMostCommonBit = <span class="hljs-function">(<span class="hljs-params">lines, index</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> occurenceOf0 = <span class="hljs-number">0</span>
  <span class="hljs-keyword">let</span> occurenceOf1 = <span class="hljs-number">0</span>
  lines.forEach(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> bit = line.charAt(index)
    <span class="hljs-keyword">if</span> (bit === <span class="hljs-string">'0'</span>) {
      occurenceOf0 += <span class="hljs-number">1</span>
    } <span class="hljs-keyword">else</span> {
      occurenceOf1 += <span class="hljs-number">1</span>
    }
  })
  <span class="hljs-keyword">return</span> occurenceOf0 &gt; occurenceOf1 ? <span class="hljs-string">'0'</span> : <span class="hljs-string">'1'</span>
}
</code></pre>
<p>Since <code>occurenceOf0 &gt; occurenceOf1</code> can be written <code>occurenceOf0 - occurenceOf1 &gt; 0</code> we don't actually need the exact count of occurrences, only the difference. Thus, we can refactor the code like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getMostCommonBit = <span class="hljs-function">(<span class="hljs-params">lines, index</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> occurenceDifference = <span class="hljs-number">0</span>
  lines.forEach(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> bit = line.charAt(index)
    <span class="hljs-keyword">if</span> (bit === <span class="hljs-string">'0'</span>) {
      occurenceDifference += <span class="hljs-number">1</span>
    } <span class="hljs-keyword">else</span> {
      occurenceDifference -= <span class="hljs-number">1</span>
    }
  })
  <span class="hljs-keyword">return</span> occurenceDifference &gt; <span class="hljs-number">0</span> ? <span class="hljs-string">'0'</span> : <span class="hljs-string">'1'</span>
}
</code></pre>
<h3 id="heading-find-the-least-common-bit-for-a-given-position">Find the least common bit for a given position</h3>
<p>After finding the most common bit, we can determine the least common bit as the opposite. For example, if the most common bit is <code>0</code> we know the least common is <code>1</code> and vice versa. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mostCommonBit = getMostCommonBit(lines, i)
<span class="hljs-keyword">const</span> leastCommonBit = mostCommonBit === <span class="hljs-string">'0'</span> ? <span class="hljs-string">'1'</span> : <span class="hljs-string">'0'</span>
</code></pre>
<h3 id="heading-concatenate-found-bits">Concatenate found bits</h3>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> gammaRate = <span class="hljs-string">''</span>
<span class="hljs-keyword">let</span> epsilonRate = <span class="hljs-string">''</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; numberOfBits; i++) {
  <span class="hljs-keyword">const</span> mostCommonBit = getMostCommonBit(lines, i)
  gammaRate += mostCommonBit
  epsilonRate += mostCommonBit === <span class="hljs-string">'0'</span> ? <span class="hljs-string">'1'</span> : <span class="hljs-string">'0'</span>
}
</code></pre>
<h3 id="heading-parse-the-binary-string-to-decimal">Parse the binary string to decimal</h3>
<p>After finding the <code>gammaRate</code> and <code>epsilonRate</code> we can parse them to decimal using the <code>parseInt</code> function.</p>
<pre><code class="lang-js"><span class="hljs-built_in">parseInt</span>(gammaRate, <span class="hljs-number">2</span>)
<span class="hljs-built_in">parseInt</span>(epsilonRate, <span class="hljs-number">2</span>)
</code></pre>
<p>You can see the final solution for part one my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-03-binary-diagnostic/one.js">GitHub repository</a></p>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>I suggest thoroughly reading and understanding the <a target="_blank" href="https://adventofcode.com/2021/day/3#part2">problem</a> before reading further. 
To solve the second part of the challenge, we need to repeatedly filter the given binary numbers based on a bit criteria until there a single number is left. We must find the so-called oxygen generator rating (<code>oxygenRate</code>) and the CO2 scrubber rating (<code>co2Rate</code>) using this filtering method.</p>
<p>There are a few steps to solve the challenge:</p>
<ul>
<li>find the bit criteria for <code>oxygenRate</code> and <code>co2Rate</code></li>
<li>filter numbers until there is a single item left</li>
<li>parse the binary string to decimal</li>
</ul>
<h3 id="heading-find-the-bit-criteria">Find the bit criteria</h3>
<p>The bit criteria for <code>oxygenRate</code> is the most common bit in position X among filtered numbers, where X starts at 0 and increases each filtering round. Similarly, the bit criteria for <code>co2Rate</code> is the least common bit.</p>
<p>We can reuse the <code>getMostCommonBit</code> function created for part one, but with changes to accommodate the additional rule - if there is an equal number of bits, the criteria should default to <code>1</code> for <code>oxygenRate</code> and <code>0</code> for <code>co2Rate</code>.  </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getOccurenceDifference = <span class="hljs-function">(<span class="hljs-params">lines, index</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> occurenceDifference = <span class="hljs-number">0</span>
  lines.forEach(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> bit = line.split(<span class="hljs-string">''</span>)[index]
    <span class="hljs-keyword">if</span> (bit === <span class="hljs-string">'0'</span>) {
      occurenceDifference += <span class="hljs-number">1</span>
    } <span class="hljs-keyword">else</span> {
      occurenceDifference -= <span class="hljs-number">1</span>
    }
  })
  <span class="hljs-keyword">return</span> occurenceDifference
}
</code></pre>
<p>The <code>getOccurenceDifference</code> returns a positive number if <code>0</code> is most common, a negative number if <code>1</code> is most common or <code>0</code> if both bits are equally common. 
Thus, the bit criteria for <code>oxygenRate</code> is defined as follows and represents the most common bit or if both bits are equally common defaults to <code>1</code>.</p>
<pre><code class="lang-js">getOccurenceDifference(oxygenRates, index) &gt; <span class="hljs-number">0</span> ? <span class="hljs-string">'0'</span> : <span class="hljs-string">'1'</span>
</code></pre>
<p>The bit criteria for <code>co2Rate</code> represents the least common bit or if both bits are equally common defaults to <code>0</code>.</p>
<pre><code class="lang-js">getOccurenceDifference(co2Rates, index) &gt; <span class="hljs-number">0</span> ? <span class="hljs-string">'1'</span> : <span class="hljs-string">'0'</span>
</code></pre>
<h3 id="heading-filter-numbers-until-there-is-a-single-item-left">Filter numbers until there is a single item left</h3>
<p>The first filtering round starts with all lines for both <code>oxygenRates</code> and <code>co2Rates</code>. We can copy the lines representing the binary numbers into each corresponding array.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> oxygenRates = [...lines]
<span class="hljs-keyword">let</span> co2Rates = [...lines]
</code></pre>
<p>We repeatedly filter these numbers until there is a single item left. Each time we must increase the index of bit we compare with <code>criteriaBit</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> index = <span class="hljs-number">0</span>
<span class="hljs-keyword">while</span> (oxygenRates.length &gt; <span class="hljs-number">1</span>) {
  <span class="hljs-keyword">const</span> bitCriteria = getOccurenceDifference(oxygenRates, index) &gt; <span class="hljs-number">0</span> ? <span class="hljs-string">'0'</span> : <span class="hljs-string">'1'</span>
  oxygenRates = oxygenRates.filter(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> line.charAt(index) === bitCriteria)
  index++
}
</code></pre>
<p>Similarly, we filter the <code>co2Rates</code>.</p>
<pre><code class="lang-js">index = <span class="hljs-number">0</span>
<span class="hljs-keyword">while</span> (co2Rates.length &gt; <span class="hljs-number">1</span>) {
  <span class="hljs-keyword">const</span> bitCriteria = getOccurenceDifference(co2Rates, index) &gt; <span class="hljs-number">0</span> ? <span class="hljs-string">'1'</span> : <span class="hljs-string">'0'</span>
  co2Rates = co2Rates.filter(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> line.charAt(index) === bitCriteria)
  index++
}
</code></pre>
<h3 id="heading-parse-the-binary-string-to-decimal">Parse the binary string to decimal</h3>
<p>Finally, we can parse the first and only element in <code>oxygenRates</code> and <code>co2Rates</code> in the same manner we did for part one.</p>
<pre><code class="lang-js"><span class="hljs-built_in">parseInt</span>(oxygenRates[<span class="hljs-number">0</span>], <span class="hljs-number">2</span>)
<span class="hljs-built_in">parseInt</span>(co2Rates[<span class="hljs-number">0</span>], <span class="hljs-number">2</span>)
</code></pre>
<p>You can see the final solution for part two my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-03-binary-diagnostic/two.js">GitHub repository</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 3 was about thoroughly reading the problem, understanding it and breaking it down into smaller parts. We processed strings representing binary numbers and relied on JavaScript functions like <code>parseInt(binaryString, 2)</code>, <code>String.charAt(index)</code>, <code>array.filter(condition)</code> to solve the challenges.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 2]]></title><description><![CDATA[This blog post is second in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in Day 2: Dive!.
All solutions are in this GitHub repository.
Solving Part One
The goal is to find the horizontal position and d...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-2</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-2</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[coding challenge]]></category><category><![CDATA[challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Thu, 02 Dec 2021 14:50:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638449955242/QC4gphxv1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post is second in the Advent of Code 2021 series and shows a JavaScript-based solution to the problem described in <a target="_blank" href="https://adventofcode.com/2021/day/2">Day 2: Dive!</a>.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>The goal is to find the horizontal position and depth of a moving submarine based on a set of given instructions.</p>
<p>According to the problem the initial depth and horizontal positions are <code>0</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> depth = <span class="hljs-number">0</span>
<span class="hljs-keyword">let</span> horizontalPosition = <span class="hljs-number">0</span>
</code></pre>
<p>We can read the set of instructions using the <code>readInput</code> utility created on Day 1. Then we can split the data line by line.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> commands = data.split(<span class="hljs-string">'\n'</span>)
</code></pre>
<p>Each line contains a command type and a number of steps. To use these, we can split the line by the space character, then convert the steps to a number.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [type, stepsAsString] = command.split(<span class="hljs-string">' '</span>)
<span class="hljs-keyword">const</span> steps = <span class="hljs-built_in">Number</span>(stepsAsString)
</code></pre>
<p>Finally, we can calculate the depth and horizontal positions based on the command type and steps to move according to the rules described in the challenge. </p>
<pre><code class="lang-js"> <span class="hljs-keyword">switch</span> (type) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">'forward'</span>:
    horizontalPosition += steps
    <span class="hljs-keyword">break</span>
  <span class="hljs-keyword">case</span> <span class="hljs-string">'down'</span>:
    depth += steps
    <span class="hljs-keyword">break</span>
  <span class="hljs-keyword">case</span> <span class="hljs-string">'up'</span>:
    depth -= steps
    <span class="hljs-keyword">break</span>
  <span class="hljs-attr">default</span>:
    <span class="hljs-keyword">break</span>
}
</code></pre>
<p>The final solution:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { URL, fileURLToPath } <span class="hljs-keyword">from</span> <span class="hljs-string">'url'</span>
<span class="hljs-keyword">import</span> { readInput } <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/readInput.js'</span>

<span class="hljs-keyword">const</span> solve = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> commands = data.split(<span class="hljs-string">'\n'</span>)
  <span class="hljs-keyword">let</span> depth = <span class="hljs-number">0</span>
  <span class="hljs-keyword">let</span> horizontalPosition = <span class="hljs-number">0</span>

  commands.forEach(<span class="hljs-function">(<span class="hljs-params">command</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> [type, stepsAsString] = command.split(<span class="hljs-string">' '</span>)
    <span class="hljs-keyword">const</span> steps = <span class="hljs-built_in">Number</span>(stepsAsString)

    <span class="hljs-keyword">switch</span> (type) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">'forward'</span>:
        horizontalPosition += steps
        <span class="hljs-keyword">break</span>
      <span class="hljs-keyword">case</span> <span class="hljs-string">'down'</span>:
        depth += steps
        <span class="hljs-keyword">break</span>
      <span class="hljs-keyword">case</span> <span class="hljs-string">'up'</span>:
        depth -= steps
        <span class="hljs-keyword">break</span>
      <span class="hljs-attr">default</span>:
        <span class="hljs-keyword">break</span>
    }
  })
  <span class="hljs-keyword">return</span> depth * horizontalPosition
}

<span class="hljs-keyword">const</span> inputPath = fileURLToPath(<span class="hljs-keyword">new</span> URL(<span class="hljs-string">'./input.txt'</span>, <span class="hljs-keyword">import</span>.meta.url))

<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> readInput(inputPath)

<span class="hljs-built_in">console</span>.log(solve(data))
</code></pre>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>The second part of the problem requires calculating depth and horizontal position in a slightly different way using new rules and an aim value.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> aim = <span class="hljs-number">0</span>
</code></pre>
<p>The new rules can be written in JavaScript as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">switch</span> (type) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">'forward'</span>:
    horizontalPosition += steps
    depth += aim * steps
    <span class="hljs-keyword">break</span>
  <span class="hljs-keyword">case</span> <span class="hljs-string">'down'</span>:
    aim += steps
    <span class="hljs-keyword">break</span>
  <span class="hljs-keyword">case</span> <span class="hljs-string">'up'</span>:
    aim -= steps
    <span class="hljs-keyword">break</span>
  <span class="hljs-attr">default</span>:
    <span class="hljs-keyword">break</span>
}
</code></pre>
<p>The final solution for part two is on my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-02-dive/two.js">GitHub repository</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Day 2 was about calculating values such as horizontal position and depth of a moving submarine based on a set of given commands. I had fun solving the challenge and the utility functions added on Day 1 helped solve the second challenge somewhat faster.</p>
]]></content:encoded></item><item><title><![CDATA[Advent of Code 2021: Day 1]]></title><description><![CDATA[The Advent of Code is an Advent calendar with programming challenges. It is a wonderful way to keep your skills sharp, learn a new programming language, prepare for interviews, or have something to look forward to each day leading up to Christmas.
Th...]]></description><link>https://blog.cristiana.tech/advent-of-code-2021-day-1</link><guid isPermaLink="true">https://blog.cristiana.tech/advent-of-code-2021-day-1</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[challenge]]></category><category><![CDATA[coding challenge]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Tue, 30 Nov 2021 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638436419515/ojqqptC02H.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <a target="_blank" href="https://adventofcode.com/2021">Advent of Code</a> is an Advent calendar with programming challenges. It is a wonderful way to keep your skills sharp, learn a new programming language, prepare for interviews, or have something to look forward to each day leading up to Christmas.</p>
<p>This blog series will walk you through my thought process and show possible solutions to the challenges. I used JavaScript to solve these, but you can use any programming language.</p>
<p>All solutions are in this <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021">GitHub repository</a>.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>To use JavaScript, we need to set a Node.js project. I opted for Yarn as a package manager due to improved performance when installing dependencies and personal preference, but <code>npm</code> works well too.</p>
<p>Steps:</p>
<ol>
<li>Initialize the project by running <code>yarn init</code>. This command creates the <code>package.json</code> file containing project name, description, licencing and dependencies.</li>
<li>Add <code>"type": "module"</code> to the <code>package.json</code> file to enable <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules">ESModules</a> since Node.js uses CommonJS modules by default.</li>
<li>Install  <a target="_blank" href="https://prettier.io">Prettier</a> to format code automatically. Run <code>yarn add prettier</code> and add the following configuration in <code>.prettierrc</code>: <pre><code><span class="hljs-attr">trailingComma:</span> <span class="hljs-string">"es5"</span>
<span class="hljs-attr">tabWidth:</span> <span class="hljs-number">2</span>
<span class="hljs-attr">semi:</span> <span class="hljs-literal">false</span>
<span class="hljs-attr">singleQuote:</span> <span class="hljs-literal">true</span>
<span class="hljs-attr">endOfLine:</span> <span class="hljs-string">"lf"</span>
</code></pre></li>
<li>Add <code>.gitignore</code> file for the Node.js project. <a target="_blank" href="https://github.com/github/gitignore/blob/master/Node.gitignore">This template from GitHub</a> works well.</li>
</ol>
<p>The solution and input files are grouped by day in the <code>src</code> folder (e.g. <code>src/day-01-sonar-sweep</code>).</p>
<pre><code>advent<span class="hljs-operator">-</span>of<span class="hljs-operator">-</span>code<span class="hljs-number">-2021</span>
│   .gitignore
│   .prettierrc
│   package.json
│   yarn.lock
│
├───node_modules
└───src
    └───day<span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>sonar<span class="hljs-operator">-</span>sweep
            input.txt
            one.js
            two.js
</code></pre><h2 id="heading-input-reader-utility">Input Reader Utility</h2>
<p>Reading input data from a file is a common need when solving any of the challenges. Thus, I created a utility function that accepts a file path as a parameter and returns a <code>Promise</code> with the data as a string.</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/util/readInput.js</span>
<span class="hljs-keyword">import</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">'fs'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> readInput = <span class="hljs-function">(<span class="hljs-params">inputPath</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span>
    fs.readFile(inputPath, <span class="hljs-string">'utf8'</span>, <span class="hljs-function">(<span class="hljs-params">err, data</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (err) {
        <span class="hljs-built_in">console</span>.error(err)
        reject(err)
      }
      resolve(data)
    })
  )
}
</code></pre>
<p>We can then import and use the <code>readInput</code> utility in each solution file (e.g. <code>one.js</code>):</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { readInput } <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/readInput.js'</span>

<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> readInput(inputPath)
</code></pre>
<p>The input path is relative to the solution file. We can use the <code>url</code> module from Node.js to build the path needed for the file reader.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { URL, fileURLToPath } <span class="hljs-keyword">from</span> <span class="hljs-string">'url'</span>

<span class="hljs-keyword">const</span> inputPath = fileURLToPath(<span class="hljs-keyword">new</span> URL(<span class="hljs-string">'./input.txt'</span>, <span class="hljs-keyword">import</span>.meta.url))
</code></pre>
<h2 id="heading-solving-part-one">Solving Part One</h2>
<p>You can read the problem on <a target="_blank" href="https://adventofcode.com/2021/day/1">Advent of Code Day 1</a>.
Given an array of depths, the objective is to compare every two adjacent depths and count when the depth increases.</p>
<p>To solve this problem, we first need to parse the contents of the input file. Since each number is given on a new line we can use the <code>split</code> function with the new line character <code>\n</code> as a separator to get an array of strings representing the contents of each line. Then we convert each line to a number.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> depths = data.split(<span class="hljs-string">'\n'</span>).map(<span class="hljs-function">(<span class="hljs-params">line</span>) =&gt;</span> <span class="hljs-built_in">Number</span>(line))
</code></pre>
<p>Since the first depth does not increase or decrease, we can remove it from the array and store it with the purpose of comparing it to the next depth.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> previousDepth = depths.shift()
</code></pre>
<p>The depth increases when <code>depth - previousDepth &gt; 0</code> is true.
We can iterate the array and count how many times the depth increases using <code>forEach</code> and a counter variable.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> increaseCount = <span class="hljs-number">0</span>

depths.forEach(<span class="hljs-function">(<span class="hljs-params">depth</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (depth - previousDepth &gt; <span class="hljs-number">0</span>) {
    increaseCount += <span class="hljs-number">1</span>
  }
  previousDepth = depth
})
</code></pre>
<p>Put together, the solution is:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { URL, fileURLToPath } <span class="hljs-keyword">from</span> <span class="hljs-string">'url'</span>
<span class="hljs-keyword">import</span> { readInput } <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/readInput.js'</span>

<span class="hljs-keyword">const</span> getIncreaseCount = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> depths = data.split(<span class="hljs-string">'\n'</span>).map(<span class="hljs-function">(<span class="hljs-params">i</span>) =&gt;</span> <span class="hljs-built_in">Number</span>(i))
  <span class="hljs-keyword">let</span> previousDepth = depths.shift()
  <span class="hljs-keyword">let</span> increaseCount = <span class="hljs-number">0</span>

  depths.forEach(<span class="hljs-function">(<span class="hljs-params">depth</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (depth - previousDepth &gt; <span class="hljs-number">0</span>) {
      increaseCount += <span class="hljs-number">1</span>
    }
    previousDepth = depth
  })
  <span class="hljs-keyword">return</span> increaseCount
}

<span class="hljs-keyword">const</span> inputPath = fileURLToPath(<span class="hljs-keyword">new</span> URL(<span class="hljs-string">'./input.txt'</span>, <span class="hljs-keyword">import</span>.meta.url))

<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> readInput(inputPath)

<span class="hljs-built_in">console</span>.log(getIncreaseCount(data))
</code></pre>
<h2 id="heading-solving-part-two">Solving Part Two</h2>
<p>The second part has the objective of comparing sums of three depths to the next set of three depths. For example, given the depths a, b, c, d, e. We would have to compare:</p>
<ul>
<li>a + b + c and b + c + d</li>
<li>b + c + d and c + d + e</li>
</ul>
<p>Since we subtract the sums to find whether the depth increases or decreases, the problem can be reduced to compare</p>
<ul>
<li>a and d</li>
<li>b and e</li>
</ul>
<p>In other words, we need to compare every two depths positioned three indexes apart.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> increaseCount = <span class="hljs-number">0</span>

<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; depths.length - <span class="hljs-number">2</span>; i++) {
  <span class="hljs-keyword">if</span> (depths[i + <span class="hljs-number">3</span>] - depths[i] &gt; <span class="hljs-number">0</span>) {
    increaseCount += <span class="hljs-number">1</span>
  }
}
</code></pre>
<p>You can see the final solution on my <a target="_blank" href="https://github.com/mancristiana/advent-of-code-2021/blob/main/src/day-01-sonar-sweep/two.js">GitHub repository</a>.</p>
<h2 id="heading-summary">Summary</h2>
<p>Day 1 consisted of setting up a Node.js project with Yarn and Prettier, creating an input reader utility, parsing numbers from an input file, iterating through a number array and comparing every two numbers positioned either one or three indexes apart.</p>
]]></content:encoded></item><item><title><![CDATA[Creating an Empty Commit]]></title><description><![CDATA[There are times when creating an empty commit in Git is useful. A common scenario is the need to trigger a continuous integration pipeline or adding an important commit message that might have some effect. For example, GitVersion integrates with Git ...]]></description><link>https://blog.cristiana.tech/creating-an-empty-commit</link><guid isPermaLink="true">https://blog.cristiana.tech/creating-an-empty-commit</guid><category><![CDATA[Git]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Tue, 04 May 2021 19:18:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620062370588/C-4Qjtw9K.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are times when creating an empty commit in Git is useful. A common scenario is the need to trigger a continuous integration pipeline or adding an important commit message that might have some effect. For example, GitVersion integrates with Git and uses commit messages to increase version numbers of your library or application semantically. </p>
<p>This short post shows you how you can create an empty commit.</p>
<h2 id="attempt-to-commit-without-any-file-changes">Attempt to commit without any file changes</h2>
<p>I needed to create an empty commit when using GitVersion. Let me explain.
GitVersion finds commit messages containing patterns like <code>+semver:minor</code> and determines the corresponding build and release number used in the continuous deployment process. While the best practice is adding this text on the commit with the minor or major change, there are cases where the change is broken up into multiple smaller commits. I personally experienced such a scenario or forgot to add the correct message bumping the version.</p>
<p>So I tried running this:</p>
<pre><code>git <span class="hljs-keyword">commit</span> -m "+semver:minor"
</code></pre><p>Git, however, did not let me commit, proudly declaring my branch was up to date and there was nothing to commit.</p>
<h2 id="using-the-allow-empty-option">Using the <code>--allow-empty</code> option</h2>
<p>Git assumes that creating an empty commit might be a mistake, thus preventing it by default. You can bypass this using the <a target="_blank" href="https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---allow-empty"><code>--allow-empty</code></a> option.</p>
<pre><code>git <span class="hljs-keyword">commit</span> -m "+semver:minor" <span class="hljs-comment">--allow-empty</span>
</code></pre><p>With this approach, you can create an empty commit containing no files or any changes, only with your desired message.</p>
<h2 id="using-the-allow-empty-message-option">Using the <code>--allow-empty-message</code> option</h2>
<p>When researching to write this post, I stumbled upon the <a target="_blank" href="https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---allow-empty-message"><code>--allow-empty-message</code></a> option. Similarly to the <code>--allow-empty</code> option, it is not meant for typical workflow. Omitting to write a descriptive short message about what has changed is not good practice and makes it harder to scan through the changes when looking at the commit history.</p>
<p>However, an empty commit with no message might be useful for triggering a Continuous Deployment &amp; Integration (CD/CI) pipeline. </p>
<pre><code>git <span class="hljs-keyword">commit</span> <span class="hljs-comment">--allow-empty-message --no-edit</span>
</code></pre><p>This snippet bypasses Git's requirement of adding a message. The <a target="_blank" href="https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---no-edit"><code>--no-edit</code></a> option keeps the selected empty message and prevents launching an editor, which by default prompts modifying empty commit messages.</p>
<h2 id="summary">Summary</h2>
<p>In rare cases, you might need to bypass Git's default requirements when making a commit. The <code>--allow-empty</code> and <code>--allow-empty-message</code> options can be useful to create empty commits to trigger some effect. The examples mentioned in this post were triggering a CI/CD pipeline or increasing the semantic version of your package or application.</p>
]]></content:encoded></item><item><title><![CDATA[Why Learn Data Science?]]></title><description><![CDATA[Should you learn Data Science if you work as a Software Engineer?
Data Science skills are among the most sought after in the modern tech industry. Successful business collect and analyse large amounts of data to effectively make decisions, innovate a...]]></description><link>https://blog.cristiana.tech/why-learn-data-science</link><guid isPermaLink="true">https://blog.cristiana.tech/why-learn-data-science</guid><category><![CDATA[Data Science]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Thu, 22 Apr 2021 21:42:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619032572902/csplxsFZO.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Should you learn Data Science if you work as a Software Engineer?</p>
<p>Data Science skills are among the most sought after in the modern tech industry. Successful business collect and analyse large amounts of data to effectively make decisions, innovate and create an excellent service for their customers. </p>
<p>This article is the first in the <strong>Road to Data Science</strong> series and fittingly introduces the benefits of learning Data Science from a Software Engineer's perspective. While the points I make in this article reflect my expectations and reasons for learning, I hope it will motivate you to explore this marvellous field.</p>
<h2 id="a-new-perspective">A New Perspective</h2>
<p>At the beginning of my learning journey, I had no clear idea of what Data Science was. Fortunately, Denise Sengül's brief introduction clarified some of my initial assumptions, captivated my interest and sparked my curiosity about the intricate world of Data Science.</p>
<p>I encourage you to watch the first 20 minutes of <a target="_blank" href="https://www.youtube.com/watch?v=wTPwXgurR6M">What the Tech... is a Data Scientist?</a>. In this video, Denise reveals how "Data Science is about finding patterns in data for a specific purpose".</p>
<p>Rather than seeing Data Science as a completely different discipline, think of it as part of the problem-solving process. This new perspective of Data Science means that learning data analysis techniques and shifting your mindset to think like a Data Scientist becomes a valuable tool for solving problems.</p>
<p>I firmly believe that learning, seeking to improve and constantly building new skills are healthy habits of a successful Software Engineer. Having Data Science skills can broaden your perspective and improve decision-making.</p>
<h2 id="career-opportunities">Career Opportunities</h2>
<p>Data Scientists who are also Software Engineers are somewhat rare and have a combination of IT, statistics, and communication skills. Having a broad set of skills can advance your career and give you many opportunities in the future.</p>
<p>The diagram below is taken from Denise Sengül's presentation and illustrates the variety of job titles related to Data Scientist based on the skillset required on the job. Artificial Intelligence Engineer and Machine Learning Engineer use IT skills and statistics. Having IT skills, communication and domain expertise in a business are suitable for Data Engineer and Data Warehouse Architect positions. Finally, Data Analysts and Business Intelligence Analysts know statistics, have domain expertise and strong communication skills.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619037315703/SkNLf1XJ_.png" alt="image.png" /></p>
<h2 id="build-smart-software">Build Smart Software</h2>
<p>Investing time in learning about Artificial Intelligence (AI) and Machine Learning (ML) techniques can empower you to build the innovative, smart products of the future.</p>
<p>Software products are expected to become increasingly smarter by anticipating user's needs and making predictions. For example, mainstream content streaming applications like Netflix, Youtube and Spotify collect and analyse user's data to recommend personalised content, thus, creating a better user experience. </p>
<p>By learning how to integrate features such as image processing, natural language processing, computer vision, and many more into modern products, you can create powerful applications. Examples range across industries from self-driving cars, legal analysis, fraud prevention to assistant software that can help doctors perform diagnosis faster. </p>
<p>Many of these applications are empowered by cloud computing services like Google Cloud, AWS and Microsoft Azure. Thus, by learning the basics of AI and ML, you can get started with some of these services that simplify the integration of AI-based features and build the intelligent software products of tomorrow.</p>
<h2 id="engineer-big-data">Engineer Big Data</h2>
<p>The ability to engineer and analyse large amounts of ever-increasing quantities of data is essential in today's organisations. The Big Data field emerged when NASA scientists had to solve the challenge of collecting, processing and storing an unimaginably large amount of data from space missions, Earth observatory, etc.</p>
<p>While not everyone works at NASA, having the skills to manage large datasets, make data visualisations and finding patterns help organisations gain insight and make informed decisions to grow their business. </p>
<h2 id="summary">Summary</h2>
<p>Learning Data Science</p>
<ul>
<li>helps you solve business problems by using insights from data</li>
<li>gives you a wider range of career opportunities</li>
<li>empowers you to build AI-based software</li>
<li>enables you to work with Big Data</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Creating a React Component Library with TypeScript, Storybook & Rollup]]></title><description><![CDATA[A shared UI component library is fundamental to the frontend architecture of a growing company where you have teams maintaining several projects that use the same visual elements. The UI component library ensures visual consistency between projects o...]]></description><link>https://blog.cristiana.tech/creating-a-react-component-library-with-typescript-storybook-and-rollup</link><guid isPermaLink="true">https://blog.cristiana.tech/creating-a-react-component-library-with-typescript-storybook-and-rollup</guid><category><![CDATA[React]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[components]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Sun, 11 Apr 2021 22:42:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618083880763/3lbmPOs2w.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A shared UI component library is fundamental to the frontend architecture of a growing company where you have teams maintaining several projects that use the same visual elements. The UI component library ensures visual consistency between projects owned by different teams and improves productivity since you can update components, fix visual issues, and solve similar problems in a single place. </p>
<p>If you have a single project, you don't need a separate library for your components as you can define them directly in your project.</p>
<p>This post shows how to set up and get started using </p>
<ul>
<li>Create React App for installing React and Testing Library</li>
<li>Storybook for documenting and showcasing components in isolation</li>
<li>Rollup for bundling the library</li>
</ul>
<p>You can find the resulting project on <a target="_blank" href="https://github.com/mancristiana/blog-react-component-library">GitHub</a>.</p>
<h2 id="heading-create-react-app">Create React App</h2>
<p>To get started, we can create a new project called <code>ui</code> using <a target="_blank" href="https://create-react-app.dev/docs/getting-started#creating-a-typescript-app">Create React App</a>:</p>
<pre><code>npx create<span class="hljs-operator">-</span>react<span class="hljs-operator">-</span>app ui <span class="hljs-operator">-</span><span class="hljs-operator">-</span>template typescript
</code></pre><p>This generates boilerplate code that allows us to create React components and test them using <a target="_blank" href="https://testing-library.com/docs/react-testing-library/intro/">React Testing Library</a>. </p>
<p>You can remove <code>start</code>, <code>build</code> and <code>eject</code> scripts from <code>package.json</code> because we will use Storybook to start our project and Rollup to bundle a production-ready package.</p>
<pre><code><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-string">"test"</span>: <span class="hljs-string">"react-scripts test"</span>
},
</code></pre><p>You can also remove <code>App.tsx</code>, <code>App.css</code>, <code>App.test.tsx</code>, <code>index.css</code>, <code>index.tsx</code>, <code>logo.svg</code>, <code>reportWebVitals.ts</code> since we won't use them.</p>
<h2 id="heading-setting-up-storybook">Setting up Storybook</h2>
<p><a target="_blank" href="https://storybook.js.org">Storybook</a> is a wonderful tool for developing, showcasing and documenting UI components in isolation. Storybook works with any component-based library in JavaScript such as React, Vue, Angular, and more. </p>
<p>To install Storybook in our React application, run this command:</p>
<pre><code>npx sb <span class="hljs-keyword">init</span>
</code></pre><p>You should now be able to run Storybook locally by running <code>npm run storybook</code> or if you prefer <code>yarn storybook.</code></p>
<p>Here is a preview of the Storybook application:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618057127075/ywnGp7Mg3.png" alt="image.png" /></p>
<h3 id="heading-understanding-the-project-structure-with-storybook">Understanding the Project Structure with Storybook</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618064316028/mo6nWRMYq.png" alt="StorybookStructureOverview.png" /></p>
<h4 id="heading-the-stories-folder">The <code>stories</code> folder</h4>
<p>By default, the <code>npx sb init</code> command creates a <code>stories</code> folder inside <code>src</code> with example components and documentation pages. While you can safely remove this folder, I recommend exploring it first!</p>
<ul>
<li><code>Introduction.stories.mdx</code> file contains the documentation used to generate the <em>Introduction to Storybook</em> page in the image preview above. The file is written using <a target="_blank" href="https://storybook.js.org/docs/react/writing-docs/mdx#gatsby-focus-wrapper">MDX</a> format, which is a combination of Markdown and <a target="_blank" href="https://reactjs.org/docs/introducing-jsx.html">JSX</a>, so you can write components directly into the documentation. The links in this file are also worth exploring! </li>
<li><code>Button.tsx</code> and <code>Button.stories.tsx</code> are great examples of how you can define a component and a corresponding page in Storybook. The Button story documents available props, code usage, and showcases component variations. Through the Controls, you can experiment with toggling and customizing props.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618062929216/Y5Iq1JePQ.gif" alt="StorybookButton.gif" /></p>
<h4 id="heading-the-storybook-folder">The <code>.storybook</code> folder</h4>
<p>Contains files for customizing Storybook:</p>
<ul>
<li><code>main.js</code> defines the file pattern used by Storybook to determine what to include in the showcase application. By default, Storybook uses files containing <code>.stories</code> in their name.<pre><code> <span class="hljs-string">"stories"</span>: [
   <span class="hljs-string">"../src/**/*.stories.mdx"</span>,
   <span class="hljs-string">"../src/**/*.stories.@(js|jsx|ts|tsx)"</span>
 ]
</code></pre> <a target="_blank" href="https://storybook.js.org/docs/react/addons/introduction">Addons</a> for the Storybook application are also defined in <code>main.js.</code><pre><code> <span class="hljs-string">"addons"</span>: [
   <span class="hljs-string">"@storybook/addon-links"</span>,
   <span class="hljs-string">"@storybook/addon-essentials"</span>,
   <span class="hljs-string">"@storybook/preset-create-react-app"</span>
 ]
</code></pre></li>
<li><p><code>preview.js</code> configures how actions and controls will show up depending on the prop's name. By default, props starting with <code>on</code> such as <code>onClick</code>, <code>onChange</code>, <code>onSubmit</code> are automatically interpreted by Storybook as actions, so when triggered, they get logged inside Storybook's Actions addon. Besides, props suffixed with <code>background</code> and <code>color</code> will show a color picker control, whereas props suffixed with <code>Date</code> display a date picker control.</p>
<pre><code> <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> parameters = {
  <span class="hljs-attr">actions</span>: { <span class="hljs-attr">argTypesRegex</span>: <span class="hljs-string">"^on[A-Z].*"</span> },
  <span class="hljs-attr">controls</span>: {
    <span class="hljs-attr">matchers</span>: {
      <span class="hljs-attr">color</span>: <span class="hljs-regexp">/(background|color)$/i</span>,
      date: <span class="hljs-regexp">/Date$/</span>,
    },
  },
}
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618065413057/oWt-h93IO.jpeg" alt="StorybookActions.jpg" /></p>
</li>
</ul>
<h4 id="heading-the-packagejson-file">The <code>package.json</code> file</h4>
<p>This file is automatically updated with Storybook development dependencies, custom eslint configuration for stories, and the following scripts:</p>
<pre><code>  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"react-scripts test"</span>,
    <span class="hljs-string">"storybook"</span>: <span class="hljs-string">"start-storybook -p 6006 -s public"</span>,
    <span class="hljs-string">"build-storybook"</span>: <span class="hljs-string">"build-storybook -s public"</span>
  },
</code></pre><ul>
<li><code>npm run storybook</code> starts the Storybook application locally</li>
<li><code>npm run build-storybook</code> builds the Storybook application ready for deployment</li>
</ul>
<p>Rollup needs an entry point to generate the bundle. Let's create <code>index.ts</code> in the <code>src</code> file that exports each of our components generated by Storybook:</p>
<pre><code><span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">"./stories/Button"</span>
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">"./stories/Header"</span>
<span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">"./stories/Page"</span>
</code></pre><h2 id="heading-bundling-with-rollup">Bundling with Rollup</h2>
<p>Rollup is a good bundling tool choice if we want to package the React component library and reuse it in other projects. </p>
<blockquote>
<p>In <a target="_blank" href="https://medium.com/webpack/webpack-and-rollup-the-same-but-different-a41ad427058c">Webpack and Rollup: the same but different</a> Rich Harris recommends using Webpack for applications and Rollup for libraries.</p>
</blockquote>
<p>First, you need to install dependencies either using npm</p>
<pre><code>npm install @rollup<span class="hljs-operator">/</span>plugin<span class="hljs-operator">-</span>commonjs @rollup<span class="hljs-operator">/</span>plugin<span class="hljs-operator">-</span>node<span class="hljs-operator">-</span>resolve rollup<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>peer<span class="hljs-operator">-</span>deps<span class="hljs-operator">-</span><span class="hljs-keyword">external</span> @rollup<span class="hljs-operator">/</span>plugin<span class="hljs-operator">-</span>typescript postcss rollup<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>postcss  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev
</code></pre><p>or with yarn</p>
<pre><code>yarn add rollup @rollup<span class="hljs-operator">/</span>plugin<span class="hljs-operator">-</span>commonjs @rollup<span class="hljs-operator">/</span>plugin<span class="hljs-operator">-</span>node<span class="hljs-operator">-</span>resolve rollup<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>peer<span class="hljs-operator">-</span>deps<span class="hljs-operator">-</span><span class="hljs-keyword">external</span> @rollup<span class="hljs-operator">/</span>plugin<span class="hljs-operator">-</span>typescript postcss rollup<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>postcss <span class="hljs-operator">-</span>D
</code></pre><p>Let's understand these dependencies:</p>
<ul>
<li><a target="_blank" href="https://rollupjs.org/guide/en/#command-line-reference"><code>rollup</code></a> gives the command-line interface (CLI) to bundle the library</li>
<li><a target="_blank" href="https://github.com/rollup/plugins/tree/master/packages/commonjs"><code>@rollup/plugin-commonjs</code></a> converts CommonJS modules (potentially used in node_modules) to ES6, which is what Rollup understands. If you don't know what CommonJS modules are, this article explains module systems in JavaScript: <a target="_blank" href="https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm">What the heck are CJS AMD UMD and ESM in JavaScript?</a></li>
<li><a target="_blank" href="https://github.com/rollup/plugins/tree/master/packages/node-resolve"><code>@rollup/plugin-node-resolve</code></a> helps Rollup understand how to import dependencies in <code>node_modules</code>.</li>
<li><a target="_blank" href="https://github.com/rollup/plugins/tree/master/packages/typescript"><code>@rollup/plugin-typescript</code></a> transpiles TypeScript files to JavaScript.</li>
<li><a target="_blank" href="https://www.npmjs.com/package/rollup-plugin-peer-deps-external"><code>rollup-plugin-peer-deps-external</code></a> prevents adding peer dependencies to the bundle because the consumer of the library is expected to have them. So we also get a smaller bundle size.</li>
<li><a target="_blank" href="https://github.com/egoist/rollup-plugin-postcss"><code>rollup-plugin-postcss</code></a> integrates with PostCss tool for bundling styles. You can configure this tool with CSS modules, Less, Sass, depending on your preference.</li>
</ul>
<p>Next, we need to update <code>package.json</code>.
According to the <a target="_blank" href="https://github.com/rollup/rollup/wiki/pkg.module">Rollup Wiki</a>, libraries should be distributed using CommonJS and ES6. We specify the output file paths using <code>main</code> and <code>module</code> properties. We also use these properties in the Rollup configuration file.</p>
<p>Then, add a <code>build</code> script that uses the <code>rollup</code> command-line interface with the <code>-c</code> argument. This means that Rollup will look for a configuration file named <code>rollup.config.js</code> to bundle the component library.</p>
<p>Add <code>react</code> and <code>react-dom</code> to <code>peerDependencies</code> and <code>devDependencies</code> (we still need them for Storybook) and remove these from <code>dependencies</code>. This is needed by <code>rollup-plugin-peer-deps-external</code> plugin to prevent distributing and bundling dependencies that the consumer library already has.</p>
<pre><code>{
  ...
  <span class="hljs-string">"main"</span>: <span class="hljs-string">"./build/index.js"</span>,
  <span class="hljs-string">"module"</span>: <span class="hljs-string">"./build/index.es.js"</span>,
  <span class="hljs-string">"scripts"</span>: {
    ...
    <span class="hljs-string">"build"</span>: <span class="hljs-string">"rollup -c"</span>
  },
  <span class="hljs-string">"peerDependencies"</span>: {
    <span class="hljs-string">"react"</span>: <span class="hljs-string">"^17.0.2"</span>,
    <span class="hljs-string">"react-dom"</span>: <span class="hljs-string">"^17.0.2"</span>
  },
  <span class="hljs-string">"devDependencies"</span>: {
    ...
    <span class="hljs-string">"react"</span>: <span class="hljs-string">"^17.0.2"</span>,
    <span class="hljs-string">"react-dom"</span>: <span class="hljs-string">"^17.0.2"</span>
  }
}
</code></pre><p>Finally, the <code>rollup.config.js</code> file has the following contents:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">commonjs</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@rollup/plugin-commonjs"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">resolve</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@rollup/plugin-node-resolve"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">peerDepsExternal</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"rollup-plugin-peer-deps-external"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">typescript</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@rollup/plugin-typescript"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">postcss</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"rollup-plugin-postcss"</span>;

<span class="hljs-keyword">import</span> <span class="hljs-title">packageJson</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./package.json"</span>;

<span class="hljs-comment">// eslint-disable-next-line import/no-anonymous-default-export</span>
export default {
  input: <span class="hljs-string">"./src/index.ts"</span>,
  output: [
    {
      file: packageJson.main,
      format: <span class="hljs-string">"cjs"</span>,
      sourcemap: <span class="hljs-literal">true</span>
    },
    {
      file: packageJson.module,
      format: <span class="hljs-string">"esm"</span>,
      sourcemap: <span class="hljs-literal">true</span>
    }
  ],
  plugins: [
    peerDepsExternal(),
    resolve(),
    commonjs(),
    typescript(),
    postcss()
  ]
};
</code></pre><h2 id="heading-conclusion">Conclusion</h2>
<p>We created a React component library powered by Create React App. We installed Storybook to create a documentation page and enable developing components in isolation. Finally, we configured Rollup for bundled the library. </p>
<p>While this is one way of getting started, an alternative approach could be based on <a target="_blank" href="https://www.npmjs.com/package/create-react-library">Create React Library</a>. Let me know if you would like to see an article about that.</p>
<p>I hope you found this interesting.
Thanks for reading!</p>
]]></content:encoded></item><item><title><![CDATA[Adding Website Previews on Twitter, Facebook & Slack (Link Unfurling)]]></title><description><![CDATA[A crucial aspect of creating a website is making sure it looks great when sharing it on social media. From a user perspective, previews save time and help determine whether to visit a website or not. Thus, enabling rich content sharing can drasticall...]]></description><link>https://blog.cristiana.tech/adding-website-previews-on-twitter-facebook-and-slack-link-unfurling</link><guid isPermaLink="true">https://blog.cristiana.tech/adding-website-previews-on-twitter-facebook-and-slack-link-unfurling</guid><category><![CDATA[HTML5]]></category><category><![CDATA[Twitter]]></category><category><![CDATA[Facebook]]></category><category><![CDATA[slack]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Tue, 06 Apr 2021 19:11:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1617730213438/HNXFa0Q6-.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A crucial aspect of creating a website is making sure it looks great when sharing it on social media. From a user perspective, previews save time and help determine whether to visit a website or not. Thus, enabling rich content sharing can drastically improve traffic to your website. </p>
<p>You can control the title, description, preview image, and other custom properties that show up when someone pastes a link to your website on Twitter, Facebook, as part of a Slack message, or on other social media. This is called <strong> <em>link unfurling</em> </strong>, and the previews are called <strong> <em>unfurls</em> </strong> according to <a target="_blank" href="https://medium.com/slack-developer-blog/everything-you-ever-wanted-to-know-about-unfurling-but-were-afraid-to-ask-or-how-to-make-your-e64b4bb9254">Slack Developer Blog</a>.</p>
<p>In this article, we explore how to build a web page that shows image previews, a title, and a short description. Here is an example of the website preview on Facebook:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617728941294/oGwX70_E9.png" alt="unfurl-fb.png" /></p>
<p>Facebook and the majority of social media platforms such as LinkedIn rely on <a target="_blank" href="https://developers.facebook.com/docs/sharing/webmasters#markup">Open Graph HTML markup</a> to show website previews and other media previews. </p>
<ul>
<li><a target="_blank" href="https://ogp.me/?fbclid=IwAR25IhUdezbpor3j4KwLVg9Sv5DJOAlToJG0gxgpDdwxHr3KaGeNzZ5ShEM#types"><code>og:type</code></a> defines the type of object or media you want to share and it can be one of following:  <code>article</code>, <code>book</code>, <code>music</code>, <code>profile</code>, <code>video</code>, <code>website</code>
If you don't specify this property, it will default to <code>website</code>.</li>
<li><code>og:url</code> is the Canonical URL of your website. This means the preferred or base URL of a webpage typically used by search engines.</li>
<li><code>og:title</code> is the title of the page you are linking. Unless you are linking the home page this is not your brand or website name.</li>
<li><code>og:description</code> is a short description of the page.</li>
<li><code>og:image</code> is the URL of the preview image of your web page.</li>
</ul>
<p>For example, the following snippet included in the <code>head</code> section of a HTML page of https://fearlessintotech.com website was used to generate the preview above.</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">property</span>=<span class="hljs-string">"og:type"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"website"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">property</span>=<span class="hljs-string">"og:url"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"https://fearlessintotech.com"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">property</span>=<span class="hljs-string">"og:title"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"Fearless into Tech"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">property</span>=<span class="hljs-string">"og:description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"A community initiative from women for women. Fearless into Tech is a decentralised, peer-to-peer supported group of tech-curious, self-learning women."</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">property</span>=<span class="hljs-string">"og:image"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"https://fearlessintotech.com/images/preview.jpg"</span> /&gt;</span>
</code></pre><p>Twitter developed its own mechanism called <a target="_blank" href="https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards">Twitter Cards</a> for optimizing links in tweets and enabling rich content sharing. There is some overlap between Open Graph and Twitter Cards. For example, <code>twitter:title</code>, <code>twitter:description</code>, <code>twitter:url</code> and <code>twitter:image</code> have the same function as their Open Graph counterparts. In addition, there are some Twitter-specific tags:</p>
<ul>
<li><code>twitter:card</code> similar to <code>og:type</code> specifies which card type should be used when sharing the web page link. There are four types of cards:  <em>Summary Card</em> containing a title, description and thumbnail; <em>Summary Card with Large Image</em> same as <em>Summary Card</em>, but instead of a thumbnail features a large image; <em>App Card</em> for links to download mobile apps; <em>Player Card</em> for showing video, audio, and other media.</li>
<li><code>twitter:site</code> specifies the Twitter account associated with the website</li>
<li><code>twitter:creator</code> specifies the Twitter account associated with the author of the content on the website. This might be more relevant to articles posted on blog platforms, where the site and creator are distinct.</li>
</ul>
<pre><code>&lt;meta <span class="hljs-type">name</span>="twitter:card" content="summary_large_image"&gt;
&lt;meta <span class="hljs-type">name</span>="twitter:site" content="@FearlessInto"&gt;
&lt;meta <span class="hljs-type">name</span>="twitter:domain" <span class="hljs-keyword">value</span>="fearlessintotech.com" /&gt;
&lt;meta <span class="hljs-type">name</span>="twitter:title" <span class="hljs-keyword">value</span>="Fearless into Tech" /&gt;
&lt;meta <span class="hljs-type">name</span>="twitter:description" <span class="hljs-keyword">value</span>="A community initiative from women for women. Fearless into Tech is a decentralised, peer-to-peer supported group of tech-curious, self-learning women." /&gt;
&lt;meta <span class="hljs-type">name</span>="twitter:image" content="https://fearlessintotech.com/images/preview.jpg" /&gt;
&lt;meta <span class="hljs-type">name</span>="twitter:url" <span class="hljs-keyword">value</span>="https://fearlessintotech.com" /&gt;
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617736113561/OSwOZ1QGj.jpeg" alt="unfurl-twitter.jpg" /></p>
<p>Slack uses a combination of Open Graph and Twitter tags to unfurl links as shown in  <a target="_blank" href="https://api.slack.com/reference/messaging/link-unfurling#classic_unfurl">Slack API Documentation</a>. The website preview shows up like this when shared in a Slack message:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617728956163/9f_z6q9dz.jpeg" alt="unfurl-slack.jpg" /></p>
<p>Once you include all the tags for various social media platforms, you can test how your website link would be unfurled by entering the link to your website in the following pages:</p>
<ul>
<li>https://cards-dev.twitter.com/validator</li>
<li>https://developers.facebook.com/tools/debug/</li>
</ul>
<p>To sum up, including meta tags on your web pages using the Open Graph coupled with Twitter Cards is a powerful mechanism that allows various social media platforms to perform link unfurling and show previews when someone shares a link to your website.</p>
]]></content:encoded></item><item><title><![CDATA[Rounded Black and White Image Effect using CSS]]></title><description><![CDATA[In web applications, you might not have control of user-uploaded content such as images. Moreover, creating a beautiful web design, a rich user interface, and great experience requires taking full advantage of CSS.  
A great example of custom-styled ...]]></description><link>https://blog.cristiana.tech/rounded-black-and-white-image-effect-using-css</link><guid isPermaLink="true">https://blog.cristiana.tech/rounded-black-and-white-image-effect-using-css</guid><category><![CDATA[CSS]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Thu, 01 Apr 2021 19:38:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1617305817653/cfWUW0rL8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In web applications, you might not have control of user-uploaded content such as images. Moreover, creating a beautiful web design, a rich user interface, and great experience requires taking full advantage of CSS.  </p>
<p>A great example of custom-styled images is on most social media applications such as Facebook, Twitter, and Linkedin, where profile pictures are displayed in a circle. </p>
<p>This article shows you how you can create a similar effect to display a black and white image with rounded corners.</p>
<p>This is the markup for the image in HTML:</p>
<pre><code class="lang-html"> <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
     <span class="hljs-attr">src</span>=<span class="hljs-string">"profile.jpg"</span>
     <span class="hljs-attr">width</span>=<span class="hljs-string">"200"</span>
     <span class="hljs-attr">height</span>=<span class="hljs-string">"200"</span>
     <span class="hljs-attr">alt</span>=<span class="hljs-string">"Profile picture"</span>
     <span class="hljs-attr">class</span>=<span class="hljs-string">"rounded grayscale"</span>
 /&gt;</span>
</code></pre>
<p>The <code>img</code> tag is styled using two CSS utility classes <code>rounded</code> and <code>grayscale</code>. </p>
<p>The <code>rounded</code> class turns the square image into a circle by using the <code>border-radius</code> property and setting it to <code>50%</code> of the image's width. </p>
<pre><code class="lang-css"><span class="hljs-selector-class">.rounded</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
}
</code></pre>
<p>Sara Cope explores the wonderful <code>border-radius</code> property in depth on <a target="_blank" href="https://css-tricks.com/almanac/properties/b/border-radius">CSS Tricks</a>.</p>
<p>The <code>grayscale</code> class creates the black and white effect. You need to use the filter property with the grayscale option and specify <code>100%</code> which completely saturates the color. According to  <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/filter">MDN Web Docs</a> most modern browsers support filter property with the <code>-webkit-</code> vendor prefix.</p>
<pre><code><span class="hljs-selector-class">.grayscale</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">grayscale</span>(<span class="hljs-number">100%</span>);
  <span class="hljs-attribute">-webkit-filter</span>: <span class="hljs-built_in">grayscale</span>(<span class="hljs-number">100%</span>);
}
</code></pre><p>To sum up, you can use the <code>border-radius</code> and <code>filter</code> with <code>grayscale</code> properties to stylize an image with rounded corners and a black and white appearance. This is especially useful when you don't have control over the image content.
Thanks for reading and I hope you found this interesting!</p>
]]></content:encoded></item><item><title><![CDATA[Calculating Color Contrast in TypeScript using Web Content Accessibility Guidelines (WCAG)]]></title><description><![CDATA[When developing applications or websites it is important to use high color contrast between the text elements and their background to ensure they are readable for anyone with low vision impairments and color deficiencies. 
There might be cases when y...]]></description><link>https://blog.cristiana.tech/calculating-color-contrast-in-typescript-using-web-content-accessibility-guidelines-wcag</link><guid isPermaLink="true">https://blog.cristiana.tech/calculating-color-contrast-in-typescript-using-web-content-accessibility-guidelines-wcag</guid><category><![CDATA[Accessibility]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Cristiana Man]]></dc:creator><pubDate>Mon, 29 Mar 2021 10:46:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1617014635152/7oyPtEJ8B.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When developing applications or websites it is important to use high color contrast between the text elements and their background to ensure they are readable for anyone with low vision impairments and color deficiencies. </p>
<p>There might be cases when you want to calculate and display the color contrast ratio. For example, if you are developing a component library or design system and you want to emphasize color usage guidelines with accessibility in mind.</p>
<p>This article shows how you can calculate the color contrast ratio in TypeScript given two colors in either RGB or hex format. </p>
<p>First, let's explore the concept of color contrast ratio visually. If you inspect the color of a text element in Chrome Developer Tools you can see the contrast ratio for that color and whether the contrast is high enough for the text to be considered legible. In the screenshot, color <code>#2db477</code> against white has a contrast ratio of 2.66 which is not high enough. The Developer tools also recommend two alternative colors that would meet the high contrast color requirements where the ratios are 4.5.1 and 7.0:1 respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1617000811930/KGj2Y0pId.jpeg" alt="Color Contrast In Developer Tools.jpg" /></p>
<p>What does this AA: 4.5 and AAA: 7.0 mean?</p>
<p>The Web Content Accessibility Guidelines (WCAG) is a standard that defines three levels of accessibility that should be implemented in the following priority:</p>
<ul>
<li>A: This level is required for assistive technology to read and understand a webpage. </li>
<li>AA: This is the ideal support and it is required for government and public websites. Normal text should have a color contrast of at least 4.5 to meet this level. Large text, such as headings, as well as icons, should have a color contrast of at least 3.0.</li>
<li>AAA: This level offers specialized support for specific audiences. The text should have a color contrast of at least 7.0.</li>
</ul>
<p>The WCAG defines a <a target="_blank" href="https://www.w3.org/TR/WCAG20-TECHS/G18.html#G18-tests">procedure</a> which we can use to calculate color contrast. There are many contrast checkers online such as the Chrome Developer Tools, <a target="_blank" href="https://webaim.org/resources/contrastchecker/">WebAim</a>, and many others that use the procedure described in the WCAG specification. </p>
<p>According to the procedure we first need to measure the luminance of the foreground color and background color. Then calculate the contrast ratio using this formula <code>(L1 + 0.05) / (L2 + 0.05)</code>, where L1 represents the luminance of the lighter color and L2 represents the luminance of the darker color.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">contrast</span>(<span class="hljs-params">foregroundColor: RGB, backgroundColor: RGB</span>) </span>{
    <span class="hljs-keyword">const</span> foregroundLumiance = luminance(foregroundColor);
    <span class="hljs-keyword">const</span> backgroundLuminance = luminance(backgroundColor);
    <span class="hljs-keyword">return</span> backgroundLuminance &lt; foregroundLumiance
        ? ((backgroundLuminance + <span class="hljs-number">0.05</span>) / (foregroundLumiance + <span class="hljs-number">0.05</span>))
        : ((foregroundLumiance + <span class="hljs-number">0.05</span>) / (backgroundLuminance + <span class="hljs-number">0.05</span>));
};
</code></pre><p>You can define the <code>RGB</code> type as an array of three numbers. We will use this type when calculating contrast.</p>
<pre><code><span class="hljs-keyword">type</span> RGB = [<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>];
</code></pre><p>The relative luminance of each color part (red, green and blue) can be calculated using this function:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">luminance</span>(<span class="hljs-params">rgb: RGB</span>) </span>{
    <span class="hljs-keyword">const</span> [r, g, b] = rgb.map(<span class="hljs-function">(<span class="hljs-params">v</span>) =&gt;</span> {
        v /= <span class="hljs-number">255</span>;
        <span class="hljs-keyword">return</span> v &lt;= <span class="hljs-number">0.03928</span> ? v / <span class="hljs-number">12.92</span> : <span class="hljs-built_in">Math</span>.pow((v + <span class="hljs-number">0.055</span>) / <span class="hljs-number">1.055</span>, <span class="hljs-number">2.4</span>);
    });
    <span class="hljs-keyword">return</span> r * <span class="hljs-number">0.2126</span> + g * <span class="hljs-number">0.7152</span> + b * <span class="hljs-number">0.0722</span>;
};
</code></pre><p>If we use hex color format it will be useful to get the RGB value. We can achieve that using the following function:</p>
<pre><code><span class="hljs-function">function <span class="hljs-title">getRgbColorFromHex</span>(<span class="hljs-params">hex: <span class="hljs-keyword">string</span></span>)</span> {
    hex = hex.slice(<span class="hljs-number">1</span>);
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">value</span> = parseInt(hex, <span class="hljs-number">16</span>);
    <span class="hljs-keyword">const</span> r = (<span class="hljs-keyword">value</span> &gt;&gt; <span class="hljs-number">16</span>) &amp; <span class="hljs-number">255</span>;
    <span class="hljs-keyword">const</span> g = (<span class="hljs-keyword">value</span> &gt;&gt; <span class="hljs-number">8</span>) &amp; <span class="hljs-number">255</span>;
    <span class="hljs-keyword">const</span> b = <span class="hljs-keyword">value</span> &amp; <span class="hljs-number">255</span>;

    <span class="hljs-keyword">return</span> [r, g, b] <span class="hljs-keyword">as</span> RGB;
};
</code></pre><p>Finally, we can use our functions to calculate the contrast between two colors (e.g. <code>#2db477</code> and <code>#ffffff</code>):</p>
<pre><code><span class="hljs-keyword">const</span> foregroundColor = getRgbColorFromHex(<span class="hljs-string">"#2db477"</span>);
<span class="hljs-keyword">const</span> backgroundColor = getRgbColorFromHex(<span class="hljs-string">"#ffffff"</span>);
<span class="hljs-keyword">const</span> contrastRatio = contrast(foregroundColor, backgroundColor);
</code></pre><p>Alternatively, if you prefer using the RGB type directly:</p>
<pre><code><span class="hljs-string">const</span> <span class="hljs-string">contrastRatio</span> <span class="hljs-string">=</span> <span class="hljs-string">contrast([45,</span> <span class="hljs-number">180</span><span class="hljs-string">,</span> <span class="hljs-number">119</span><span class="hljs-string">],</span> [<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>]<span class="hljs-string">);</span>
</code></pre><p>To sum up, we looked at how the Web Content Accessibility Guidelines (WCAG) defines three levels of accessibility and what each level requires in terms of color contrast. We then defined functions in TypeScript that calculate color contrast using the formulas in the WCAG specification, given colors in either hex or RGB format. </p>
]]></content:encoded></item></channel></rss>