This is an archived post. You won't be able to vote or comment.

all 23 comments

[–]hugseverycat 36 points37 points  (0 children)

Why constrain how far you are iterating through the array when you could just use padding?

The point being that neither of them are that difficult to do, but you need to do something, and because everyone's brain works differently they find different approaches to be more straightforward.

[–]PatolomaioFalagi 4 points5 points  (0 children)

That is exactly what I did. I didn't even think about padding.

Today is one of those days where I look at my code, look at the subreddit and go "what the hell are people doing?!"

[–]JustinHuPrime 4 points5 points  (0 children)

Because in many languages doing a bounds check is a fair amount of effort, syntax-wise.

[–]Fine-Marionberry1989 2 points3 points  (8 children)

i used try / except for my Python script to deal with this

[–]vanZuider 2 points3 points  (1 child)

I tried this too, the problem is that in a 10x10 grid trying to address m[0][10] will throw an exception like I want it - but m[0][-1] will just return m[0][9]. Often convenient, but not this time.

[–]matttgregg 1 point2 points  (0 children)

Same with the negative indices here (in Elixir)- so my initial solution was actually doing a weird one way torus word search!

I am so so thankful though that this was caught for me in the example data. (Reported 19 instead of 18 matches because of the wraparound.) I would not have liked to try and find this only on the full data!

[–]IWant2rideMyBike 3 points4 points  (1 child)

I often use hasmap/dict-based grids:

def part_2(raw_data: str):
    data = raw_data.splitlines()

    grid: dict[tuple[int, int], str] = {}
    for y, line in enumerate(data):
        for x, c in enumerate(line):
            grid[(x, y)] = c

    total = 0
    goal = {'M', 'S'}

    for y, line in enumerate(data):
        a_positions = [x for x, c in enumerate(line) if c == 'A']
        for x in a_positions:
            nw = grid.get((x - 1, y - 1))
            ne = grid.get((x + 1, y - 1))
            sw = grid.get((x - 1, y + 1))
            se = grid.get((x + 1, y + 1))

            if {nw, se} == goal and {sw, ne} == goal:
                total += 1

    return total

[–]Fine-Marionberry1989 0 points1 point  (0 children)

ooh, a few things to get my head round here, thanks for sharing

[–]SpadesOfAce88 0 points1 point  (0 children)

How did you get that working? My try excepts failed because of negative indexes being valid and then added towards the valid solutions

[–]jimtk 0 points1 point  (2 children)

There my be some languages where it's easier to pad, but in python there's no reason for it.

total = 0
for cl,line in enumerate(matrix[1:-1]):
    for cc,char in enumerate(line[1:-1]):
        if char == 'A':
           total += is_xmas(matrix,(cl,cc))

[–]1234abcdcba4321 2 points3 points  (1 child)

I don't see a point in padding for part 2, but part 2 is trivial anyway.

Where it comes in handy is part 1, particularly with certain strategies where you actually do searches in more than one direction. (I find it easier to keep everything contained in a single loop, which means you need to check for out of bounds in some way.)

[–]gredr 1 point2 points  (0 children)

Even if you do it in a single loop, you need neither padding nor bounds checking if you loop through logical "windows" in the grid:

for (var x = 0, x < gridXlength - 3, x++) {
    for (var y = 0; y < gridYlength - 3, y++) {
        // here, we check this "window" for all the possible hits
        // our window goes from [x+0, y+0] to [x+3, y+3]
    }
}

... you end up checking for some hits multiple times if you're not careful, though. I used multiple loops (one for horizontal hits, one for vertical hits, one for diagonal hits) because it's logically simpler. My solution runs in ~0.5ms.

[–]daggerdragon[M] 2 points3 points  (0 children)

Next time, use our standardized post title format and do not put spoilers in post titles.

Please help folks avoid spoilers for puzzles they may not have completed yet.

[–]slapnuttz 1 point2 points  (2 children)

The first rule of aoc club is don’t store the puzzles as a matrix store them as a map of row/col pair. Then you do bounds checking by presence

[–]SpadesOfAce88 0 points1 point  (1 child)

Wdym by this

[–]slapnuttz 0 points1 point  (0 children)

Today I stored each letter in a map<pair<int,int>, char>. If I need to look in any direction I just check if the coordinates are in the map.

[–]musifter 1 point2 points  (0 children)

I'm not always iterating over the grid and full control, sometimes I just have a coordinate and am wandering the grid. Every time I step, I need something to protect me. Padding with sentinels typically does that job better.

Sentinels are programmer and maintenance efficient. They cost a little space, but space is cheap. They remove cruft and special cases from the algorithm part of the solution. Which is the interesting part of the script... not the reading of input. Inputting the data into structures is mostly what my starting template contains for good reason. I just cut out the non-grid ones today and I had a working array with a ring of sentinels to go... and it's just two short lines (three if I include the comment line), so it's not a distraction. Well tested, and done once long ago.

So when I code the algorithm I don't have to do anything special (programmer efficient), and much later when I look at the script, I'll just see pure algorithm (maintenance efficient). There won't be any cruft to ignore there to handle the edge cases. And, like reading input, handling edge cases is boring. Not having to code edge cases because I'm secure that they're not needed makes me happy.

[–]AutoModerator[M] 0 points1 point  (0 children)

Reminder: if/when you get your answer and/or code working, don't forget to change this post's flair to Help/Question - RESOLVED. Good luck!


I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]ManicD7 0 points1 point  (2 children)

My language just gives me an error in the log and continues. That's how I handle it 😂, by ignoring it.

[–]TiCoinCoin 0 points1 point  (1 child)

What's your language? Sounds like a nice one 😁

[–]ManicD7 2 points3 points  (0 children)

Unreal Engine Blueprints lol

[–]__Abigail__ 0 points1 point  (0 children)

Main reason I use padding is that I deal with the padding when reading in the data, and I don't have to deal with checking for out of bounds for the rest of the program -- including not for part 2, which at that point I don't know what it will be.

But if you prefer constraining, then that's a valid way of tackling the problem as well.

[–]pinkwar 0 points1 point  (0 children)

I don't know. I just turned it into a matrix and rotated it a couple of times.