0

I need to write a python function that returns a list or tuple of coordinates for a unit hypercube, (square/box/tesseract etc.) based on starting coordinates that will be placed in the top left. I have a vector class that takes a list of any length, which I use for different unrelated parts of the project. The order of the points doesn't really matter, only that the starting position is the 'lowest point', ie [x, y, z ...] and that no other point is [x-1, y] or something like that. It needs to work for any number of dimensions, and each side is one unit long.

For a square, it would look like this:

def square(x, y):
  return [
    Vector([x, y]),
    Vector([x + 1, y]),
    Vector([x + 1, y + 1]),
    Vector([x, y + 1])
  ]

A cube would look like this:

def cube(x, y, z):
  return [
    Vector([x, y, z]),
    Vector([x + 1, y, z]),
    Vector([x + 1, y + 1, z]),
    Vector([x, y + 1, z]),
    Vector([x, y, z + 1]),
    Vector([x + 1, y, z + 1]),
    Vector([x + 1, y + 1, z + 1]),
    Vector([x, y + 1, z + 1]),
  ]

It keeps going like that, so I need to write a function that would look something like this:

def hypercube(start):
  points = [];

  #Add all the points to the list (need to figure out)

  return points

# And it will be used like so:

starts = [35, 12]
print(hypercube(starts))
# result: 
#[Vector(35, 12), Vector(36, 12), Vector(36, 13), Vector(35, 13)]


starts = [35, 12, 34, 17, 2]
print(hypercube(starts))
#result :
#[Vector(35, 12, 34, 17, 2), ... Vector(36, 13, 35, 18, 3)]

I understand that there is probably a recursive way to do this, I just can't think of it.

Bagel03
  • 725
  • 7
  • 22

1 Answers1

1

The itertools function combinations_with_replacement can give you all the needed combinations of "add 1" or "add nothing" for each axis in your cube.

So, supposing your Vector class supports Vector addition:

from itertolls import combinations_with_replacements

from ... import Vector

def hypercube(starts):
    dimensions = len(starts)
    return [starts + Vector(*combination) for combination in combinations_with_replacements((0, 1), dimensions)]

And if your "Vector" does not support addition with the + operator yet, all you have to do is to include an __add__ method to it:


class Vector:

    def __add__(self, other):
       return self.__class__([comp1 + comp2  for comp1, comp2 in zip(self, other)]) 

(In this case, assuming your "Vector" inherits from Python Sequences like a list, or collections.abc.Sequence and is properly iterable - otherwise, just pass zip the Vector attribute that holds the sequence data)

jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • That worked surprisingly well, thanks for the tip about adding a __add__ method to classes, didn't know that before. – Bagel03 Apr 21 '20 at 21:23