<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas</title>
    <description>The latest articles on DEV Community by Lucas (@heylucas).</description>
    <link>https://dev.to/heylucas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F430727%2Ffab58739-a11e-45d3-b5d6-415cf498aa74.jpg</url>
      <title>DEV Community: Lucas</title>
      <link>https://dev.to/heylucas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heylucas"/>
    <language>en</language>
    <item>
      <title>How to do better on coding interviews</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Wed, 13 Jan 2021 11:12:45 +0000</pubDate>
      <link>https://dev.to/heylucas/how-to-do-better-on-coding-interviews-2ok8</link>
      <guid>https://dev.to/heylucas/how-to-do-better-on-coding-interviews-2ok8</guid>
      <description>&lt;p&gt;tl;dr Warm up before the interview.&lt;br&gt;
This post is a summary of my YouTube video:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/DShg-vqnpck"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;A few years ago I learned a trick: warm up before my coding interviews. I know, it sounds weird. But don't worry, keep reading, it will all make sense (hopefully).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why warm up
&lt;/h2&gt;

&lt;p&gt;Being the gym lover I am, let's start with gym analogy.&lt;/p&gt;

&lt;p&gt;Pretend today is leg day. You come into the gym, grab the bar, load 200KG on it and start squatting. Sounds reasonable? Probably not.&lt;/p&gt;

&lt;p&gt;Most likely we would come into the gym and warm up. We'd just do enough exercise to get the blood flowing and our bodies ready for the exercise. So why don't we do the same for coding interviews? Isn't it weird?&lt;/p&gt;

&lt;p&gt;We all know coding demands focus. Anyone who's had random ping on Slack or meeting interrupt their flow knows how it feels. It takes time to get back on track.&lt;/p&gt;

&lt;p&gt;The same applies to interviews.&lt;/p&gt;

&lt;p&gt;Interviewing is inherently hard, not because of the coding challenge, but because of all the other factors involved: time, stress, anxiety, etc. Jumping into an interview cold does you no good. In the best case, it slows you down. In the worst case, it causes you to fail the interview.&lt;/p&gt;

&lt;p&gt;Warming up will prime your mind and put yourself in a ready state to come in and crush that interview.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to warm up
&lt;/h2&gt;

&lt;p&gt;YMMV, but this is what works for me and a few people I know that are pretty good at interviews.&lt;/p&gt;

&lt;p&gt;One hour before your interview, start the warm up.&lt;/p&gt;

&lt;p&gt;You can use whatever you want: VS Code, LeetCode, pen and paper. Anything that works for you.&lt;/p&gt;

&lt;p&gt;Choose 1-3 problems you already know how to solve and start working on them. This is key.&lt;/p&gt;

&lt;p&gt;Back to the gym analogy: you don't warm up for squats with a load that leaves you busted and prevents you from doing the actual working sets. You load just enough to get yourself ready for the real thing. That's the goal with the coding warm up.&lt;/p&gt;

&lt;p&gt;You choose exercises you already know to avoid wasting energy that can be used for the interview itself. You just need to get those brain juices flowing.&lt;/p&gt;

&lt;p&gt;Another reason to stick to a problem you know how to solve is this: if you pick a hard problem and fail at solving it right before your interview, what do you think that's gonna do to your confidence? Probably not much good, right? So don't do it. Stick to what you know for the warm up.&lt;/p&gt;

&lt;p&gt;And last, but not least, stop your warm up 15 minutes before the interview starts. Just step away from the computer. Go get some water, use the toilet, or stare at a wall if you have to. Use this time to chill. I like to play some chill music to help me get in the mood. Do this to help control your interview stress (we all get stressed, trust me).&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Warm up before your interview so your mind is ready for the coding problems.&lt;/li&gt;
&lt;li&gt;Start your warm up 1 hour before the interview.&lt;/li&gt;
&lt;li&gt;Choose 1-3 exercises you already know how to solve and get cranking.&lt;/li&gt;
&lt;li&gt;Give yourself a 15 minute break before the interview to relax.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  That's all
&lt;/h2&gt;

&lt;p&gt;Thank you for reading this far!&lt;br&gt;
If you like this post, let me know on &lt;a href="https://twitter.com/0800LUCAS"&gt;Twitter&lt;/a&gt;! I also post videos about this sort of stuff on YouTube, so go check &lt;a href="https://www.youtube.com/channel/UCbf0aCU8t_dQTaFf3WOavxg"&gt;my channel&lt;/a&gt; if you haven't yet.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>interviewtips</category>
      <category>coding</category>
      <category>career</category>
    </item>
    <item>
      <title>How I got offers from Amazon, Microsoft, and Bloomberg</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Mon, 04 Jan 2021 09:13:25 +0000</pubDate>
      <link>https://dev.to/heylucas/how-i-got-offers-from-amazon-microsoft-and-bloomberg-l04</link>
      <guid>https://dev.to/heylucas/how-i-got-offers-from-amazon-microsoft-and-bloomberg-l04</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is an excerpt of my YouTube video:&lt;/em&gt; &lt;iframe width="710" height="399" src="https://www.youtube.com/embed/pj57nB1CKHU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Last year I decided it was time to switch jobs. Interviewing is always a hassle, so I decided to keep track of what worked for me. I'm sharing this in the hopes someone else might benefit from what I've learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I prepared for the phone screens
&lt;/h2&gt;

&lt;p&gt;I kept it simple: LeetCode for practice problems. I didn't aim for an arbitrary number of questions to "be ready".&lt;/p&gt;

&lt;p&gt;Practiced each day for a few hours and used space repetition. I'd cover multiple topics each session. That prevented things from getting too boring.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I prepared for the onsite interviews
&lt;/h2&gt;

&lt;p&gt;Since I had practiced a lot of coding for the phone screens, I put coding in the back-burner.&lt;/p&gt;

&lt;p&gt;Instead, I focused on system design and behavioral questions.&lt;/p&gt;

&lt;p&gt;For system design, &lt;a href="https://www.educative.io/courses/grokking-the-system-design-interview"&gt;Grokking the System Design Interview&lt;/a&gt; was pretty useful. To supplement that,  I also watched YouTube videos to see how different people approached different problems.&lt;/p&gt;




&lt;p&gt;When it came to behavioral prep, I used &lt;a href="https://apps.ankiweb.net/"&gt;Anki&lt;/a&gt; flashcards. I went through all of Amazon's leadership principles, researched common behavioral questions, and created the cards with my answers. I also made sure to include any follow ups I could think of to my cards.&lt;/p&gt;

