Part 1: Accessible Rolls of Paper
I’ve managed to make it to the printing room floor but with the elevators offline but it’s going to be difficult to get around the North Pole base without them.
Fortunately, some elves have offered to help break through the wall into (what they think might be) a cafeteria on the other side - It’s all going to need decorating so I guess I’ll take up their offer.
Unfortunately their forklifts are all busy shifting some large rolls of paper, so I first need to help manage their workload. Honestly I’d have thought they would have done the project management course down here too!
They have, however, handily provided me with a diagram which includes the positions of all the rolls of paper that need removing; not all are immediately accessible so the first task is to identify which rolls are accessible.
| |
In their diagram, the @ symbol represents the rolls of paper, . is empty space. There must be no more than 4 other rolls surrounding a particular roll to deem it accessible.
More list comprehension to parse the input into a 2D-array, I could have left the second dimension a string as that’s already indexable but I prefer to better represent the data as it’s intended to be used.
| |
I’m not sure straight off the bat if python has some magical built-in function that can aid with this - I know there is itertools which might be worth a look. I’ll have a go first.
| |
This takes an x,y coordinate and then iterates through -1, 0, 1 for dx, skipping anything that falls outside of the diagram limits. Nested in this is another of the same range iteration but this time used as dy - again skipping anything that falls outside the diagram range. I can then use dx and dy to index the grid relative to the current x,y position to evaluate if the space is occupied.
Then it’s just a case of checking this for each roll of paper:
| |
The sum function is just counting 1s when the conditions are met, using generator expressions to iterate through the rows/cols of the diagram to find the rolls of paper. For the example this is 13.
Part 2: Moving Paper
Next is to remove the accessible rolls of paper; how many rolls can they remove in total?
In the example diagram, this would mean removing the 13 accessible rolls that I just identified, reevaluating which rolls are now accessible and then removing them and so on.
It’s not too complicated and there are no additional changes required to the accessible check. I just need to use the same generator expression to select the index of any accessible rolls and this time remove them from the diagram.
I can use something here that I haven’t so far in these challenges: the walrus operator, :=. This allows me to declare and assign the removable list and truthy evaluate it all in one as part of the while condition. This will automatically then exit the loop once there are no results, i.e. nothing is left accessible.
| |
The sum of removed rolls in the example is then 43 in total.
Sorted. Let’s hope that they can actually get me through this wall…
Improving Accessibility
Looking back at the accessible function I’m trying to see how best to improve this.
I think utilising itertools.product to produce the pairs of dx,dy values that I iterate on to check the neighboring positions of a roll would be good. This replaces the nested loops with product(range(-1, 2), repeat=2) which is very nice.
But also, this could use another generator expression and sum as I did with the outer count in part 1, rather than incrementing the count manually.
| |
This certainly reduces the levels of nesting required, and it still has all the guards on bounds as my original too. The only thing is that it appears to consistently almost double my solution time going from around ~0.25s to ~0.50s. I’m not sure if that’s something to do with generator expressions, the use of product or just if the ability to short circuit differently in the nested version is the reason for that.
As always, full code is available at github.com/lordmoocow/aoc25.
I’m not sure if it’s having done Advent of Code challenges a few times now, but the difficulty level so far this year has been fairly minimal - these tasks haven’t had much in the way of things to catch you out hammering your stack into oblivion or require any complex algorithm. It is only day 4, but with half the days this year I wasn’t sure if it would escalate quickly. 8 days to go so plenty of time to get tougher.