Advent Of Vim, Episode 4

Advent Of Vim, Episode 4

Solving AdventOfCode challenges in 30 seconds using VIM and Neovim!


5 min read

AdventOfVim is part of the S909 project.

1. Getting Started

To begin, access today's challenge and carefully read the instructions below before attempting to solve it.

New here? scenario1 and scenario2 might be unfamiliar territory. These sprints are designed to stretch your limits – you'll need to tackle the problem from both angles, or your solution won't fly. So, if you're content to stay within your comfort zone, this sprint isn't for you. Start with the first episode and give it a go yourself. Spend at least 15 minutes grappling with both scenarios before peeking at the solutions.

Remember, make sure that you are in sync with your team, if you don't have a team yet submit your application here

Good luck!

1.2 Sample data

The provided sample data should be used for testing the commands. Once you feel comfortable and confident, you can apply these commands to your actual input data.



Expected output:

  • part1: 2

  • part2: 4

2. Solutions

This guide assumes you've already watched the accompanying walk-through YouTube video. If you haven't, please do.

2.1 The First Scenario

2.1.1 Part One

To achieve our goal of parsing each line, checking if one range fully contains the other, and then printing the final score, we can leverage the power of awk.

First, let's ensure that awk can easily distinguish each column field by removing unnecessary delimiters and replacing them with spaces. Execute the following command in vim:

:%s/\D/ /g

Now, let's proceed with awk:

:%!awk '{s+= ($1 >= $3 && $2 <= $4) || ($3 >= $1 && $4 <= $2)} END{print s}'

2.1.2 Part Two

For the second part, our objective is to test if the two ranges are overlapping. One way to accomplish this is as follows:

:%!awk '{s+= ($1 >= $3 && $1 <= $4) || ($3 >= $1 && $3 <= $2)} END{print s}'

We've successfully solved the whole challenge. Well done!

2.2 The Second Scenario

Now, let's turn our attention to the second scenario. This time, we'll be writing a Vim script to achieve the desired outcome. Here's a step-by-step guide:

  1. Read all lines.

  2. Split each line by non-digit characters using split(x, '\D').

  3. Convert the resulting substrings to numbers using str2nr().

  4. Compare both ranges.

  5. Echo the sum.

Feel free to craft your Vim script based on these guidelines. This approach provides a clear roadmap for processing the data and obtaining the desired result. Good luck!

5. Exercises

In case you care about this content, follow me on Twitter. I sometimes tweet the hints and solutions for these exercises, however I want you to spend some time with the exercises on your own and with your team.

Twitter is too noisy, make sure to enable notifications to be notified otherwise you'll miss out.

  1. No matter which method we choose, some repetitions are unavoidable. However, our initial task is to streamline the data into a consistent format. Specifically, we want all ranges on the left to be smaller than those on the right. use awk to achieve this.

  2. Using the refined data, solve Part1 and Part2. do you notice the difference—no need to repetitively test range2 against range1.

  3. For a deeper dive into useful Vimscript functions, let's explore an alternative to split(x, '\D'). Instead, use substitute(), then split(). Finally, achieve the same result using only matchlist().

  4. In real-world scenarios, data often arrives in messy formats. Challenge yourself to solve Part1 and Part2 using only regex, treating the ranges as strings. Refer to the provided walkthrough video for hints. Generate ranges on each line, then utilize regex to compare them, and ultimately print the sum. Additionally, consider using tr, for example if echo '1 2 3 4 5' | tr -d '1 2' that means range [1,2] is fully within because it was deleted from 1 2 3 4 5.

    • You need to integrate your daily programming language inside Vim so that you can use it to generate data, manipulate data, and solve any hurdles that you might come across. This will help you save time and increase productivity.

      • Modify your setup so that you can use the language that you know best within Vim anytime you like.

      • Your main language may offer superior tools. For example, instead of re-implementing the wheel and wasting time, what if we can say rangeA in rangeB and x in rangeB? We can save a lot of work.

      • Help Vim understand your language so that it can call your language compiler seamlessly.

      • If your main language doesn’t have these cool features, you may already be familiar with libraries that you load all the time and maybe they are powerful. For example, if you are using JavaScript, Imagine that there is a super famous library called XY that gives us two awesome functions: range(1,10).in(range(2,4)) or in(range(1,10), range(2,4)). It would be awesome if we were able to solve the whole challenge using something like that.

      • In normal/insert mode, you need to be capable of using your language and capturing its output and directly inserting it in the current buffer you are working at or replacing the line that it was invoked from (map a special key so that it can happen in less than a second). For example, if you are using JavaScript and you type log('hi'), then if you try to call node, it will throw an error that log doesn’t exist. So, figure out a way to load all your favorite modules and libs automatically every time you call node.

      • Now that you have enhanced your setup, and you can evaluate your main language in microseconds anywhere in Vim, it’s time to resolve part 1 and part 2 using your language.

  5. Share your setup for the previous exercise in our Discord channel #tips. Please mention the programming language you use.