&lt;p&gt;This definitely made me memorize my answers.&lt;/p&gt;

&lt;p&gt;This might sound like cheating, but the truth is you're not gonna be able to come up with a story on the spot. You'll ramble. You'll forget details. You'll get confused. Interviewing is already stressful enough. Preparing the questions and answers beforehand will give you a leg up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I did all of my interviews in a single week
&lt;/h2&gt;

&lt;p&gt;Onsite interviews usually take 5 hours. Three onsites in a week totals 15 hours. I won't lie, it sucked. I was pretty exhausted after that week. But at the same time, it didn't suck.&lt;/p&gt;

&lt;p&gt;Doing all the interviews at once gave me momentum and helped me perform well. It also helped me get it over quickly.&lt;/p&gt;

&lt;p&gt;It also gave me a huge advantage: leverage. You see, when you tell companies you already have other onsites, they pay attention. You're suddenly in high demand. That makes them move faster and gives you more power to command a better offer.&lt;/p&gt;

&lt;p&gt;This was the first time I scheduled my interviews like this and, trust me, it made a huge difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's all folks
&lt;/h2&gt;

&lt;p&gt;If you've read this far, thank you! I hope this post was useful and showed you one path you can take to prepare for your interviews.&lt;/p&gt;

&lt;p&gt;If you liked this post, have a look at my &lt;a href="https://www.youtube.com/channel/UCbf0aCU8t_dQTaFf3WOavxg"&gt;YouTube channel&lt;/a&gt;. I post videos every week, discussing tech, career, and productivity!&lt;/p&gt;

&lt;p&gt;If you'd like to chat, hit me up on &lt;a href="https://twitter.com/0800LUCAS"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>career</category>
      <category>amazon</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Advent of Code 2020 in Kotlin: Day 05</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Sat, 05 Dec 2020 16:25:11 +0000</pubDate>
      <link>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-05-4a6i</link>
      <guid>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-05-4a6i</guid>
      <description>&lt;p&gt;On &lt;a href="https://adventofcode.com/2020/day/5"&gt;Day 05&lt;/a&gt; we need to find our seat on the airplane! We must go over and decode a list of boarding passes to find their seat IDs. A boarding pass is just a sequence of 10 characters.&lt;/p&gt;

&lt;p&gt;The whole problem revolves around &lt;a href="https://en.wikipedia.org/wiki/Binary_search_algorithm"&gt;Binary Search&lt;/a&gt;. Decoding a boarding pass is composed of two parts: Initially we analyse the first 7 characters to find the correct row; then, we look at the last 3 characters to find the correct column.&lt;/p&gt;

&lt;p&gt;When looking for a row or a column, we divide the search space in half after each inspected character.&lt;/p&gt;

&lt;p&gt;Since we are not looking for a number specifically, we can use &lt;a href="https://en.wikipedia.org/wiki/Binary_search_algorithm#Procedure_for_finding_the_leftmost_element"&gt;left-most binary search&lt;/a&gt; to get the correct index we are looking for.&lt;/p&gt;

&lt;p&gt;Let’s dig into the code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Data representation
&lt;/h2&gt;

&lt;p&gt;I wanted to represent each line in the input file as a &lt;code&gt;BoardingPass&lt;/code&gt;object. The boarding pass would list its row, column, and seat ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;BoardingPass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;seatID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty straightforward, isn’t it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the data
&lt;/h2&gt;

&lt;p&gt;Like on Day 04, I extended the File class to return me a list of BoardingPasses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toListOfBoardingPassesOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BoardingPass&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;readLines&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBoardingPass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to convert a line (String) into a BoardingPass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBoardingPass&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;BoardingPass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Find the correct column&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;lo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;hi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;127&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'F'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;

    &lt;span class="c1"&gt;// Find the correct row&lt;/span&gt;
    &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;mid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'L'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;column&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BoardingPass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m not gonna go over how the binary search above works (check the Wikipedia article for that). All we do here is iterate over the characters in the boarding pass and extract the row and column. We then return a &lt;code&gt;BoardingPass&lt;/code&gt; object with those values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: Get the max seat ID in the list of boarding passes
&lt;/h2&gt;

&lt;p&gt;Pretty easy this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toListOfBoardingPassesOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seatID&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;maxOrNull&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We read the boarding passes, get the seat ID for each one of them and then select the one with maximum value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Find our own seat ID
&lt;/h2&gt;

&lt;p&gt;The question tells us that our boarding pass is the only one missing in the input, and that the seats immediately before and after ours are taken.&lt;/p&gt;

&lt;p&gt;We just must find the empty seat.&lt;/p&gt;

&lt;p&gt;One way to do this might be to sort the list of seatIDs and find where there’s a gap of 1. That would give us O(n * log(n)) runtime complexity.&lt;/p&gt;

&lt;p&gt;Instead, I decided to use a variation of Counting Sort. We know there will be at most 128 * 8 seats (i.e., 128 rows and 8 columns per row). So I preallocated an array of that size, where each position denotes a seat. Each position in the array has value 0 or 1. Zero means that seat is empty, one means it is taken.&lt;/p&gt;

&lt;p&gt;Now we just go over each seat ID we have and mark then as taken in the array. After that, we just iterate over the entire array and find an empty seat between two taken seats. That empty seat is ours.&lt;/p&gt;

&lt;p&gt;Here’s what the code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;totalSeats&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;maxSeatID&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;totalSeats&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="c1"&gt;// Preallocate array for seats. Zero indicates the seat is emtpy&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;seats&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalSeats&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toListOfBoardingPassesOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seatID&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;seats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;maxSeatID-1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The current seat is empty but the previous and next seats are taken,&lt;/span&gt;
    &lt;span class="c1"&gt;// so that's our seat.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toByte&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;seats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i-1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toByte&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;seats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toByte&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll notice that on the line highlighted I call the &lt;code&gt;toByte&lt;/code&gt; method multiple times. That’s necessary due to Kotlin’s limitation. It cannot automatically detect that those literals are of type &lt;code&gt;Byte&lt;/code&gt; and there’s no shorthand to cast them. There’s even &lt;a href="https://youtrack.jetbrains.com/issue/KT-3936"&gt;a ticket on JetBrains’s issue tracker&lt;/a&gt; but it doesn’t seem to be going anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s all folks
&lt;/h2&gt;

