Consecutive values in array with periodic boundaries in Python - python

I have some 2D-arrays filled with 0 and 1:
import numpy as np
a = np.random.randint(2, size=(20, 20))
b = np.random.randint(2, size=(20, 20))
c = np.random.randint(2, size=(20, 20))
d = np.random.randint(2, size=(20, 20))
and I want to count the consecutive occurrence of the ones with periodic boundaries.
That means (in 1D for clearness):
[1 1 0 0 1 1 0 1 1 1]
should give me 5(last three elements + first two).
The 2D-arrays should be compared/counted in the third (second if you start with 0) axis, like first stacking the arrays in axis=2 and then applying the same algorithm like for 1D. But I am not sure if this is the most simple way.

Here's one way for ndarrays a of 2D and higher dim arrays, meant for performance efficiency -
def count_periodic_boundary(a):
a = a.reshape(-1,a.shape[-1])
m = a==1
c0 = np.flip(m,axis=-1).argmin(axis=-1)+m.argmin(axis=-1)
z = np.zeros(a.shape[:-1]+(1,),dtype=bool)
p = np.hstack((z,m,z))
c = (p[:,:-1]<p[:,1:]).sum(1)
s = np.r_[0,c[:-1].cumsum()]
l = np.diff(np.flatnonzero(np.diff(p.ravel())))[::2]
d = np.maximum(c0,np.maximum.reduceat(l,s))
return np.where(m.all(-1),a.shape[-1],d)
Sample runs -
In [75]: np.random.seed(0)
...: a = np.random.randint(2, size=(5, 20))
In [76]: a
Out[76]:
array([[0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0],
[0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1],
[1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0]])
In [77]: count_periodic_boundary(a)
Out[77]: array([7, 4, 5, 2, 6])
In [72]: np.random.seed(0)
...: a = np.random.randint(2, size=(2, 5, 20))
In [73]: a
Out[73]:
array([[[0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0],
[0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1],
[1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0],
[0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0]],
[[1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0],
[1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1],
[0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0],
[1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0]]])
In [74]: count_periodic_boundary(a)
Out[74]: array([7, 4, 5, 2, 6, 2, 5, 4, 2, 1])

You can use groupby from itertools:
from itertools import groupby
a = [1, 1, 0, 0, 1, 1, 0, 1, 1, 1]
def get_longest_seq(a):
if all(a):
return len(a)
a_lens = [len(list(it)) for k, it in groupby(a) if k != 0]
if a[0] == 1 and a[-1] == 1:
m = max(max(a_lens), a_lens[0] + a_lens[-1])
else:
m = max(a_lens)
return m
print(get_longest_seq(a))

Here is a two-liner, admittedly containing one rather long line:
*m,n = a.shape
return np.minimum(n,(np.arange(1,2*n+1)-np.maximum.accumulate(np.where(a[...,None,:],0,np.arange(1,2*n+1).reshape(2,n)).reshape(*m,2*n),-1)).max(-1))
How it works:
Let's first ignore the wrap around and consider a simple example: a = [1 0 0 1 1 0 1 1 1 0]
We want to transform this into b = [1 0 0 1 2 0 1 2 3 0], so we can simply take the maximum. One way of generating b is taking the arange r = [1 2 3 4 5 6 7 8 9 10] and subtracting aux = [0 2 3 3 3 6 6 6 6 10]. aux we create by multiplying r with (1-a) yielding [0 2 3 0 0 6 0 0 0 10] and taking the cumulative maximum.
To deal with the wrap around we simply put two copies of a next to each other and then use the above.
Here is the code again broken down into smaller bits and commented:
*m,n = a.shape
# r has length 2*n because of how we deal with the wrap around
r = np.arange(1,2*n+1)
# create r x (1-a) using essentially np.where(a,0,r)
# it's a bit more involved because we are cloning a in the same step
# a will be doubled along a new axis we insert before the last one
# this will happen by means of broadcasting against r which we distribute
# over two rows along the new axis
# in the very end we merge the new and the last axis
r1_a = np.where(a[...,None,:],0,r.reshape(2,n)).reshape(*m,2*n)
# take cumulative max
aux = np.maximum.accumulate(r1_a,-1)
# finally, take the row wise maximum and deal with all-one rows
return np.minimum(n,(r-aux).max(-1))

Related

Uniform distribution of array data

I have an array [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], and I would like to translate it into a uniform position, what would be the output get: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]. The array is not always of such length and the numbers in it can be in different proportions to each other, so the question arises how to do it dynamically and not manually?
Need help
This would work:
arr = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
counters = {}
for element in arr:
counters[element] = counters.get(element, 0) + 1
frequences = {k:len(arr)/float(v) for (k,v) in counters.items()}
progress = {k:0.0 for (k,v) in counters.items()}
result = []
for upperBound in range(len(arr)):
partial_result = {}
for (k,frequence) in frequences.items():
if(frequence * progress[k] < float(upperBound) + 0.5):
progress[k] = progress[k] + 1
partial_result[k] = frequence * progress[k] - float(upperBound)
for (k,v) in sorted(partial_result.items(), key=lambda item: item[1]):
result.append(k)
print(result)
First getting frequencies for each number, then going from 1 to len(arr) checking if accumulated frequency for each number is below this threshold, if so output this number and accumulate its frequency further.
Solution:
my_list = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
def make_uniform_list(the_list):
my_set = list(set(the_list))
size = len(the_list)/len(my_set)
new_list = []
for i in range(round(size)):
new_list += my_set
return new_list
Examples:
ex_1 = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
print(make_uniform_list(ex_1))
# [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
ex_2 = [0, 1, 1, 0, 1, 1, 1, 0, 0, 1]
print(make_uniform_list(ex_2))
# [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
ex_3 = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3]
print(make_uniform_list(ex_3))
# [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
I don't know if I get your question right. Is this code what you're looking for?
a = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
for e,i in enumerate(a): #finding the place where pattern is changed
if i!=a[0]:
divier_idx = e
break
result=[]
for i in zip(a[divier_idx:],a[:divier_idx]): #grouping data into needed formation
result.extend(i)
if len(a[divier_idx:]) != len(a[:divier_idx]): #in case if the sec part is longer than the first one by 1 item it is appended to the end
result.append(a[-1])
print(result)
# the output: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

How to reduce (m, 50) tensor to (m, 25) tensor based on tensor value in tensorflow 1.10

For example,
# (m, 50) tensor a
print(a)
<tf.Tensor: id=11543, shape=(3, 50), dtype=int32, numpy=
array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 15, 32, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 11, 1, 1, 1, 11, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 421, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 1, 1, 1, 1, 1, 1,
1, 1, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]], dtype=int32)>
# (m, 50) tensor b
print(b)
<tf.Tensor: id=20624, shape=(3, 50), dtype=int32, numpy=
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 11, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 142, 1]], dtype=int32)
The tensor shape is (m, 50) and half of it is all 0, so I want to reduce tensor into (m, 25) which drops all 0 half part.
I am wondering how to implement it in tf 1.10.
I'll assume that it is known that the number of zeros in each row represent exactly half the size of the column. If it doesn't, then removing the zeros will result in a ragged tensor (a tensor with different dimension sizes) which is not supported in tf v1.10.0.
You can create a mask where the elements in the tensor are greater than 0 and then mask them out using tf.boolean_mask(and also we will have to reshape the result because tensorflow 1.10 cannot infer the new shape).
import tensorflow as tf
# using the `a` defined in your question
mask = tf.cast(a > 0, dtype=tf.int32)
result = tf.boolean_mask(a, mask)
result = tf.reshape(result, (3, 25))
with tf.Session() as sess:
print(result.eval())
# [[ 1 1 1 1 1 1 1 1 1 1 15 32 1 1 7 1 1 1
# 1 1 1 1 1 1 1]
# [ 1 1 1 1 1 11 1 1 1 11 1 1 1 1 1 8 1 1
# 1 1 1 1 1 1 1]
# [ 1 1 1 1 1 421 1 1 1 1 1 1 1 1 1 12 1 1
# 1 1 1 1 1 1 42]]

Using elements from a list with many levels to create a dictionary

I have the following code:
population = [[[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [1], [0]],
[[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1], [3], [1]],
[[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [4], [2]],
[[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [3], [3]]]
def CreateDictionary(population):
d=dict()
for ind in range (0, len(population)):
g = ','.join(str(ind[0][1]) for ind in population)
f = ','.join(str(ind[1][1]) for ind in population)
d[g] = f
return (d)
The result I get is:
{'[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1],
[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1],
[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0]': '[1],[3],[4],[3]'}
What I am trying to do is to create a dictionary using the first and second element for each part in the list (the third can be ignore) and assign one to the other, such as:
d={'0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1': 1,
'0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1': 3} and so on...
The first element (the binary sequence) can be text, it doesnt matter, but the second needs to be in a format that I can use to calculate other stuff. Since I am trying to do mathematical operations in this list form and its also not working.
I tried many things in other ways, but I get several errors while trying to run the code, this is the only way I could make it run but its not even close to what I wanted. Any thoughts on how I could approach this?
Thank you!
If it is what you want, use a dictionary comprehension. For converting the list to string, use the join() function after mapping each element to a string.
population = [[[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [1], [0]],
[[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1], [3], [1]],
[[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [4], [2]],
[[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [3], [3]]]
d = {", ".join(map(str,i[0])):i[1][0] for i in population}
print(d)
Output:
{'0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0': 4, '1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0': 3, '0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1': 3, '0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1': 1}
Alternative solution: We could convert the list to numbers base 10 (from binary):
def return_decimal(lst):
return int(''.join(map(str,lst)),2)
population = [[[0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [1], [0]],
[[0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1], [3], [1]],
[[0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0], [4], [2]],
[[1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [3], [3]]]
d = dict((return_decimal(i[0]),i[1][0]) for i in population)
Returns:
{40152: 3, 11745: 1, 27876: 4, 14769: 3}
To find a value:
find = [0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1] # 11745
d.get(return_decimal(find))
Returns:
1
I can't really see a use for a dict created like this (indexing becomes a pain). I'd really suggest just keeping separate lists x and y (see my answer). But you can create a dict by passing tuples of x and y to the dict constructor:
x, y, *_ = zip(*population)
x = [', '.join(map(str, z)) for z in x]
y = [z[0] for z in y]
d = dict(zip(x, y))
d
{'0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1': 1,
'0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1': 3,
'0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0': 4,
'1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0': 3}
You could try dict comprehension :
population_dict = {" ".join(str(x) for x in item[0]): int(item[1][0]) for item in population}
this dict comprehension is same as:
population_dict={}
for item in population:
population_dict[" ".join(str(x) for x in item[0])] = int(item[1][0])
print(population_dict)
output:
{'0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1': 3, '0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1': 1, '1 0 0 1 1 1 0 0 1 1 0 1 1 0 0 0': 3, '0 1 1 0 1 1 0 0 1 1 1 0 0 1 0 0': 4}

Error shuffling list into new list

I am creating a list by shifting an old list out_g, item by item, and appending the result to the new one, new_sets. As I am iterating, I check the resulting shift, and it is correct. After this is complete, I print out the new list, and it is all a single object repeated. What am I missing?
The error occurs during the for loop at the end, where I append the results to new_sets.
#!/usr/bin/python
import math
def LFSR(register, feedback, output):
"""
https://natronics.github.io/blag/2014/gps-prn/
:param list feedback: which positions to use as feedback (1 indexed)
:param list output: which positions are output (1 indexed)
:returns output of shift register:
"""
# calculate output
out = [register[i-1] for i in output]
if len(out) > 1:
out = sum(out) % 2
else:
out = out[0]
# modulo 2 add feedback
fb = sum([register[i-1] for i in feedback]) % 2
# shift to the right
for i in reversed(range(len(register[1:]))):
register[i+1] = register[i]
# put feedback in position 1
register[0] = fb
return out
def shiftInPlace(l, n):
# https://stackoverflow.com/questions/2150108/efficient-way-to-shift-a-list-in-python
n = n % len(l)
head = l[:n]
l[:n] = []
l.extend(head)
return l
##########
## Main ##
##########
n = 3
# init register states
if n == 5 :
LFSR_A = [1,1,1,1,0]
LFSR_B = [1,1,1,0,1]
LFSR_A_TAPS =[5,4,3,2]
LFSR_B_TAPS =[5,3]
elif n == 7:
LFSR_A = [1,0,0,1,0,1,0]
LFSR_B = [1,0,0,1,1,1,0]
LFSR_A_TAPS = [7,3,2,1]
LFSR_B_TAPS = [7,3]
elif n == 3:
LFSR_A = [1,0,1]
LFSR_B = [0,1,1]
LFSR_A_TAPS = [3,2]
LFSR_B_TAPS = [3,1]
output_reg = [n]
N = 2**n-1
out_g = []
for i in range(0,N): #replace N w/ spread_fact
a = (LFSR(LFSR_A, LFSR_A_TAPS, output_reg))
b = (LFSR(LFSR_B, LFSR_B_TAPS, output_reg))
out_g.append(a ^ b)
# FOR BALANCED GOLD CODES NUMBER OF ONES MUST BE ONE MORE THAN NUMBER
# OF ZEROS
nzeros = sum(x == 0 for x in out_g)
nones = sum(x == 1 for x in out_g)
print "Gold Code Output Period[%d] of length %d -- {%d} 0's, {%d} 1's" % (N,N,nzeros,nones)
# produce all time shifted versions of the code
new_sets = []
for i in range(0,N-1):
new_sets.append(shiftInPlace(out_g,1))
# a=shiftInPlace(out_g,1)
# new_sets.append(a)
print new_sets[i]
print new_sets
My output :
Gold Code Output Period[7] of length 7 -- {3} 0's, {4} 1's
[1, 1, 0, 1, 0, 1, 0]
[1, 0, 1, 0, 1, 0, 1]
[0, 1, 0, 1, 0, 1, 1]
[1, 0, 1, 0, 1, 1, 0]
[0, 1, 0, 1, 1, 0, 1]
[1, 0, 1, 1, 0, 1, 0]
[[1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0]]
Correct values are printing on the iteration, but the final list has all the same values.
The problem should be obvious from your output - you are seeing the same list because you are appending the same list. Consider - you even name your function "shift in place", so that returns a mutated version of the same list you passed in, and then you append that same list. So one quick fix is to make a copy which you end up appending:
new_sets = []
for i in range(0,N-1):
new_sets.append(shiftInPlace(out_g,1)[:]) # append copy
# a=shiftInPlace(out_g,1)
# new_sets.append(a)
print new_sets[i]
This gives the output:
Gold Code Output Period[7] of length 7 -- {3} 0's, {4} 1's
[1, 1, 0, 1, 0, 1, 0]
[1, 0, 1, 0, 1, 0, 1]
[0, 1, 0, 1, 0, 1, 1]
[1, 0, 1, 0, 1, 1, 0]
[0, 1, 0, 1, 1, 0, 1]
[1, 0, 1, 1, 0, 1, 0]
[[1, 1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1], [0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 1, 1, 0], [0, 1, 0, 1, 1, 0, 1], [1, 0, 1, 1, 0, 1, 0]]
As an aside, for efficient in-place rotations, consider changing your data-structure to a collections.deque, which implements a doubly-linked list:
In [10]: from collections import deque
...: d = deque([1, 1, 0, 1, 0, 1, 0])
...: print(d)
...: for i in range(0, N-1):
...: d.rotate(-1)
...: print(d)
...:
deque([1, 1, 0, 1, 0, 1, 0])
deque([1, 0, 1, 0, 1, 0, 1])
deque([0, 1, 0, 1, 0, 1, 1])
deque([1, 0, 1, 0, 1, 1, 0])
deque([0, 1, 0, 1, 1, 0, 1])
deque([1, 0, 1, 1, 0, 1, 0])
deque([0, 1, 1, 0, 1, 0, 1])
You might try creating your list of rotations like this:
>>> li=[1,0,1,1,0,0]
>>> [li[r:]+li[:r] for r in range(len(li))]
[[1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 0, 1], [1, 1, 0, 0, 1, 0], [1, 0, 0, 1, 0, 1], [0, 0, 1, 0, 1, 1], [0, 1, 0, 1, 1, 0]]
... following up on my comment to juanpa's answer ...
When you append in this fashion, you append a reference to the in-place list. Your two-line code with variable a works the same way. You've appended 6 copies of the same variable reference; every time you shift the list, you shift the underlying object. All of the appended references point to that object.
Here's detailed output tracing your program. Note how all of the elements of new_sets change on every iteration. In my repair, I used the two-line assignment, but added a copy like this: new_sets.append(a[:])
Gold Code Output Period[7] of length 7 -- {3} 0's, {4} 1's
TRACE out_g = [0, 1, 1, 0, 1, 0, 1]
ENTER shiftInPlace, l= [0, 1, 1, 0, 1, 0, 1]
LEAVE shiftInPlace, head= [0] l= [1, 1, 0, 1, 0, 1, 0]
TRACE a= [1, 1, 0, 1, 0, 1, 0] new_sets= [[1, 1, 0, 1, 0, 1, 0]]
TRACE out_g = [1, 1, 0, 1, 0, 1, 0]
ENTER shiftInPlace, l= [1, 1, 0, 1, 0, 1, 0]
LEAVE shiftInPlace, head= [1] l= [1, 0, 1, 0, 1, 0, 1]
TRACE a= [1, 0, 1, 0, 1, 0, 1] new_sets= [[1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1]]
TRACE out_g = [1, 0, 1, 0, 1, 0, 1]
ENTER shiftInPlace, l= [1, 0, 1, 0, 1, 0, 1]
LEAVE shiftInPlace, head= [1] l= [0, 1, 0, 1, 0, 1, 1]
TRACE a= [0, 1, 0, 1, 0, 1, 1] new_sets= [[0, 1, 0, 1, 0, 1, 1], [0, 1, 0, 1, 0, 1, 1], [0, 1, 0, 1, 0, 1, 1]]
TRACE out_g = [0, 1, 0, 1, 0, 1, 1]
ENTER shiftInPlace, l= [0, 1, 0, 1, 0, 1, 1]
LEAVE shiftInPlace, head= [0] l= [1, 0, 1, 0, 1, 1, 0]
TRACE a= [1, 0, 1, 0, 1, 1, 0] new_sets= [[1, 0, 1, 0, 1, 1, 0], [1, 0, 1, 0, 1, 1, 0], [1, 0, 1, 0, 1, 1, 0], [1, 0, 1, 0, 1, 1, 0]]
TRACE out_g = [1, 0, 1, 0, 1, 1, 0]
ENTER shiftInPlace, l= [1, 0, 1, 0, 1, 1, 0]
LEAVE shiftInPlace, head= [1] l= [0, 1, 0, 1, 1, 0, 1]
TRACE a= [0, 1, 0, 1, 1, 0, 1] new_sets= [[0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 1, 1, 0, 1]]
TRACE out_g = [0, 1, 0, 1, 1, 0, 1]
ENTER shiftInPlace, l= [0, 1, 0, 1, 1, 0, 1]
LEAVE shiftInPlace, head= [0] l= [1, 0, 1, 1, 0, 1, 0]
TRACE a= [1, 0, 1, 1, 0, 1, 0] new_sets= [[1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0]]
[[1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 0, 1, 0]]

How to increase a grid world's size by 1000 times

I'm using a program in which I have to input the environment's map. The input form looks like this.
self.map=[ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
I want to increase the size of the given structure by thousand times and maintain the form of the structure. After increasing the structure size will be 18000x6000. The code looks like this
Can someone suggest me a way to achieve this or any alternate way.
If you really want to use Python's lists (numpy's arrays are better for large matrices) you could use
repeatfactor = 1000
mat = self.map # copy reference, not data
m = len(mat)
n = len(mat[0])
newmatrix = [[mat[r % m][c % n]
for c in range(n * repeatfactor)]
for r in range(m * repeatfactor)]
Try np.repeat twice--once in each axis. Not the prettiest, but should work. So something like this:
map_array = np.array(self.map)
map_array = np.repeat(map_array, 1000, axis=0)
map_array = np.repeat(map_array, 1000, axis=1)

Categories

Resources