Advent of Code 2024

Hahaha…

Flip… flip… flip…

1 Like
Day 3 Spoiler

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
1 Like

Here is my whole solution:

Day 3 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
2 Likes

You make it look so easy Kem.

1 Like
My Day 3 code
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
1 Like

Morning person over here. :sunny:

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)

2 Likes

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 :joy:)

I figured out how to do the other format just now.

RegEx Spoiler

"(?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)

Day 1 Hack

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.

Day 4 spoiler

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.

1 Like

Part 1 is done. (and didn’t take much time at all)

image

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.

1 Like

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.

Day 4 Part 2 Spoiler
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.

2 Likes

Day 5 looked a lot harder than it was.

Day 5 Part 1 spoiler

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.

Day 5 Part 2 spoiler

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. :face_with_symbols_over_mouth:

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.

Also saw this and laughed out loud.

2 Likes