Advent of Code 2022

There might be a way to do it, but I imagine that will lead to abuses.

  • I start a fake Google account to look at the puzzle and write my solution.
  • With code in hand, I log into my real account, grab the data, and run my already-written code.
  • I am now at the top of the leaderboard, having solved both parts in 7 seconds.

:confused:

Sure, one can cheat. But some do that with ChatGPT already. too.

But I requested this particularly for the private boards, where people know and trust each other not to cheat - hopefully.

I don’t even want the default display to change, which always starts at GMT-5. I just want the start time recorded and delivered in the JSON data, so that the plugin I linked to above would be able to use that for the “adjusted” puzzle times.

1 Like

BTW, the guy who solved day 1 in 52 seconds (or whatever) posted a video of him doing it. He used the node console in his browser, which is kind of impressive.

There are some who write extra scripts so that they just have to paste the puzzle description and the test input and output data, which trains the AI, and then ask it to apply the learned to the puzzle input.

There’s currently a lot of criticism about ChatGPT because when it relies on data from the internet, it often gives wrong answers in a very confident way that looks right.

But with AoC, there’s training data, which makes it much more reliable. It might later still get things wrong with the more complex puzzles. We’ll see. I remember from 2021 that often my solutions were wrong even though I got the test results right because I missed a tiny detail (for instance, in a path finding puzzle, the test input only had a path in 3 directions, but the real input required a path with all 4 directions, which my algo didn’t get right at first.)

The Leaderboard is just a side artifact of having fun together with these puzzles… and we are not going to win against Kem anyway so… :smiley:

3 Likes

Are you daring me?!?!?!

1 Like

I’ve been typing with my toes, just to give you all a chance.

:stuck_out_tongue:

4 Likes

Like some of the others, I used the specs from the example when trying to solve part 2. Then, reread the problem, and misinterpreted what needed to be done. Reread it again, and finally figured it out. Fortunately, all of the needed data had been calculated in part 1.

Day 7 Spoiler
Class fldrItm
 Parent as fldrItm
 child() as fldrItm
 fullpath as string 'Full path name
 itmSize as integer 'total space used by files in this dir
 chTotal as integer 'total space used by subdirs
 dirTotal as integer 'total of itmSize & chTotal
end class


Public Sub Day07()
  tf3.Text = "Day07 Parts 1 & 2"+EndOfLine+EndOfLine
  inpReset 'Init input data
  dim txt As String = rdLine
  dim cDir As String = ""
  dim dSize As Integer = 0
  dim cNode As new fldrItm
  cNode.Parent=nil
  cNode.fullpath = "/"
  dim nodeList() As fldrItm
  nodeList.Append cNode
  dim topNode As fldrItm = nodeList(0)
  'Input read and process loop
  while txt<>""
    if left(txt,1)="$" then
      'process cmd
      select case MidWords(txt,2,1)
      case "cd"
        'Navigate directories
        select case MidWords(txt,3,1)
        case "/"
          'root dir
          cNode = topNode
          cDir = cNode.fullpath
        case ".."
          'up one level
          if cNode.Parent = Nil then
            cNode = topNode
          Else
            cNode = cNode.Parent
          end if
          cDir = cNode.fullpath
        else
          'down one level
          dim makeNew As Boolean
          dim testname As string = cNode.fullpath +" "+MidWords(txt,3,1)
          if cNode.child.Ubound<0 then
            'No child nodes, so add this one
            makeNew = True
          else
            'check child nodes for match
            makeNew = True
            for i as Integer = 0 to cNode.child.Ubound
              if cNode.child(i).fullpath = testname then
                makeNew = False
                'set new node to the child
                cNode=cNode.child(i)
                'get current name
                cDir = cNode.fullpath
                exit for i
              end if
            next
          end if
          if makeNew then
            'subdir doesn't exist, so add it
            nodeList.Append new fldrItm
            dim lastNode As fldrItm = nodeList(nodeList.Ubound)
            lastNode.fullpath = testname  '<--- Arrrrgh, this was the culprit
            lastNode.Parent = cNode
            cNode.child.Append lastNode
            cNode=lastNode
            cDir = cNode.fullpath
          end if
        end select
      case "ls"
        'do nothing
      end select
    else
      'Input is not a command, so scan for files and sizes
      select case MidWords(txt,1,1)
      case "dir"
        'do nothing
      Else
        'add file size to dir total
        dSize = val(LeftWords(txt,1))
        cNode.itmSize = cNode.itmSize + dSize
      end select
    end if
    txt=rdLine 'read next input line
  wend
  '
  'The full node tree is now built.
  '
  'Recursive size calc:
  dim totalfilesize As Integer = calcSize(topNode,0)
  '
  'Find part 1 solution by totalling all dirs of size 100000 or smaller
  '
  Dim grandtotal As Integer = 0
  for i as Integer = 0 to nodeList.Ubound
    nodeList(i).dirTotal = nodeList(i).itmSize + nodeList(i).chTotal
    if nodeList(i).dirTotal<=100000 then
      grandtotal = grandtotal+nodeList(i).dirTotal
    end if
  next
  tf3.AppendText "Part 1 solution: "+str(grandtotal)+EndOfLine
  '
  'Part 2
  '
  dim tgtsize As Integer = topNode.dirTotal-40000000
  tf3.AppendText "Total used: "+str(topNode.dirTotal)+EndOfLine
  tf3.AppendText "Target size: "+str(tgtsize)+EndOfLine
  dim bestnode As Integer =-1
  dim bestsize As Integer =70000000
  for i as Integer = 0 to nodeList.Ubound
    if nodeList(i).dirTotal>=tgtsize and nodeList(i).dirTotal<bestsize then
      bestsize = nodeList(i).dirTotal
      bestnode = i
    end if
  next
  if bestnode>=0 then
    tf3.AppendText "Part 2 solution: "+str(bestsize)+EndOfLine
  end if
End Sub


Public Function CalcSize(nd As fldrItm, level As Integer) as Integer
  'Traverse the node tree and calculate directory sizes
  'If no child nodes, just return total at this level
  if nd.child.Ubound < 0 then
    return nd.itmSize
  else
    'Calculate total size of child nodes
    nd.chTotal = 0
    for i as Integer = 0 to nd.child.Ubound
      nd.chTotal = nd.chTotal + CalcSize(nd.child(i), level+1)
    next
    Return nd.itmSize+nd.chTotal
  end if
End Function

'Note Code for the text functions LeftWords, RightWords, MidWords and WordCount are not shown.
'They are the word equivalents of the character based functions Left, Right, Mid and Len.

1 Like

I see @Paul_Lefebvre is now also part of the private AoC leaderboard. Welcome!

2 Likes

Today I couldn’t come up with a good algorithm.

Spoiler

Tried initially to rotate the input field (I have already code for that) so that I could simply go over each line, but then it got too complicated to rotate the coordinates when I wanted to record a tree’s visibility. So I wrote instead separate code for up/down and for left/right scanning. Which then worked out fine the first try.
Then part 2 - where my code wasn’t going to work, so I had to end up writing a function that would advance the x/y coord depending on a direction. All that felt familiar (we had something like that in 2021 as well). Not happy with my code. I like to see more elegant solutions.

Sooo tired.

I had all kinds of mental blocks today and made silly errors. I’m guessing my code looks similar to yours.

I’m not happy with my today puzzle code. It works, but… :woozy_face:

I just gave Day 1 a try using Atari BASIC. Haven’t had a chance to look at others yet.

2 Likes

Garry, seems you partook in Day 7 - but forgot to upload your code?

The first part, yes. The second I made more concise by using only one nested loop over x, y and direction (0-3). And used a subroutine that moves x/y according to the direction. Makes it much more readable, I think.

BTW, I need to stop staying up all night. This evening the gold points are all yours to get again :slight_smile:

Spoiler (Code)

My code for part 2:

Private height As Integer
Private width As Integer

