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 8. In this challenge, we have an input file of strings delimited with a double-quote character. Inside the string may be some escaped characters. There are three types of escape sequences being used:
- \\ – symbolizes a single \
- \” – symbolizes a single double-quote character
- \x## – symbolizes a single hexadecimal character
Part 1 of the challenge is to return the difference between the coded length of the string (including the delimited double-quotes) and the in-memory length of the string (after the escaped characters are handled).
As always, I start off with loading the input file:
1 2 3 |
DECLARE @InputText VARCHAR(MAX); SELECT @InputText = REPLACE(FileText, CHAR(10), '') FROM OPENROWSET(BULK 'D:\AdventOfCode\Day08.txt', SINGLE_CLOB) UselessAlias(FileText); |
The next step is to:
- Get the length of the string as entered
- Replace all \\ and \” with a single pipe character (|)
- Get the length of this new string. The difference between #1 and this value is the number of characters not stored in memory from the original string, for just these two escape sequences.
- With the new string, replace all \x with a |, and get the difference in length of these two strings. This tells me the number of hex escape sequences going on. This number times three is the number of characters that the code has that will not be in memory.
With this information, I just need to determine the in-memory string length by subtracting from the value in #3 above the delimiting double-quote characters (2) and then (3 * the value returned in #4 above). All that is left is to sum up the difference between the code string length and the in-memory length.
The code to perform all of this is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
WITH cte1 AS ( SELECT ItemNumber , Item , LEN(Item) AS CodeLength , LEN(ca1.ShortString) AS StringLength , LEN(ca1.ShortString) - LEN(REPLACE(ca1.ShortString, '\x','|')) AS HowManyHexEscapesAreInTheString FROM Sandbox.dbo.DelimitedSplit8K(@InputText, CHAR(13)) CROSS APPLY (SELECT REPLACE(REPLACE(Item, '\\', '|'), '\"', '|')) ca1(ShortString) WHERE Item > '' ), cte2 AS ( SELECT ItemNumber , Item , CodeLength , StringLength - (HowManyHexEscapesAreInTheString * 3) - 2 AS StringLength FROM cte1 ) SELECT SUM(CodeLength - StringLength) AS Part1 FROM cte2; |
For Part 2, we need to generate the escaped string for the original string. This needs to replace a \ with a \\, replace a ” with a \”, and then perform the new length and delta calculations. It’s important to replace the \ before the “, or you will end up replacing the \ that is escaping the “. This ended up adding just four simple lines of code to the above, so I’m just going to post the complete code here with the new lines of code highlighted:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
WITH cte1 AS ( SELECT ItemNumber , Item , LEN(Item) AS CodeLength , LEN(ca1.ShortString) AS StringLength , LEN(ca1.ShortString) - LEN(REPLACE(ca1.ShortString, '\x','|')) AS HowManyHexEscapesAreInTheString , LEN(ca2.LongString) AS LongStringLength FROM Sandbox.dbo.DelimitedSplit8K(@InputText, CHAR(13)) CROSS APPLY (SELECT REPLACE(REPLACE(Item, '\\', '|'), '\"', '|')) ca1(ShortString) CROSS APPLY (SELECT '"' + REPLACE(REPLACE(Item, '\', '\\'), '"', '\"') + '"') ca2(LongString) WHERE Item > '' ), cte2 AS ( SELECT ItemNumber , Item , CodeLength , StringLength - (HowManyHexEscapesAreInTheString * 3) - 2 AS StringLength , LongStringLength FROM cte1 ) SELECT SUM(CodeLength - StringLength) AS Part1 , SUM(LongStringLength - CodeLength) AS Part2 FROM cte2; |