3

I want all possible single right shift arrays:

def gen(total):
    rot = []
    init = [0]*total
    init[0] = 1
    print init
    rot.append(init)
    for i in range(total-1):
        init[i] = init[i] - init[i+1]
        init[i+1] = init[i] + init[i+1]
        init[i] = init[i+1] - init[i]
        print init
        rot.append(init)
    return rot

rot = gen(8)

print rot

This prints

[1, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0]
[0, 0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 1]

I want this to be list of lists. I initialise an array rot but appending to it creates same rows

[[0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1]]

How to handle this issue?

PS: I don't want to use numpy like numpy.eye(8)

4
  • Show your full code with appending. Commented Oct 2, 2015 at 13:18
  • 2
    Please don't use that method to swap two numbers. It's a horrendous hack (likewise for the xor version) that is not very readable and it breaks down with large integers. Python already a syntax for swapping values: init[i], init[i + 1] = init[i + 1], init[i]. Commented Oct 2, 2015 at 13:20
  • Python has long integers with no upper limit, so that swapping technique should be safe. I do agree that it shouldn't be used though. Commented Oct 2, 2015 at 13:24
  • @Kevin That's true. It's just so unreadable compared to the proper method (in fact I find it much more opaque compared to the naïve use of a temporary variable). Commented Oct 2, 2015 at 13:28

5 Answers 5

7

Existing answers cover pretty well the problem with the existing code, so here's a different approach entirely:

>>> [[int(a==b) for b in range(8)] for a in range(8)]
[[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], 
[0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], 
[0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], 
[0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1]]

(some newlines added to the output by me for legibility)

Sign up to request clarification or add additional context in comments.

Comments

1

You should append a copy of the generated list like this:

from copy import deepcopy

def gen(total):
    rot = []
    init = [0]*total
    init[0] = 1
    print init
    for i in range(total-1):
        init[i] = init[i] - init[i+1]
        init[i+1] = init[i] + init[i+1]
        init[i] = init[i+1] - init[i]
        #print init
        rot.append(deepcopy(init))
    return rot

rot = gen(8)
print rot

You also can use copy.copy instead of copy.deepcopy.

Comments

1

Since you are modifying always the same object you append also always the same object. When you modify init, every entry of rot will see the change and therefore is every element the last state of init. To avoid this you need to create different objects and then append it to rot.

Comments

1

Why not use a double-ended-queue?

import collections
def gen(total):
    init = [0]*total
    init[-1] = 1
    d = collections.deque(init)
    return [list(d) for _ in range(len(d)) if not d.rotate(1)]

Comments

0

Your issue is that you're not copying the list, but your code seems needlessly complex. This seems to work just as well:

def gen(n):
    res = [[0 for j in xrange(n)] for i in xrange(n)]
    for i in xrange(n):
        res[i][i] = 1
    return res

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.