Python: Represents a square grid that wraps itself (cylinder)

I simulate something that happens on a square grid that wraps itself (i.e. if you pass the highest point, you find yourself at the lowest point, for example, in a cylinder, and if you go to the right, you just hit to the border). I need to track the location of various agents, the number of resources at different points, and calculate the direction in which the agents will move based on certain rules.

What is the best way to simulate this?

Should I create a class that represents points that have methods for returning neighboring points in each direction? If so, I probably need to make it hashed so that I can use it as keys for a dictionary that contains a complete grid (I assume such a grid should be a dictionary?)

Or should I create a class that describes the entire grid, and not expose individual points to independent objects?

Or should I just use regular (x, y) tuples and have methods elsewhere that let me search for neighbors?

Much of what I need for modeling is not yet clearly defined. In addition, I expect that the geometry of the surface may change one day (for example, it can turn on its own in both directions).

EDIT: One more question: should information about the amount of resources be applied to each instance of Point. or should I have a separate class that contains a map of resources indexed by Point?

+3
source share
2 answers

If you want to use a hashed Pointclass without too much work, subclass the tuple and add your own neighbor methods.

class Point(tuple):
    def r_neighbor(self):
        return Point((self[0] + 1, self[1]))
    def l_neighbor(self): 
        [...]

x = Point((10, 11))
print x
print x.r_neighbor()

The tuple constructor wants iterability, so double-parens in Point((10, 11)); if you want to avoid this, you can always override __new__(overriding is __init__pointless because tuples are immutable):

def __new__(self, x, y):
    return super(Point, self).__new__(self, (x, y))

This may also be the place to use modular arithmetic - although it will really depend on what you are doing:

def __new__(self, x, y, gridsize=100):
    return super(Point, self).__new__(self, (x % gridsize, y % gridsize))

__new__:

def __new__(self, tup, gridsize=100):
    return super(Point, self).__new__(self, (x % gridsize for x in tup))

: Point , , . defaultdict; .

from collections import defaultdict

grid = defaultdict(list)
p = Point((10, 13))
grid[(10, 13)] = [2, 3, 4]
print grid[p]                  # prints [2, 3, 4]
print grid[p.r_neighbor]       # no KeyError; prints []

, dict defaultdict; defaultdict(defaultdict) ; defaultdict factory.

def intdict():
    return defaultdict(int)

grid = defaultdict(intdict)

grid = defaultdict(lambda: defaultdict(int))

p = Point((10, 13))
grid[(10, 13)]["coins"] = 50
print grid[p]["coins"]              # prints 50
print grid[p.r_neighbor]["coins"]   # prints 0; again, no KeyError
+2

, , .

, . , (, , ), . , .

, , .

, , , , , .

+1

Source: https://habr.com/ru/post/1787279/


All Articles