using sqlite3 to solve an advent of code problem
Soon we will be heading into advent season. Which means it is time for Advent of Code again! Yay.
I thought of last year and how I had used sqlite3 to solve one of those problems and thought I would write it up.
The first part of the first problem is a good place to start.
You get a list of numbers from a submarine that represent depth numbers. You have to determine the number of times the depth INCREASES.
The first thing I did was get the example numbers stored into a simple text file.
You can import a CSV file into a table in sqlite3 like this.
CREATE TABLE measures ( val INTEGER ); .mode csv .import realdata.txt measures
Those statements will create a table called measures that will hold all of our depth measurements from the submarine.
Then it will load the integer values into the table with one per row. Your table will look like this
sqlite> select * from measures; val 199 200 208 210 200 207 240 269 260 263
Next we want to do some math on that value. Specifically we want to subtract the value in the previous row.
SQL has no real concepts of ordering so you have to be specific. We will use a lag plus an explicit order so sqlite3 will give us the correct answer.
This is the first step we will build up to a final answer as we go.
sqlite> SELECT val AS a, lag(val) OVER (ORDER BY rowid) AS b FROM measures; 199| 200|199 208|200 210|208 200|210 207|200 240|207 269|240 260|269 263|260
The query above selects the depth column and a lag of the depth column using the built in rowid from the measurements.
The LAG function will select the result from row in the partition. In our case we are ordering by rowid so it will always end up giving us the previous value or NULL in the case of the first row.
This step was to get both values into a single row, we will use this to compute the difference.
sqlite> SELECT CASE WHEN a-b>0 THEN 1 ELSE 0 END AS c FROM ...> (SELECT val AS a, lag(val) OVER (ORDER BY rowid) AS b FROM measures); 0 1 1 1 0 1 1 1 0 1
Now we use a CASE WHEN statement to output a 1 or 0 depending if there is an increase in depth or not.
And then we are at the last step, we just need to sum up the values and we will have our answer.
The full query is listed here
SELECT sum(c) FROM (SELECT CASE WHEN a-b>0 THEN 1 ELSE 0 END AS c FROM (SELECT val AS a, lag(val) OVER (ORDER BY rowid) AS b FROM measures));
For the example provided this will output 7 which is correct!
Amazing things can be done with sqlite3.