Say i have two arrays:
a = [1, 1, 1] and
b = [0, 0]
I want to concatenate these randomly in a seperate variable c, until i reach some desired length of c. So something like:
N = 10
c = random_concatenating((a, b), N)
[1, 1, 1, 0, 0, 1, 1, 1, 0, 0]
A verbose version:
import random
a = [1, 1, 1]
b = [0, 0]
N = 10
def random_concatenating(iterable, n):
rv = []
l = [*iterable]
print(l)
while len(rv) < n:
rv.extend(random.choice(l))
return rv[:n]
c = random_concatenating((a, b), N)
print(c)
Prints (for example):
[1, 1, 1, 0, 0, 1, 1, 1, 1, 1]
You can use itertools.cycle to repeat the lists as many times as you need then slice them to the needed list
>>> from itertools import cycle, islice
>>> a = [1, 1, 1]
>>> b = [0, 0]
>>> N = 10
>>> list(islice(cycle(a+b), N))
[1, 1, 1, 0, 0, 1, 1, 1, 0, 0]
This is one approach. Using random.choice
import random
a = [1, 1, 1]
b = [0, 0]
N = 10
foo = a + b
c = []
for i in range(N):
c.append(random.choice(foo))
print(c)
Output:
[0, 1, 1, 1, 1, 0, 1, 1, 1, 1]
One-line
c = [random.choice(foo) for i in range(N)]
Related
LIST OF LIST BIN DIVIDED INTO 8 : [[0, 1, 1, 0, 0, 1, 0, 1], [0, 1, 1, 1, 0, 1, 1, 1]]
the output I want is:
[101, 119]
This is more complex but significantly faster than any kind of string manipulation as it's essentially just integer arithmetic.
from timeit import timeit
lob = [[0, 1, 1, 0, 0, 1, 0, 1], [0, 1, 1, 1, 0, 1, 1, 1]]
def v1():
result = []
for e in lob:
r = 0
for _e in e:
r = r * 2 + _e
result.append(r)
return result
def v2():
return [int(''.join([str(y) for y in x]), 2) for x in lob]
assert v1() == v2()
for func in v1, v2:
print(func.__name__, timeit(func))
Output:
v1 0.6906622060014342
v2 2.173182999999881
so the assignment is:
write a func that gets N ( int greater than 0 ) and return a 2d array of 1's where a path of 0 makes a diamond. the length of each diamond line(1 of 4 lines) is of length N. cannot use loops list comps or recursion.
i will add my own solution but I don't think it is very numpy oriented..
please note that my solution was originally for a diamond of 1's in a 0 matrix so it might look a bit odd
example:
n=1
np.array([[0]])
n=2:
np.array([[1,0,1],[0,1,0],[1,0,1]])
n=3
np.array([[1,1,0,1,1],[1,0,1,0,1],[0,1,1,1,0],[1,0,1,0,1],[1,1,0,1,1]])
My Solution:
if n == 1:
finalMatrix = np.array([[0]])
return finalMatrix
rawMatrix = np.ones((2 * n - 1, 2 * n - 1))
midRowDiag = np.eye(2 * n - 1, k=n - 1)
midColDiag = np.eye(2 * n - 1, k=-(n - 1))
tempMatrix = rawMatrix - midRowDiag - midColDiag
halfMatrix = tempMatrix[::, n:]
# print(halfMatrix)
# Making the quarters
topRightQuart = halfMatrix[:n - 1, 0:n - 1]
topLeftQuart = np.fliplr(topRightQuart)
botLeftQuart = np.flipud(topLeftQuart)
botRightQuart = np.flipud(topRightQuart)
midCol = tempMatrix[:, n - 1]
midRow = tempMatrix[n - 1, :]
# Adding them all up
finalMatrix = np.zeros((2 * n - 1, 2 * n - 1))
finalMatrix[:, n - 1] += midCol
finalMatrix[n - 1, :] += midRow
finalMatrix[0:n - 1, 0:n - 1] += topLeftQuart
finalMatrix[0:n - 1, n:] += topRightQuart
finalMatrix[n:, 0:n - 1] += botLeftQuart
finalMatrix[n:, n:] += botRightQuart
finalMatrix[n - 1, n - 1] = 1
return finalMatrix
arr = np.diagflat([1,1],1)
arr = np.maximum(arr,np.flip(arr,0))
arr = np.maximum(arr,np.flip(arr,1))
arr = np.where((arr==0)|(arr==1), arr^1, arr)
As per my understanding you are looking to make diamonds write. This is an example for 3x3 one for 5x5 the code is underneath
arr = np.diagflat([1,1,1],2)
arr = np.maximum(arr,np.flip(arr,0))
arr = np.maximum(arr,np.flip(arr,1))
arr = np.where((arr==0)|(arr==1), arr^1, arr)
so for n needs to be a odd number and n=odd number
list of 1 len = n//2+1 and the second parameter in np.diagflat will be n//2. This is important to use // or you can simply divide and round it off
if n is the length of diagonal then the second parameter will be n-1
This pattern looks similar to a Toeplitz matrix. You can implement this using scipy.linalg.toeplitz:
>>> p = np.array([1,1,0,1,1])
>>> T = toeplitz(p, p)
Notice the layout of T:
array([[1, 1, 0, 1, 1],
[1, 1, 1, 0, 1],
[0, 1, 1, 1, 0],
[1, 0, 1, 1, 1],
[1, 1, 0, 1, 1]])
We can horizontally flip it (np.fliplr) and point-wise multiply with itself:
>>> T*np.fliplr(T)
array([[1, 1, 0, 1, 1],
[1, 0, 1, 0, 1],
[0, 1, 1, 1, 0],
[1, 0, 1, 0, 1],
[1, 1, 0, 1, 1]])
Minimal implementation:
def diamond(n):
pad = (1,)*(n-1)
p = np.array(pad + (0,) + pad)
T = toeplitz(p, p)
return np.fliplr(T)*T
Then:
>>> diamond(1)
array([[0]])
>>> diamond(2)
array([[1, 0, 1],
[0, 1, 0],
[1, 0, 1]])
>>> diamond(3)
array([[1, 1, 0, 1, 1],
[1, 0, 1, 0, 1],
[0, 1, 1, 1, 0],
[1, 0, 1, 0, 1],
[1, 1, 0, 1, 1]])
I have a list:
hash_table = [1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]
I want to change this to:
result = [[0, 0], [1, 2], [4, 5]]
How to generate:
array: [1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]
map: 0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0
# start to end, generate the result like `[int(start), int(end)]`
combine them:[[0, 0], [1, 2], [4, 5]]
0 and 1 wouldn't appear in pairs. So the numbers in result must be an integer.
What I have tried:
hash_table = [1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]
output = [[]]
for pre, next_ in zip(hash_table, hash_table[1:]):
output[-1].append(pre)
if {next_, pre} == {0, 1}:
output.append([])
output[-1].append(hash_table[-1])
# the output is [[1], [0], [1, 1, 1], [0, 0, 0], [1, 1, 1]]
start = index = 0
result = []
while index < len(output):
# output[index]
if output[0] != 0:
res.append([start, math.ceil(len(output[index]))])
# I don't know how to handle the list "output".
# I couldn't know it. My mind has gone blank
start += len(output[index])/2
Any good ideas? I thought I made it too complicated.
You can use itertools.groupby to group the 0s and 1s:
import itertools
hash_table = [1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]
result = []
cur_ind = 0
for (val, vals) in itertools.groupby(hash_table):
vals = list(vals) # itertools doesn't make it a list by default
old_ind = cur_ind
cur_ind += len(vals)
if val == 0:
continue
result.append([old_ind // 2, (cur_ind - 1) // 2])
print(result)
Essentially, itertools.groupby will give an iterator of [(1, [1]), (0, [0]), (1, [1, 1, 1]), (0, [0, 0, 0]), (1, [1, 1, 1])] (more or less). We can iterate through this iterator and keep track if the index we're on by adding the length of the sublist to the current index. If the value is 1, then we have a run of ones so we append it to the results. The old_ind // 2 is integer division and is equivalent to int(old_ind / 2).
You could use groupby from itertools library:
import itertools
hash_table = [1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]
s = "".join(map(str, hash_table)) # s = "10111000111"
gs = [(i, list(g)) for i, g in itertools.groupby(s)]
idx, result = 0, []
for i, g in gs: # i can be '1' or '0' (i.e, if the group consist in 1's or 0's)
if i == '1':
result.append([idx/2, (idx + len(g) - 1)/2])
idx += len(g)
return result
This is the input and the output should be as shown. This is what i have tried:
input a = [1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0]
output a = [[1,1,0],[1,1,1,0],[1,0],[1,1,0]]
def new_list(x):
new = []
for item in range(length(x)):
if x[item]== 0:
new.append(x[:item+1])
return new
First extract to inides of 0 elements. Then use it to slice the original list:
a = [1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0]
def new_list(x):
indices = [i for i,e in enumerate(x) if e == 0] # indices of zeros
indices = [0] + [i+1 for i in indices] # 0 is 1st slice, +1 is for slicing (1 higher than index)
ii1,ii2 = indices[:-1],indices[1:] # first and second index for each sub-list
return [x[i1:i2] for i1,i2 in zip(ii1,ii2)]
print(new_list(a))
Few modifications in your function to get your required output.
def new_list(x):
new = []
slice_idx = 0
for index, val in enumerate(x):
if val == 0:
new.append(x[slice_idx:index+1])
slice_idx = index +1
return new
Input: a = [1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0]
new_list(a)
[[1, 1, 0], [1, 1, 1, 0], [1, 0], [1, 1, 0]]
I have this list:
l = [0, 1, 2]
and obviously l[0] = 0, l[1] = 1, l[2] = 2,
but I want l[3] to be = to 0, l[4] = 1, l[5] = 2 and so on...
you can use the modulus operator to cycle through the elements of the list.
l[index % 3]
In general:
lst = [0, 1, 2]
lst[index % len(lst)]
Depending on what you're trying to do, you can "multiply" a list to create a longer, repeating list of the original. Alternatively, you can create an iterator that just yields the same sequence of numbers indefinitely:
>>> numbers = [0, 1, 2] * 5
>>> numbers
[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
>>> from itertools import cycle
>>> number_iter = cycle([0, 1, 2])
>>> next(number_iter)
0
>>> next(number_iter)
1
>>> next(number_iter)
2
>>> next(number_iter)
0
>>> next(number_iter)
1
>>> next(number_iter)
2
>>>