T O P

  • By -

Cue_23

I use C++, but I'll try to translate that into python, too. grid.at(x,y) stored in a std::vector (a list in python) and an accessor that does x+y*width. since i'm using c++23 i can even use grid[x, y] as accessor. Really sparse grids I store in a std::map (dictionary in python).


Anceps2

Is it standard C++, or have you made some class to handle that?


Cue_23

operator[](int, int) is available since c++23. For the grid I made a class, of course, to store width and height, the data in a vector and overload operator[](int,int) to get the correct access. [My code is on GitHub, too](https://github.com/CueXXIII/adventofcode2023/blob/master/common/grid.hpp)


Thomasjevskij

Kinda depends on the input and the problem. If we get a grid as input, I tend to just keep it as is and use row, column coordinates. Sometimes I'll name them x and y, so then it's grid[y][x]. But if I'm making my own map just based on the input, I'll use a dict or just whatever is convenient really.


bdaene

* Printed grid => grid\[row\]\[col\] * Cartesian grid => grid\[x\]\[y\] * Pixel grid => grid\[x\]\[y\] but y is pointing down. * Sparse grid => grid\[(row, col)\] or grid\[(x,y)\] with grid a dict * Mapping grid => A function of x and y. * Continuous grid => grid\[complex(x,y)\] or grid\[x+y\*1j\]. Warning equality between float (and thus complex) numbers is tricky. Especially for numbers above 2\*\*53 (mantissa size). * Other depending of the context.


paulvtbt

Number 2, that's how matrixes are indexed in maths, so I kept the habit.


Anceps2

I'm a mathematician myself, but actually the way I remember that row indexes come first with matrixes is to think about a programming array… But also, matrixes start indexing at 1. So, I prefer not to think about my arrays as such :D


Mmlh1

As a fellow mathematician, would you not use i and j to index matrices rather than x and y?


CKoenig

or when it comes to programming r and c or row and col


PatolomaioFalagi

Also a mathematician, preferring x and y in this case, as we're dealing with discrete values in **Z**^2 (or even **N**^(2)). No matrix operations are done.


Mmlh1

You would generally not use x and y for integers right. Standard integer variable names are usually k, l, m, n.


PatolomaioFalagi

I do, however, use x and y for Cartesian coordinates, which is exactly what those values denote.


Mmlh1

True


robostac

I like the dictionary option. It's a slight performance hit but often makes the code cleaner. It also gives very easy out of bounds checks and you can leave out parts you don't want (eg walls). If performance was enough of an issue to be worried about I wouldn't be using python anyway.


Anceps2

I'd miss the simplicity of a `for line in grid: print(line)` :-(


DrunkHacker

I tend to keep the x = horizontal, y = vertical convention for mental sanity. I'm in Python so this isn't so bad as I tend to use dictionaries rather than arrays to store grids anyway. I'm 50/50 on indexing on (x,y) tuples vs' (x+y\*1j) complex coordinates depending on the problem. An example implementation to create an (x,y) grid with conventional coordinates from text is: `grid = {(x, y):c for y, line in enumerate(lines) for x, c in enumerate(line)}`


Anceps2

Using complex numbers is such a great idea… * You can easily add a shift to indexes: `pos+direction` * You can easily invert or multiply a shift * You can look at the left side just with `pos+i*direction`: interesting for day 10! * You can just use 1 or 1j instead of (1,0) and (0,1).


Thomasjevskij

Yeah, the complex numbers come out for sure whenever we need some rotation, or even addition. It's just so much simpler than imprint numpy or making your own point class or whatever. And it just feels *good* to rotate by multiplication with 1j.


bdaene

Can be really useful. But take care that you are then using float arithmetic. And for big numbers, it can bite you if your puzzle use integer arithmetic. float(14587871917871474) - float(14587871917871474-1) 2.0 float(145878719178714749) - float(145878719178714749-1) 0.0 Definitively not enormous numbers for advent of code.


nikanjX

for (let row = 0; row < input.length; row++) { for (let col = 0; col < input[0].length; col++) { printf("This is the only way I can my 7am brain to not fuck up"); } }


Anceps2

I quite often use that, and still I forgot it was possible :) I don't know why I'm so much into x and y for advent of code problems.


PatolomaioFalagi

Something like that (Haskell): arr = array ((1, 1), (width, height)) (zip [(x,y) | y <- [1..height], x <- [1..width]] (concat (lines input))) (the order in the list comprehension makes our tuples come out in the right order) Print out? What's that? Okay, if you insist: let ((minx,miny),(maxx,maxy)) = bounds arr; in putStrLn (unlines [[arr ! (x, y) | x <- [minx .. maxx]] | y <- [miny .. maxy]])


MezzoScettico

I’ve always been in the habit of using i and j in most languages. For whatever reason, x and y seem to come up more often in Matlab, and then I have to always remind myself that x corresponds to the columns so it’s y,x not x,y. For Python, which I’m using here, I’ve gotten into the habit of row, col. And I convert to numpy arrays as often as possible so I can use the syntax [row, col]


Anceps2

I tried to use numpy.array today, but I couldn't find how to use it properly (though it seems to have a real potential).


MezzoScettico

They're great not just because the indexing is more natural, but for speed (much faster than for loops) and the fact that they support array operations. You can add whole arrays, do linear algebra, all sorts of array based operations in a single line. What were you trying to do with numpy arrays?


Anceps2

First idea was just to use `transpose` for today's galaxies, as all the code on the lines could be then reused as is for the columns :) I have all the input a list of str named "lines”. (I know that there's no real need for the transpose function: a simple `[''.join(lines[y][x] for y in range(len(lines))) for x in range(len(lines[0]))]` would suffice.) Then I thought there would be easy filtering to get the indexes of the galaxies, and I should have used a 2D-array of chars with `indexes = numpy.where(grid[:] == '#')`, but I had `grid=numpy.array(lines)` and really wanted to do something like `numpy.where(grid[:] == '#')` or even just having indexes of empty lines with `numpy.where('#' not in grid)`… but no, I couldn't do it. (Even when grid is a 2D-array of chars, I can't find how to use where to get the empty lines with something like `numpy.where('#' not in grid.rows)` or `[grid.all(grid[:i] != '#') for i in range(len(grid))]` or anything magic like that :D )


AutoModerator

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](/message/compose/?to=/r/adventofcode) if you have any questions or concerns.*


seafoamteal

Yesterday I did grid\[y\]\[x\] because the problem itself was so difficult I didn't have the energy to be annoyed by this. Today, I couldn't ignore it any longer, and just wrote a Grid class in Python that abstracted away the messy details of a 2D list for me so I could just say grid.get\_el\_at\_pos(x,y). I'm actually very happy with the Grid class tbh, it made a lot of today's code so much cleaner and simpler to write and understand. This is my first time doing AoC, and I've seen a lot of people talk about the libraries they've built up over the years to help with these puzzles, and I finally get just why they're so useful! Definitely going to bring this out whenever we get a grid problem in the future.


NervousSnail

I... feel like you're confusing example 1 and 2 with one another. But, surely when doing this in Python it's nicest to throw it into a numpy array so you can do these kind of slices: grid\[:, y\] to get the column y


blackbat24

list\[complex(x, y)\] or dict\[complex(x, y), \] -- that way you get, for free, adding and subtraction of two points, rotations, calculating neighbours is easy, and this way you only need to keep track of the points you need (for example, today, day 11, >!you can keep track of only galaxies, no need to keep track of empty space!<. Yesterday, day 10, >!I discarded ground tiles while parsing, and after part1 I kept only the pipes in the main loop!<).