&lt;p&gt;Today’s puzzle was pretty straightforward. My only surprise was the weirdness about the implicit conversions in Kotlin. Still, I’m happy with my solution.&lt;/p&gt;

&lt;p&gt;Let’s see what’s up with day 06 tomorrow!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Advent of Code 2020 in Kotlin: Day 04</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Fri, 04 Dec 2020 15:39:00 +0000</pubDate>
      <link>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-04-3pcg</link>
      <guid>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-04-3pcg</guid>
      <description>&lt;p&gt;&lt;a href="https://adventofcode.com/2020/day/4"&gt;Day 04&lt;/a&gt; was Advent of Code’s version of &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Papers,_Please"&gt;Papers, Please&lt;/a&gt;&lt;/em&gt;. You had to go over a list of passports and validate them. I’m not too happy with how the code turned out, as it’s a bit verbose for my taste. Alas, it’s not terrible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data representation
&lt;/h2&gt;

&lt;p&gt;A passport must contain a set of fields and we need to ensure they are present. I created a &lt;code&gt;Passport&lt;/code&gt; class with an entry for each of those fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;byr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;iyr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;eyr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;hgt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;hcl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;ecl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see I mark each field as &lt;em&gt;nullable&lt;/em&gt; (the ? after the type). I do this is because each passport maybe have missing fields, making them invalid.&lt;/p&gt;

&lt;p&gt;To help me construct the Passport objects, I defined a Builder class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;byr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;iyr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;eyr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;hgt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;hcl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;ecl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;

      &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;setField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;"byr"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;byr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="s"&gt;"iyr"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iyr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="s"&gt;"eyr"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eyr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="s"&gt;"hgt"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hgt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;
          &lt;span class="s"&gt;"hcl"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hcl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;
          &lt;span class="s"&gt;"ecl"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ecl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;
          &lt;span class="s"&gt;"pid"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;
      &lt;span class="s"&gt;"cid"&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fieldValue&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;byr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iyr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eyr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;hgt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hcl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ecl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reading the data
&lt;/h2&gt;

&lt;p&gt;Like on &lt;a href="https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-03-2bf1"&gt;Day 03&lt;/a&gt;, I defined an extension method on the &lt;code&gt;File&lt;/code&gt; class. This method returns a &lt;em&gt;nullable&lt;/em&gt; list of &lt;code&gt;Passport&lt;/code&gt;s.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPassportListOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;passportBuilder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nf"&gt;forEachLine&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passportBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="n"&gt;passportBuilder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;parts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;passportBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passportBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parsing the passports is a bit tricky. The fields might span multiple lines. An empty line marks the end of a passport record. That’s why in the code above I check if the current line is empty to insert the passport in the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Counting the valid passports
&lt;/h2&gt;

&lt;p&gt;To check if a passport is valid or not, I just added a new method to the Passport class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;byr&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;iyr&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;eyr&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;hgt&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;hcl&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;ecl&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code to actually count the passports is trivial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toPassportListOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;The second part of the problem is nothing special. Before we just had to check if the required fields were present, now we must check if the fields have correct values. That’s easy enough, we just extend the &lt;code&gt;isValid&lt;/code&gt;method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;validEyeColors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"amb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"blu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"brn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"gry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"grn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hzl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"oth"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;hairColorRegex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"""#[a-f0-9]{6}"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;validHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;76&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cm"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;193&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;byr&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;byr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;2002&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;iyr&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;iyr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2010&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;2020&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;eyr&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;eyr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;2030&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;hgt&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;validHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hgt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;hcl&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;hairColorRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hcl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;ecl&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;validEyeColors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ecl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The validation code is pretty ugly but it gets the job done. The first 3 fields are years, so we just check if they are within a given range.&lt;/p&gt;

&lt;p&gt;To validate the height, I created a separate method. Heights can be given either in centimeters or inches. It made sense to have a separate method for that.&lt;/p&gt;

&lt;p&gt;Hair color was just a matter of using a regular expression for a HEX color code. Eye color is a set membership check. And the last field, Passport ID (PID), we just check its length.&lt;/p&gt;

&lt;h2&gt;
  
  
  The end
&lt;/h2&gt;

&lt;p&gt;That’s it for day 4. I’m not exactly happy with this code. I feel like I wrote too much to accomplish too little. I’m sure Kotlin has some facilities that would make writing this code a lot shorter, but I haven’t explored that yet.&lt;/p&gt;

&lt;p&gt;Now on to day 05!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Advent of Code 2020 in Kotlin: Day 03</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Thu, 03 Dec 2020 19:08:31 +0000</pubDate>
      <link>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-03-2bf1</link>
      <guid>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-03-2bf1</guid>
      <description>&lt;p&gt;Today’s puzzle was a bit more involved than the last two days. &lt;a href="https://adventofcode.com/2020/day/3"&gt;The puzzle&lt;/a&gt; asks us to write some code to direct a toboggan. We are given a grid that represents the area we have to cross. We start at the top-left position (coordinates (0, 0)) and need to get to the last row and count how many trees we’ve seen along the way. The way we are allowed to move is specified in the question.&lt;/p&gt;

&lt;p&gt;Let’s have a look at how I tackled this problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Representing the grid
&lt;/h2&gt;

&lt;p&gt;I chose to represent the grid as &lt;code&gt;data class&lt;/code&gt; containing three fields: width, height, and cells. Cells is just an array of arrays that represents each coordinate in the grid. If the cell is &lt;code&gt;true&lt;/code&gt;, it means there’s a tree there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Loading the grid
&lt;/h2&gt;

&lt;p&gt;I initially implemented this using companion methods, like I did on &lt;a href="https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-02-5827"&gt;Day 02&lt;/a&gt;. Once I got it working, I saw someone commented on &lt;a href="https://www.reddit.com/r/adventofcode/comments/k5fdgr/day_02_in_kotlin/geexb3m/"&gt;Reddit&lt;/a&gt;that using extension methods would be more Kotlin-like. I changed the code and what I did instead was extend the &lt;code&gt;File&lt;/code&gt; class with a method to load the grid.&lt;/p&gt;

&lt;p&gt;On the one hand, I think the code reads quite nicely this way. On the other hand, I’m not a huge fan of extension methods in this case. It feels wrong to embed this application-specific functionality in the &lt;code&gt;File&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Here’s what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toGridOrNull&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;cells&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;readLines&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'#'&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;toTypedArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;toTypedArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;height&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;width&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No magic here. We read all the lines in the file, apply map to them transforming each line into an array of &lt;code&gt;Boolean&lt;/code&gt;s. We mark the cell as a tree if the character we are looking at is equal to &lt;code&gt;#&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the answer
&lt;/h2&gt;

&lt;p&gt;Now that we’ve loaded the grid into memory, we need to actually find the result.&lt;/p&gt;

&lt;p&gt;I started by first extending the &lt;code&gt;Grid&lt;/code&gt; class with a couple of methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Inside the Grid class    &lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;isTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;countTrees&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;currentRow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;currentColumn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;verticalStep&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;horizontalStep&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;trees&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentRow&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;currentRow&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;verticalStep&lt;/span&gt;
        &lt;span class="n"&gt;currentColumn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentColumn&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;horizontalStep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="c1"&gt;// this ensures we wrap around&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentRow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currentColumn&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;trees&lt;/span&gt;&lt;span class="p"&gt;++&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;trees&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;isTree&lt;/code&gt; is just a helper method so we can check if a cell is a tree. &lt;code&gt;countTrees&lt;/code&gt;is a bit morecomplex: In part 1 of the problem, we always move 3 columns to the right and 1 row down. Those numbers are represented by the &lt;code&gt;horizontalStep&lt;/code&gt; and &lt;code&gt;verticalStep&lt;/code&gt; variables, respectively. We then iterate until we reach the last row of the grid. At each step, we compute &lt;code&gt;currentColumn&lt;/code&gt;using modulo since the grid wraps around. The tree counter is bumped whenever we find one.&lt;/p&gt;

&lt;p&gt;Now our &lt;code&gt;main&lt;/code&gt; function looks very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toGridOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;countTrees&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;The second part is pretty similar to the first one, but now we are asked to count how many trees we find by moving in different patterns. Once we have the count for each pattern, we multiply all of them and that’s the answer.&lt;/p&gt;

&lt;p&gt;When it comes to the Grid class, we only need to make a minor tweak:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Inside the Grid classs&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;countTrees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verticalStep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;horizontalStep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;currentRow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;currentColumn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;trees&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentRow&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we did was pull the &lt;code&gt;verticalStep&lt;/code&gt; and &lt;code&gt;horizontalStep&lt;/code&gt; variables out of the body and into the parameter list.&lt;/p&gt;

&lt;p&gt;The difference now is that our &lt;code&gt;main&lt;/code&gt; function is a lot more complex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;grid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toGridOrNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;steps&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;treeCounts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verticalStep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;horizontalStep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;countTrees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verticalStep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;horizontalStep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;totalTrees&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;treeCounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBigInteger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalTrees&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s unpack what is going on here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load the grid&lt;/li&gt;
&lt;li&gt;If the grid was successfully loaded, create a list with all the movement patterns we need to check (specified in the question).&lt;/li&gt;
&lt;li&gt;For each pattern, create count how many trees we find in the grid and put the results in a list.&lt;/li&gt;
&lt;li&gt;Multiply all the tree counts.&lt;/li&gt;
&lt;li&gt;Print the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The code is fairly easy to follow and the points above should help understand what is going on. One thing to notice is the call to &lt;code&gt;toBigInteger()&lt;/code&gt;: If we just multiply the numbers as &lt;code&gt;Int&lt;/code&gt;, the result overflows (we get a negative number). Kotlin’s &lt;code&gt;Int&lt;/code&gt; type is only 32-bits long. To avoid that, we convert each tree count to a &lt;code&gt;BigInteger&lt;/code&gt; object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;Today’s puzzle was interesting, in particular because it let me play with a few more things. Like I mentioned above, I’m not sure I like extension methods in this case but it was a good exercise.&lt;/p&gt;

&lt;p&gt;Another thing was the integer overflow issue. I wonder if Kotlin, like Rust, is able to detect this sort of errors when the program is compiled in &lt;strong&gt;debug&lt;/strong&gt; mode. That would be very handy.&lt;/p&gt;

&lt;p&gt;Let’s see what day 4 brings us!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Advent of Code 2020 in Kotlin: Day 02</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Wed, 02 Dec 2020 18:19:49 +0000</pubDate>
      <link>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-02-5827</link>
      <guid>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-02-5827</guid>
      <description>&lt;p&gt;A new day, a new challenge. Day 02 of the &lt;a href="https://adventofcode.com/"&gt;Advent of Code&lt;/a&gt; gave us a “practical” problem: There’s a database of passwords and it has inconsistent data. We need to find the passwords that match the correct format and count them.&lt;/p&gt;

&lt;p&gt;The input is provided in a file, where each line is formatted as &lt;code&gt;&amp;lt;number&amp;gt;-&amp;lt;number&amp;gt; &amp;lt;letter&amp;gt;: &amp;lt;password&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How the input should be interpreted is different in parts 1 and 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1
&lt;/h2&gt;

&lt;p&gt;In this first part, the &lt;code&gt;&amp;lt;number&amp;gt;&lt;/code&gt; items in the line indicate the minimum and the maximum (respectively) number of times &lt;code&gt;&amp;lt;letter&amp;gt;&lt;/code&gt; should appear in the &lt;code&gt;&amp;lt;password&amp;gt;&lt;/code&gt; for it to be valid.&lt;/p&gt;

&lt;p&gt;Here’s how I solved it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.File&lt;/span&gt;

