In my previous post, I introduced you to the Advent of Code programming challenge, and explained how I’m going through the days, solving both parts of each puzzle. Continuing on, today we have day 6. In this challenge, you’re competing with your neighbors in the annual Christmas house decorating contest. Since you helped Santa fix up his nice list, he’s helping you out. You have a 1000 x 1000 grid that represents lights. Santa has sent you directions on how to light up each light (see the directions here). The directions state whether to turn on, turn off, or toggle the lights in the specified coordinates. These coordinates are specified in starting and ending X/Y pairs, for example, “turn on 0,0 through 5,5”. Your challenge is to determine how many lights are turned on at the end of the lighting instructions.

As before, the first step is to load the instructions into a variable. You should be familiar with this by now…

In the next step, I’ll load this data into a temporary table. In conjunction with this, I will also determine if the lights are being turned on, turned off, or toggled, and what the two sets of coordinates are:

One thing that I want to point out here is that the “Toggle”, “TurnOn” and “TurnOff” columns are of the BIT data type. These are being set by a neat little feature: if the value being passed into this data is a zero, then the bit will be off / false / 0. If the value is not zero, then the bit value with be on / true / 1. Any non-zero value (even a negative number) will set a bit to true. What I am doing is using the CHARINDEX function to return whether the specified text is found in the search string. If it is found, then it will return the starting position of the specified text; if it is not found then it will return 0. So this will very nicely set the BIT column for me.

At this point, we have all of the instructions loaded into a table. Now we need to process them. There are two ways to represent this grid – either a table with 1001 columns (1 for the row number), and 1000 rows. Or a table with 3 columns (X position, Y position, and a column to store the current setting of the light), and a million rows. I’m going to go with the million-row version:

Notice that the “Tally” cte was modified to use the “Thousands” cte, so that only a thousand rows are generated.

Looking through the instructions, you notice that each step needs to be performed in order, and lights at a specific point can be flipped multiple times. This means that we need to utilize a looping mechanism. And in SQL Server, a looping mechanism means just one thing… I need to use my ugly foe, a cursor, so that all of the updates for the first instruction are performed before starting the next one. So this next bit of code will create the SQL statement to be run for each statement, and it will use a cursor to present this to be run instruction by instruction. By creating the SQL statement, this also means that I’ll be running some dynamic SQL. The where clause controls what X/Y ranges are updated.

And since the requirement is to count how many lights are on:

Another way that this could have been handled is to count the number of rows where IsLightOn = 1.

Part two: after you have got this up and running, you realize that it doesn’t really look that great. How are you going to win the contest with this? So you go back and look over the instructions, and you realize that you interpreted the instructions wrong. What you’re supposed to be doing is adjusting the brightness level of the lights in that grid. A turn on command means to increase the brightness level by one level. A turn off command means to decrease it by one brightness level (but it can’t go below 0 – off is off, and it won’t go any darker than that!). And a toggle command means to increase the brightness level by two levels. And now you need to know what the final brightness level is of all of the lights. Fortunately, this means that only minor changes are necessary.

  1. Add the following line to be inserted between lines 6 and 7 of the “Create Grid” block of code so that the brightness level can be kept track of:

Replace lines 17 and 18 in the “Create Grid” block of code with the following so that the brightness level is initially set to zero:

Insert the following code between lines 8 and 9 of the “Update Grid” code to control the modification of the brightness level:

And finally, replace the “Return results” code block with the following code so that you can see what the final results are: