For-loop to fill in node positions in an array for a cube

117 views Asked by At

So I started making this for 4D cube (tesseract) but then got a little confused so I dropped it down a dimension.

I'm trying to figure out a way to iteratively go through the list I named "pos" (basically a list of 1s and 0s indicating the position of the node) and fill in the relevant value.

e.g. The origin would be [0,0,0] while 'pqr' would be [1,1,1].

I want to do this for a general amount of dimensions and I think I figured out the right way to start it. It first sorts the nodes by length and then by lexigraphical order. After that, it checks the length of the node and if its in the right dimension then it can iterate through the 'pos' list adding 1s to the appropriate field. It looks ahead and if the next node is a higher dimension then it changes the way it adds to the next dimension. This is where I need help.

How can I iterate through this list to add 1 on the appropriate dimension to make a scaffold for my cube?

Input

#!/usr/bin/python
axis_labels = ['p','q','r']

dimension = len(axis_labels)

D_node_edge = {'pr': ['pqr'], 'pq': ['pqr'], 'p': ['pq', 'pr'], 'qr': ['pqr'], 'q': ['pq', 'qr'], '0': ['p', 'q', 'r'], 'pqr': [], 'r': ['pr', 'qr']}

D_node_pos = {}
pos = [0 for p in xrange(dimension)]
ordered_nodes = sorted(D_node_edge, key = lambda x: (len(x),x))
dim_tmp = 1

D_node_pos['0'] = pos
for i in xrange(1,2**dimension-1):
    node = ordered_nodes[i]
    
    n_node = ordered_nodes[i+1]
    if len(node) == dim_tmp:
        #need help right here to go through and add relevant entries to 'pos'
        D_node_pos[node] = pos
        
    if len(n_node) > dim_tmp:
        dim_tmp += 1
    

Desired Output values for D_node_pos.items()

0 [0,0,0]
p [1,0,0]
q [0,1,0]
r [0,0,1]
pq [1,1,0]
pr [1,0,1]
qr [0,1,1]
pqr [1,1,1]
2

There are 2 answers

0
wflynny On BEST ANSWER

If you only want the vertex lists, you could easily do:

>>> map(list, product([0, 1], repeat=dimension))

or

>>> sorted(map(list, product([0, 1], repeat=dimension)), key=sum)
[[0, 0, 0],
 [0, 0, 1],
 [0, 1, 0],
 [1, 0, 0],
 [0, 1, 1],
 [1, 0, 1],
 [1, 1, 0],
 [1, 1, 1]]

Otherwise, if you also want the label combinations, you could try something like:

from itertools import product

axis_labels = ['p','q','r']    
dimension = len(axis_labels)

for comb in product([0, 1], repeat=dimension):
    label = ''.join([axis_labels[i] for i in range(dimension) if comb[i]])
    if not label: label = '0'
    print label, list(comb)

Yields

0 [0, 0, 0]
r [0, 0, 1]
q [0, 1, 0]
qr [0, 1, 1]
p [1, 0, 0]
pr [1, 0, 1]
pq [1, 1, 0]
pqr [1, 1, 1]

If you care about order, you could always store the labels/combs and sort by label length.

0
tzaman On

Using itertools:

from itertools import imap, groupby, chain, permutations
from operator import itemgetter
list(imap(itemgetter(0), groupby(chain.from_iterable(permutations('0'*(3-i) + '1'*i) for i in range(4)))))
# [('0', '0', '0'), ('0', '0', '1'), ('0', '1', '0'), ('0', '0', '1'), ('0', '1', '0'), ('1', '0', '0'), ('0', '1', '1'), ('1', '0', '1'), ('1', '1', '0'), ('1', '0', '1'), ('1', '1', '0'), ('1', '1', '1')]