&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;PasswordEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;entryRegex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"""(\d+)-(\d+) +([a-z]): ([a-z]+)"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PasswordEntry&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;matchResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entryRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchEntire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matchResult&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="py"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matchResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;destructured&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PasswordEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;numberOfValidPasswords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

  &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.txt"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEachLine&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PasswordEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;numberOfValidPasswords&lt;/span&gt;&lt;span class="p"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfValidPasswords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;The solution is quite simple: We go over each line, use a &lt;code&gt;Regex&lt;/code&gt; to extract the components we are interested in, and then create an object representing the entry.&lt;/p&gt;

&lt;p&gt;The way I solved it is a bit over-engineered for such a simple problem, but it let me play with a few Kotlin concepts: Regexes and companion objects.&lt;/p&gt;

&lt;p&gt;Kotlin doesn’t support static methods like Java, which you would normally use to define a &lt;a href="https://en.wikipedia.org/wiki/Factory_method_pattern"&gt;Factory method&lt;/a&gt;. Instead, it offers companion objects: Inside your class, you can define another that provides methods to construct the object you want.&lt;/p&gt;

&lt;p&gt;So after we covert each line into a &lt;code&gt;PasswordEntry&lt;/code&gt;object, we call &lt;code&gt;isValid()&lt;/code&gt; to determine if the password is valid. If it is, we bump the count of valid passwords.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2
&lt;/h2&gt;

&lt;p&gt;The solution is almost identical, but the condition to determine if a password is valid changes. The &lt;code&gt;&amp;lt;number&amp;gt;&lt;/code&gt; entries indicate that &lt;code&gt;&amp;lt;letter&amp;gt;&lt;/code&gt; should be present in one of those indexes, but not both at the same time.&lt;/p&gt;

&lt;p&gt;Here’s the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;PasswordEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;firstOffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;secondOffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;companion&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;entryRegex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"""(\d+)-(\d+) +([a-z]): ([a-z]+)"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PasswordEntry&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ... &lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PasswordEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secondIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;firstOffset&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;xor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;secondOffset&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;Not much changed here. Since the &lt;code&gt;&amp;lt;number&amp;gt;&lt;/code&gt; entries represent the index, we subtract 1 from them. This way we get the correct offset in the string.&lt;/p&gt;

&lt;p&gt;Then in the &lt;code&gt;isValid()&lt;/code&gt; method, we use &lt;code&gt;Boolean.xor&lt;/code&gt; to check that only of those offsets has the letter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Done for the day
&lt;/h2&gt;

&lt;p&gt;This was a nice little program to work on. I was exposed to Kotlin’s regex facilities and companion objects. Not sure how I feel about latter yet. I need to play with them for a while longer to see what’s the advantage over static methods.&lt;/p&gt;

&lt;p&gt;Next up, Day 03.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Advent of Code 2020 in Kotlin: Day 01</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Tue, 01 Dec 2020 17:35:00 +0000</pubDate>
      <link>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-01-3d52</link>
      <guid>https://dev.to/heylucas/advent-of-code-2020-in-kotlin-day-01-3d52</guid>
      <description>&lt;p&gt;December is here, and with it came &lt;a href="https://adventofcode.com/"&gt;Advent of Code&lt;/a&gt;. Advent of Code is coding challenge that starts on December 1st and ends on December 25th. Every day a new puzzle is released. To win points (&lt;em&gt;stars&lt;/em&gt;) you need to complete the puzzles.&lt;/p&gt;

&lt;p&gt;Although I’ve followed the event in its past incarnations, I never took part in it. I decided to give it a go this year and since Kotlin has picked my interest recently, I chose to solve the challenges using the language. I’ll do this as an exercise, to learn more about the language and experiment.&lt;/p&gt;

&lt;p&gt;Every day, I’ll make a new post with my solution for the day’s challenge. If you don’t want spoilers, please try to solve it on your own first!&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;The question is fairly straightforward. We are given a list of numbers (transaction values) as input and need to find numbers that match a certain criteria.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 1
&lt;/h3&gt;

&lt;p&gt;In the first part of the challenge, we need to find two numbers that sum up to 2020. When we find them, we should return the result of multiplying those two numbers. That’ll be the answer to the problem.&lt;/p&gt;

&lt;p&gt;Although the question masks it with a story, this is just a 2sum problem: We want to find two numbers that sum up to a given target (in this case, 2020).&lt;/p&gt;

&lt;p&gt;Here’s how I solved it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.File

fun solve(numbers: Array&amp;lt;Int&amp;gt;) : Int? {
    val complementMap = mutableMapOf&amp;lt;Int, Int&amp;gt;()

    for (index in numbers.indices) {
    val number: Int = numbers[index]

    if (complementMap.containsKey(number)) {
        return number * complementMap.get(number)!!
    }

    val complement: Int = 2020 - number
    complementMap[complement] = number
  }

    return null
}