Private Function Solve2(input as TextParser, part as Integer) As Variant
	dim result as Integer
	
	dim field() as VarArray = input.Section(0).VariantsSepBy("")
	
	dim w as Integer = field(0).Count
	dim h as Integer = field.Ubound+1
	self.width = w
	self.height = h
	
	// Visit every tree inside the perimeter,
	// counting how many trees are visible in each of the 4 directions
	for y0 as Integer = 1 to h-2
		for x0 as Integer = 1 to w-2
			dim score as Integer = 1
			for dir as Integer = 0 to 3
				dim x as Integer = x0
				dim y as Integer = y0
				dim limit as Integer = field(y).ar(x)
				dim dist as Integer = 0
				while advance(x, y, dir)
					dist = dist + 1
					if field(y).ar(x) >= limit then
						exit
					end if
				wend
				score = score * dist
			next
			if score > result then
				result = score
			end if
		next
	next
	
	return result
end function

Private Function advance(ByRef x as Integer, ByRef y as Integer, dir as Integer) As Boolean
	select case dir
	case 0
		x = x + 1
	case 1
		y = y + 1
	case 2
		x = x - 1
	case 3
		y = y - 1
	end select
	return x >= 0 and y >= 0 and x < width and y < height
end function

It sounds like my solution for Day 8 part 1 was the same as others. My part 2 may be different.

I’ve now uploaded my AOC project here after stripping out a lot of detritus.

I’m in the process of refactoring, and my new code is slower but worlds better than it was. I’ll post soon…

My code is so much cleaner now. I wish I had done it this way last night, I’d have been done in 5 minutes.

Spoiler: 2022 Day 8

I enhanced my existing ObjectGrid class to include functions like Above( member As GridMember ) I also defined a Delegate, NextDelegate. Finally, I defined the class as Iterable and an Iterator.

The code then became simple. I convert the input to an ObjectGrid, then call for each square as GridMember in grid. I create an array of NextDelegates that I can cycle through on each square to keep fetching the next one in a given direction, then make decisions based on that.

For example:

Private Function CountVisible(grid As ObjectGrid) As Integer
  var lastRowIndex as integer = grid.LastRowIndex
  var lastColIndex as integer = grid.LastColIndex
  
  var directionals() as ObjectGrid.NextDelegate
  directionals.Add AddressOf grid.Above
  directionals.Add AddressOf grid.Right
  directionals.Add AddressOf grid.Below
  directionals.Add AddressOf grid.Left
  
  var count as integer 
  
  for each square as GridMember in grid
    if square.Row = 0 or square.Column = 0 or square.Row = lastRowIndex or square.Column = lastColIndex then
      count = count + 1
      continue for square
    end if
    
    var height as integer = square.RawValue
    
    for each directional as ObjectGrid.NextDelegate in directionals
      var thisSquare as GridMember = square
      
      do
        thisSquare = directional.Invoke( thisSquare )
        if thisSquare is nil then
          count = count + 1
          continue for square
        end if
        
        if thisSquare.RawValue.IntegerValue >= height then
          continue for directional
        end if
      loop
    next
  next
  
  return count
End Function

The ScenicScore function is similar:

Private Function ScenicScore(grid As ObjectGrid, square As GridMember) As Integer
  if square.Row = 0 or square.Row = grid.LastRowIndex or square.Column = 0 or square.Column = grid.LastColIndex then
    return 0
  end if
  
  var directionals() as ObjectGrid.NextDelegate
  directionals.Add AddressOf grid.Above
  directionals.Add AddressOf grid.Right
  directionals.Add AddressOf grid.Below
  directionals.Add AddressOf grid.Left
  
  var height as integer = square.RawValue
  
  var score as integer = 1
  
  for each directional as ObjectGrid.NextDelegate in directionals
    var nextSquare as GridMember = square
    var thisScore as integer
    
    do
      nextSquare = directional.Invoke( nextSquare )
      if nextSquare is nil then
        exit do
      end if
      
      thisScore = thisScore + 1
      
      if nextSquare.RawValue >= height then
        exit
      end if
    loop
    
    score = score * thisScore
  next
  
  return score
End Function

I just got up after going to bed earlier.

Damnit. The second one is tricky. Got my algo wrong again.

The example for part 2 doesn’t make any sense to me.

Haha, we obviously all struggle at part 2 :slight_smile: