Hahaha…
Flip… flip… flip…
Hahaha…
Flip… flip… flip…
If I’d had to do Regex, I’d give up right now. Fortunately, I wrote a Parse function a few years ago, and it did the trick:
var pText As String
if partNo = 1 then 'Use data as-is for part 1
pText = pzlData
Else 'Exclude the 'don't() data for part 2
pText = parseTxt("do()"+pzlData+"don't()","do()","don't()")
end if
Here is my whole solution:
Private Shared Function GetResult(input As String, considerDos As Boolean) As Integer
const kPatternWithoutDos as string = "mul\((\d{1,3}),(\d{1,3})\)"
const kPatternWithDos as string = "do\(\)|don't\(\)|mul\((\d{1,3}),(\d{1,3})\)"
var result as integer
var rx as new RegEx
if considerDos then
rx.SearchPattern = kPatternWithDos
else
rx.SearchPattern = kPatternWithoutDos
end if
var isEnabled as boolean = true
var match as RegExMatch = rx.Search( input )
while match isa object
var matchResult as string = match.SubExpressionString( 0 )
select case matchResult
case "do()"
isEnabled = true
case "don't()"
isEnabled = false
case else
if isEnabled then
var d1 as integer = match.SubExpressionString( 1 ).ToInteger
var d2 as integer = match.SubExpressionString( 2 ).ToInteger
result = result + ( d1 * d2 )
end if
end select
match = rx.Search
wend
return result
End Function
You make it look so easy Kem.
for partNo as Integer = 1 to 2
'Process input data
var pText As String
if partNo = 1 then
pText = pzlData
Else
pText = parseTxt("do()"+pzlData+"don't()","do()","don't()")
end if
var mulOps As Integer = pText.CountFields("mul(")-1
var s0,s1,ProductSumP1,ProductSumP2 As Integer = 0
for i as Integer = 1 to mulOps
s0 = pText.IndexOf(s0,"mul(")
s1 = pText.IndexOf(s0+1,")")
'extract arguments
var arg As String = pText.Middle(s0+4,s1-s0-4)
'check for valid argument syntax
var argF As string = Filter(arg,"0123456789,",true)
if argF = arg then
'No invalid characters so far
var aArgs() As String = arg.Split(",")
if aArgs.LastIndex=1 then
if aArgs(0).Length>0 and aArgs(1).Length>0 then
'Args are valid
var prduct As Integer = (aArgs(0).ToInteger) * (aArgs(1).ToInteger)
ProductSumP1 = ProductSumP1 + prduct
end if
end if
end if
s0=s0+1
next i
PrintLine "Part "+partNo.ToString+" solution: "+str(ProductSumP1)
'P1 example data answer = 161
'P2 example data answer = 48
PrintLine "Time: "+TimeFormat(Microseconds-et)
et = Microseconds
next partNo
Morning person over here.
Day 3 parts 1 and 2 completed.
I find visualizing the data by loading data and results into a list very helpful for figuring out what’s going on.
I thought day 3 was pretty straightforward, especially with an assist from @Kem_Tekinay’s excellent RegExRX app. (RegEx really helped me with this challenge and Kem’s app is a great tool to have in your kit)
Our RegEx’s were very close, Kem! Thanks for being a RegEx guru to the community for many-a-moon.
rx.SearchPattern = “(?mi-Us)(do()|don't())|mul([0-9]+,[0-9]+)”
Must be a typo there. That would match “mul44,55”, not “mul(44,55)”.
I think it might’ve gotten “forum-a-fied” when I was trying to figure out how to post spoilers. (which didn’t work out so great )
I figured out how to do the other format just now.
"(?mi-Us)(do\(\)|don\'t\(\))|mul\([0-9]+,[0-9]+\)"
Realized I hadn’t done part 1 of day 1.
Completed now.
I did a total “hack” for this one (but was able to get it done very quickly and it runs very quickly)
Added a preceding “#” to first value:
if n = 0 then
self.right_list.Add("#" + self.initial_values(n).Right.StringValue)
else
self.right_list.Add(self.initial_values(n).Right.StringValue)
end if
And then used String.CountFields to get a quick and dirty count of the value.
dim right_vals_chunky as String = string.FromArray(right_list,"#")
for n as Integer = 0 to self.results_grid.LastRowIndex
dim left_val as String = "#" + self.results_grid.CellTextAt(n,0)
dim count as integer = right_vals_chunky.CountFields(left_val) - 1
self.results_grid.CellTextAt(n,1) = count.ToString
self.results_grid.CellTagAt(n,1) = count
next
Would never use this in real code, but hey, it worked!
Day 4 is in the books.
I think I made it more complicated than it needed to be.
I turned the input into a two-dimensional array, then navigated looking for an “X”. If found, I called a function that looked in every legal direction using a series of IF statements. But this morning I realized that I could have just looked from each point down, right, and down-right for “XMAS” or “SMAX”. I could have put that into a loop.
I did something close to that for part 2 and was done in one IF statement.
Part 1 is done. (and didn’t take much time at all)
Part 2 looks like it might take some time which I don’t have too much of at the moment, or maybe I’ll have an epiphany as I’m doing other tasks…
Part 2 is easier than part 1, FWIW.
@Kem_Tekinay - Maybe I’m missing something obvious; very full day over here, so it’s possible the solution will spring forth like Athena from the head of Zeus when I have a chance to give it a proper think.
Understandable. I stumbled on it really by accident while coding it.
So it wasn’t hard and sadly I did not see Athena emergent.
Part 2 ended up being about as easy as part 1 (for me) once I removed an especially dunderheaded little piece of code written by the CDABWIC (chief dunderhead and bottle washer in chief) aka, me.
I was bounds checking twice, and as a result was inadvertently ignoring the last two columns of characters. (e.g. for the example data I was getting 7 matches because two of the “x-mas-es” have letters in the 9th column)
Day 4 complete.
I used a Point2D class for part one, to track adjacent letters, which worked well. Then I tried to reuse it for part 2, but it just made things more complicated, so I dropped it and my Part 2 code was half as long as part 1.
xmasCount=0
'Loop bounds reduced so that grid array bounds won't need checking
For r as integer = 1 to inpData.LastIndex-1
for c as Integer = 1 to maxLen-1
'Scan for letter "A"
if grid(r,c)="A" then
if ((grid(r-1,c-1)="M" and grid(r+1,c+1)="S") or (grid(r-1,c-1)="S" and grid(r+1,c+1)="M")) then
if ((grid(r+1,c-1)="M" and grid(r-1,c+1)="S") or (grid(r+1,c-1)="S" and grid(r-1,c+1)="M")) then
xmasCount = xmasCount+1
end if
end if
end if
next c
Next r
So yes, I agree Part 2 was much simpler.
Day 5 looked a lot harder than it was.
I parsed the rules into an array of Pair
. For each set of pages, I cycled through the rules and checked the position of the page on the left vs. the position of the page on the right. If either didn’t exist or those pages were in order, I moved onto the next rule. If they were out of order, I jumped to the next set of pages.
If all rules passed, I added its middle value to the result.
For each set of pages, I cycled through all the rules, making note of which ones were applicable. If all the pages were in order, I moved onto the next set. Otherwise, I cycled through the applicable rules and swapped pages for the ones that were still failing, and repeated that until all the pages were in order.
Day 5 complete.
Again part 2 gave me a bit of trouble. Again I was the culprit (probably because I can’t give this my full attention because of a full work day). I had a sloppy off-by-one error, again.
I’ve come up with a magic incantation for making a sloppy coding error…
“ABRA-CDABWIC”
This is based on my earlier self-description above:
CDABWIC (chief dunderhead and bottle washer in chief) aka, me.