fun main() {
    val numbers = mutableListOf&amp;lt;Int&amp;gt;()

    File("input.txt").forEachLine { numbers.add(it.toInt()) }

    print(solve(numbers.toTypedArray()))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  How it works
&lt;/h4&gt;

&lt;p&gt;The idea behind this solution is that we can simply iterate over the array of numbers and store their complements in a map. For each number of the array, we check if it is present in the map. If it is, that means we have seen its complement before and we can return the answer. If we haven’t seen the number yet, we put it in the map keyed by its complement.&lt;/p&gt;

&lt;p&gt;With this, we get O(n) runtime complexity and O(n) space complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2
&lt;/h3&gt;

&lt;p&gt;The second part is similar. We need to find three numbers that sum up to 2020 and return the result of multiplying them. This boils down to a &lt;a href="https://en.wikipedia.org/wiki/3SUM"&gt;3SUM&lt;/a&gt;problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.File

fun solve(numbers: Array&amp;lt;Int&amp;gt;) : Int? {
    numbers.sort()
    val count = numbers.size

    for (i in 0..count) {
        var left = i + 1
        var right = count - 1

    while (left &amp;lt; right) {
       val sum = numbers[left] + numbers[right] + numbers[i]

        if (sum == 2020) {
              return numbers[left] * numbers[right] * numbers[i]
        } else if (sum &amp;gt; 2020) {
              right--
        } else {
              left++
            }
        }
    }
    return null
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  How it works
&lt;/h4&gt;

&lt;p&gt;This solution is a bit more involved. We start by sorting the array of numbers. For each number in the sorted array, we try to find two so that the three of them sum up to 2020.&lt;/p&gt;

&lt;p&gt;Since we know the array is sorted, we can be smart when we search for those two numbers. We use two pointers: One after the number we “fixed” and the other at the end of the array. If the sum of the three numbers is larger than 2020, we move the &lt;em&gt;right&lt;/em&gt; pointer to the left: We know there that then the sum will be either the same or less than current one. On the other hand, if the sum is less than 2020, we move the &lt;em&gt;left&lt;/em&gt; pointer to the right: The new sum then will either be the same or greater than the current one.&lt;/p&gt;

&lt;p&gt;When we find three elements that sum up to 2020, we just return the result.&lt;/p&gt;

&lt;p&gt;This gives us O(n^2) runtime complexity and O(1) space complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s all
&lt;/h2&gt;

&lt;p&gt;It was quite fun to give this problem a go with Kotlin. The language is quite nice to write in and fairly readable, although I do have my beefs with it. Once thing i don’t get is why the &lt;code&gt;for (i in 0..count)&lt;/code&gt; doesn’t require the keyword val/var since we are effectively declaring the variable i there. Seems like an inconsistency to me.&lt;/p&gt;

&lt;p&gt;On the next post, I’ll go over how I solved day 02’s problem!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>adventofcode2020</category>
      <category>aoc</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Would you pay for a React component?</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Sat, 14 Nov 2020 21:44:47 +0000</pubDate>
      <link>https://dev.to/heylucas/would-you-pay-for-a-react-component-51h0</link>
      <guid>https://dev.to/heylucas/would-you-pay-for-a-react-component-51h0</guid>
      <description>&lt;p&gt;Places like Code Canyon allow you to build and sell your own (mostly) Wordpress plugins. That made me think about React.&lt;/p&gt;

&lt;p&gt;Why not sell React components that do some useful integration?&lt;/p&gt;

&lt;p&gt;Would you pay for a component that solved a problem you have or would you build your own?&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Better code decoupling via delegates</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Mon, 27 Jul 2020 11:09:21 +0000</pubDate>
      <link>https://dev.to/heylucas/better-code-decoupling-via-delegates-1e6e</link>
      <guid>https://dev.to/heylucas/better-code-decoupling-via-delegates-1e6e</guid>
      <description>&lt;p&gt;I work on a system called NetNORAD. NetNORAD is responsible for monitoring hosts across our fleet. We do that to measure the rate of packet loss happening in our clusters and determine if there’s a problem.&lt;/p&gt;

&lt;p&gt;The system is comprised of three main components: A scheduler, an agent, and an aggregator. The scheduler decides what hosts the agents should monitor. The agents probe those hosts using UDP packets. The aggregators chew through all the data generated by the agents and try to come up with something useful.&lt;/p&gt;

&lt;p&gt;The scheduler stores the lists of hosts it generates in Zookeeper. The system looks a bit like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fheylucas.net%2Fwp-content%2Fuploads%2F2020%2F07%2FUntitled-drawing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fheylucas.net%2Fwp-content%2Fuploads%2F2020%2F07%2FUntitled-drawing.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A problem we had with our system until recently was the lack of backups. If something went wrong and the scheduler produced a bad list of hosts, we had no way of rolling back (only forward).&lt;/p&gt;

&lt;p&gt;To address this, we decided store a copy of the lists in an object store.&lt;/p&gt;

&lt;p&gt;A teammate of mine went about implementing this in a straightforward way: We had a class called &lt;code&gt;ZookeeperWriter&lt;/code&gt; that knew how to encode the data and write it to Zookeper. My colleague’s approach was to just add a new method to support the new storage layer. Whenever we were done writing to Zookeeper, we’d write to the object store.&lt;/p&gt;

&lt;p&gt;The code looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ZookeeperWriter: def writeShardedHostList(self, region, regionalHostList, globalHostList): blobs = { f"{region}\_regional\_host\_list": self.encoder.encode(regionalHostList), f"{region}\_global\_host\_list": self.encoder.encode(globalHostList) } try: self.writeBlobs(blobs) except ZookeeperError: raise else: self.writeShardedHostListToObjectStore(region, regionalHostList, globalHostList) def writeShardedHostListToObjectStore(self, region, regionalHostList, globalHostList): blobs = { f"{region}\_regional\_host\_list": self.encoder.encode(regionalHostList), f"{region}\_global\_host\_list": self.encoder.encode(globalHostList) } self.writeBlobsToObjectStore(blobs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For historical reasons, we have multiple “flavours” of &lt;code&gt;ZookeeperWriter&lt;/code&gt; classes: &lt;code&gt;VanillaZookeeperWriter&lt;/code&gt;, &lt;code&gt;ChocolateZookeeperWriter&lt;/code&gt;, etc. Each taking different arguments to encode and store. This made the code very cumbersome to extend when we needed to extend.&lt;/p&gt;

&lt;p&gt;There was also another problem. When we encode data, we convert it to a binary format and compress it using bzip2. With the implementation we had that conversion and compression was executed twice: Once to store the data in Zookeeper and another to send it to the object store. Since the amount of data to encode was quite large, this repetitive behavior caused a slowed of around 15 minutes to our system.&lt;/p&gt;

&lt;p&gt;To address the latter, we could just rearrange the code to avoid double encoding, but that needed to be replicated to every “flavour”.&lt;/p&gt;

&lt;p&gt;How could we solve that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Delegates
&lt;/h2&gt;

&lt;p&gt;Delegation is when an object handles a request (i.e., method call) by delegating the request to a different object.&lt;/p&gt;

&lt;p&gt;I know. That’s quite abstract.&lt;/p&gt;

&lt;p&gt;In the context of this problem, think of it this way: The logic to encode data shouldn’t be tied to the code that actually writes data to the storage layer. The code handling the storage layer should only care about moving bits from here to there.&lt;/p&gt;

&lt;p&gt;In our case, we had multiple &lt;code&gt;ZookeeperWriter&lt;/code&gt;s that knew both how to encode and how to store data. This made it difficult for us to reuse the compressed data and extend the system.&lt;/p&gt;

&lt;p&gt;To solve this, I came up with a two different concepts: a &lt;code&gt;BlobWriter&lt;/code&gt; and an &lt;code&gt;AssetWriter&lt;/code&gt;. A &lt;code&gt;BlobWriter&lt;/code&gt;is only concerned about writing bytes to a specific path in some kind of storage. It doesn’t care what the data is.&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;AssetWriter&lt;/code&gt;, on the other hand, does care about the data. It knows how it should be handled and how the paths should be set. But it does not care how or where the data is written to. &lt;strong&gt;It delegates the writing to storage to a &lt;code&gt;BlobWriter&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this new setting, our classes looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class BlobWriter: @abstractmethod def writeBlobs(self , blobs: bytes): passclass ZookeeperBlobWriter(BlobWriter): def writeBlobs(self, blobs: Dict[str, bytes]): # Do zookeeper stuff to write blobsclass ObjectStoreBlobWriter(BlobWriter): def writeBlobs(self, blobs: Dict[str, bytes]): # Do object store stuffclass AssetWriter: def \_\_init\_\_(self, blobWriterDelegates: List[BlobWriter]): self.writerDelegates = blobWriterDelegatesclass ShardedListsAssetWriter(AssetWriter): def write(self, region: str, regionalHostList: HostList, globalHostList: HostList): blobs = { f"{region}\_regional\_host\_list": self.encoder.encode(regionalHostList), f"{region}\_global\_host\_list": self.encoder.encode(globalHostList) } for writer in self.writerDelegates: writer.writeBlobs(blobs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is what the usage code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assetWriter = ShardedListsAssetWriter(writerDelegates=[ZookeeperBlobWriter(...), ObjectStoreBlobWriter(...),])...assetWriter.write(regionName, regionalHostList, globalHostList)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this change, adding or modifying different asset writers is quite easy. We only need to specify how the data should be encoded and its storage will be handled by the blob writers.&lt;/p&gt;

&lt;p&gt;On the other hand, adding or modifying blob writers (i.e., support different storage layers) is a breeze. We just need to write enough code to push bytes to the storage and all the encoding is taken care by the asset writers.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;Knowing how and when to decouple your code is an important skill. It can make adding/modifying a code base easy.&lt;/p&gt;

&lt;p&gt;Delegates are one tool we should keep in our arsenal to achieve that.&lt;/p&gt;

&lt;p&gt;How about you? What do you think about delegates? Would you approach this problem differently?&lt;/p&gt;

&lt;p&gt;I’d love to hear from you and learn different ways to solve the same problem.&lt;/p&gt;

</description>
      <category>python</category>
      <category>delegates</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>3 ways to filter through collections in C++</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Mon, 20 Jul 2020 08:00:00 +0000</pubDate>
      <link>https://dev.to/heylucas/3-ways-to-filter-through-collections-in-c-5938</link>
      <guid>https://dev.to/heylucas/3-ways-to-filter-through-collections-in-c-5938</guid>
      <description>&lt;p&gt;I spent some time last week reviewing a teammate’s diff (what we call pull-requests/patches where I work). The idea was pretty simple: The system processes a list of devices (i.e., hosts in our data centers) and applies a set filters to it.&lt;/p&gt;

&lt;p&gt;Their code was straightforward: They had an abstract class called &lt;code&gt;Filter&lt;/code&gt; that specified the interface. Each filter, in turn, received a vector of devices to process and spit out the filtered results. It looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Represents a host in the data center.struct Device;class Filter {public: ~Filter() {}; virtual std::vector&amp;lt;Device&amp;gt; filter(std::vector&amp;lt;Device&amp;gt;&amp;amp;&amp;amp; devices) = 0;};class MaintenanceStatusFilter : public Filter {public: std::vector&amp;lt;Device&amp;gt; filter(std::vector&amp;lt;Device&amp;gt;&amp;amp;&amp;amp; devices) override { return std::move(devices) | ranges::actions::remove\_if(somePredicate); }};class RackFilter : public Filter {public: std::vector&amp;lt;Device&amp;gt; filter(std::vector&amp;lt;Device&amp;gt;&amp;amp;&amp;amp; devices) override { return std::move(devices) | ranges::actions::remove\_if(someOtherPredicate); }};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon first inspection, that code is absolutely fine. &lt;code&gt;ranges::actions::remove_if&lt;/code&gt; makes understanding the code a breeze.&lt;/p&gt;

&lt;p&gt;The problem is what happens when we chain filters. When you do that, with the current code, you end up reallocating the vector whenever a filter was applied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MaintenanceStatusFilter maintenanceFilter;RackFilter rackFilter;auto filteredDevices = rackFilter.filter( maintenanceFilter.filter(std::move(devices)));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can we avoid that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Views
&lt;/h2&gt;

&lt;p&gt;C++ ranges offer a handy feature called &lt;a href="https://ericniebler.github.io/range-v3/index.html#tutorial-views"&gt;View&lt;/a&gt;. Views differ from iterators in that they can be easily composed and are lazily evaluated. You can chain multiple of them and the result only gets computed when it is needed.&lt;/p&gt;

&lt;p&gt;If we change our filters to be simple functions that look at a device and decide whether they should be removed or not, our code can be as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using ranges::views;auto filteredDevices = std::move(devices) | views::remove\_if(maintenanceStatusPredicate) | views::remove\_if(rackPredicate);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It doesn’t get much simpler than that.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what if I can’t use ranges?
&lt;/h2&gt;

&lt;p&gt;C++ ranges are fairly recent and chances are, if you’re working in an older code base, you won’t be able to use it. Or maybe you’re working with some other programming language that doesn’t have that sort of functionality. What do you do?&lt;/p&gt;

&lt;p&gt;Here’s a few things you can try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use a driver
&lt;/h2&gt;

&lt;p&gt;The idea is simple: Change our filter classes to only operate on a single device at a time, and move the logic to apply all the filters to a &lt;em&gt;driver.&lt;/em&gt; This allows us to decouple the filtering logic from the “iterate-over-the-vector” logic.&lt;/p&gt;

&lt;p&gt;Here’s what the filter classes would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Filter { ... virtual bool filter(std::Device&amp;amp; device) = 0;};class MaintenanceStatusFilter : public Filter {public: virtual bool filter(std::Device&amp;amp; device) override { return somePredicate(device); }};class RackFilter : public Filter {public: virtual bool filter(std::Device&amp;amp; device) override { return someOtherPredicate(device); }};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what the driver code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Driver {private: std::vector&amp;lt;Filter\*&amp;gt; filters\_;public: Driver(std::initializer\_list&amp;lt;Filter\*&amp;gt; filters) : filters\_(filters) {} std::vector&amp;lt;Device&amp;gt; operator()(std::vector&amp;lt;Device&amp;gt;&amp;amp;&amp;amp; devices) { std::vector&amp;lt;Device&amp;gt; result; for (const auto&amp;amp; device : devices) { bool keep = true; for (Filter\* filter : filters\_) { if (f-&amp;gt;filter(device)) { keep = false; break; } } if (keep) { result.push\_back(device); } } return result; }};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the driver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MaintenanceStatusFilter maintenanceStatusFilter;RackFilter rackFilter;Driver driver = {&amp;amp;maintenanceStatusFilter, &amp;amp;rackFilter};auto filteredDevices = driver(std::move(devices));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This option is quite verbose, but I find it quite easy to follow. The driver takes a list of filters to apply and, when called, applies the filters to each device. If a filter matches, it short-circuits the whole process and excludes the device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Template composition
&lt;/h2&gt;

&lt;p&gt;This one might be the least straightforward to implement, but using it is trivial.&lt;/p&gt;

&lt;p&gt;Just like in the previous example, we will change our filters to operate on single devices.&lt;/p&gt;

&lt;p&gt;We can define a template class that allows us to chain our filters into a single one. That class will be responsible for ensuring all chained filters get applied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template&amp;lt;typename F0, typename... F&amp;gt;class Chainer : Filter {private: F0 f\_; Chainer&amp;lt;F...&amp;gt; rest\_; public: Chainer(F0 f, F... rest) : f\_(f), rest\_(rest...) {} bool filter(const Device&amp;amp; device) override { if (f\_.filter(device)) return true; return rest\_.filter(device); }};template&amp;lt;typename F&amp;gt;class Chainer&amp;lt;F&amp;gt; : Filter {private: F f\_;public: Chainer(F f) : f\_(f) {} bool filter(const Device&amp;amp; device) override { return f\_.filter(device); }};template&amp;lt;typename... F&amp;gt;Chainer&amp;lt;F...&amp;gt; chain(F... fs) { return Chainer&amp;lt;F...&amp;gt;(fs...);}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s how we apply it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auto filter = chain(MaintenanceStatusFilter(), RackFilter());std::vector&amp;lt;Device&amp;gt; filteredDevices;for (const Device&amp;amp; device : devices) { if (!filter.filter(device)) { filteredDevices.push\_back(device); }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is quite a mouthful. Basically what we did was define a “recursive” template class that can take multiple filters as input. We specialize the class for the case it receives a single filter.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Chainer&lt;/code&gt; class is also made a child of &lt;code&gt;Filter&lt;/code&gt; so we can use it as such. When filter is called on a &lt;code&gt;Chainer&lt;/code&gt;, it will apply all its chained filters to the given device. If an early filter says the device should be removed, we short-circuit the whole process and don’t invoke the remaining filters.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;chain&lt;/code&gt; function is just a convenience so we can avoid typing the templated types.&lt;/p&gt;

&lt;p&gt;The usage code is quite simple, not that different from the driver code we had before.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;I can’t lie, C++ ranges are a great addition to the language and I can’t wait to use it in more places. That said, it is still important to know how to accomplish the same thing in different ways.&lt;/p&gt;

&lt;p&gt;How about you? What are your thoughts on C++ ranges? Can you think of other ways to solve this problem?&lt;/p&gt;

</description>
      <category>cpp</category>
    </item>
    <item>
      <title>Espresso shots and software development</title>
      <dc:creator>Lucas</dc:creator>
      <pubDate>Wed, 08 Jul 2020 14:08:58 +0000</pubDate>
      <link>https://dev.to/heylucas/espresso-shots-and-software-development-618</link>
      <guid>https://dev.to/heylucas/espresso-shots-and-software-development-618</guid>
      <description>&lt;p&gt;A programmer saying they love coffee must be a cliché at this point, but I am guilty as charged: I love coffee.&lt;/p&gt;

&lt;p&gt;As Ireland started to ease its lockdown and things are opening up, I finally had a chance to take a barista course. That was something I’d wanted to do for many years.&lt;/p&gt;

&lt;p&gt;After gaining insight into the processes that happen at a coffee shop, I couldn’t help but trace parallels to what we do as software engineers. That’s what I want to talk about today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prep work
&lt;/h2&gt;

&lt;p&gt;We started our session going over what needs to happen before you start making coffee.&lt;/p&gt;

&lt;p&gt;You start by calibrating the grinders, trying to find the coarseness that will let you pull an espresso shot to perfect. Once you have it, you move to to set the grinders with the correct timing to give you the right amount of coffee for a double shot.&lt;/p&gt;

&lt;p&gt;Skip all that and you’ll get (at best) subpar coffee that won’t make your customers happy.&lt;/p&gt;

&lt;p&gt;I find this similar to the work we do before embarking on a project. Gathering the requirements, sketching out what the system should look like, defining service-level indicators (SLIs) and objectives (SLOs), etc, are all part of the prep work we do as engineers.&lt;/p&gt;

&lt;p&gt;Planning before starting the work enables us to assess the risks and put our projects in a better position to succeed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Balance
&lt;/h2&gt;

&lt;p&gt;After we learn about the prep work, our instructor went over the espresso brewing process. If you brew it for too short a period, the coffee comes out too acidic. Brew it for too long and it comes out too bitter. There’s a fine balance between those two extremes that gives you perfect coffee.&lt;/p&gt;

&lt;p&gt;The same applies to software.&lt;/p&gt;

&lt;p&gt;If you under-engineer a system, you might find yourself in trouble when requirements change or demand increases. The lack of planning will result in pain points when it’s time to make the project scale.&lt;/p&gt;

&lt;p&gt;On the other hand, an over-engineered system can become a nightmare to understand and maintain. Changes become difficult and sometimes (most of the time?) lead to unexpected results.&lt;/p&gt;

&lt;p&gt;Finding balance is not easy, but it’s needed to achieve great software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean up
&lt;/h2&gt;

&lt;p&gt;One of the things our instructor mentioned was clean up.&lt;/p&gt;

&lt;p&gt;As you go about making lattes, spillage will happen. Too much of that and your workspace becomes a mess, you become less effective at preparing the orders and everything feels terrible.&lt;/p&gt;

&lt;p&gt;That’s why clean up is important. From time to time, he said, you have to stop and clean up the area so you can keep working.&lt;/p&gt;

&lt;p&gt;I relate this to what we call &lt;strong&gt;tech debt&lt;/strong&gt; in software development. As projects go on and deadlines grow tighter, we cut corners and sometimes make poor decisions that leave our code base in a bad state.&lt;/p&gt;

&lt;p&gt;Tech debt is not inherently bad. Just like a coffee shop has to accept some untidiness to get the orders going, so does software development. Sometimes it’s needed and the right thing to do.&lt;/p&gt;

&lt;p&gt;That untidiness only becomes a real problem when we take too long to clean it up. When the debt is not repaid, work becomes difficult. Tasks that should be simple take longer to complete.&lt;/p&gt;

&lt;p&gt;Just like the coffee shop needs periodic cleaning, so do our code bases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Although this posts draws parallels to software engineering topics, I’m sure you can see similarities to other areas as well.&lt;/p&gt;

&lt;p&gt;I hope you found this post interesting, and that it helped you stop and think deeper about our craft. Or, if anything, I hope it makes you appreciate the work that’s put into your lattes a bit more!&lt;/p&gt;

</description>
      <category>practices</category>
      <category>thoughts</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
