I would like to create some number of for-loops equal to the length of a list, and iterate through the values in that list. For example, if I had the list:
[1,2,3,4]
I would like the code to function like:
for i in range(1):
for j in range(2):
for k in range(3):
for l in range(4):
myfunc(inputs)
I understand I would need to do this recursively, but I'm not quite sure how. Ideally, I would even be able to iterate through these list values by a variable step; perhaps I want to count by two's for one loop, by .8's for another, etc. In that case, I would probably deliver the information in a format like this:
[[value,step],[value,step] ... [value,step],[value,step]]
So, how could I do this?
Not quite sure what you want at the very end, but here's a way to recursively set-up your loops:
test = [1,2,3,4]
def recursive_loop(test):
if len(test) == 1:
for i in range(test[0]):
print('hi') # Do whatever you want here
elif len(test) > 1:
for i in range(test[0]):
recursive_loop(test[1:])
recursive_loop(test)
You can certainly do it with recursion, but there's already a library function for that:
itertools.product
from itertools import product
def nested_loops(myfunc, l):
for t in product(*(range(n) for n in l)):
myfunc(*t)
## OR EQUIVALENTLY
# def nested_loops(myfunc, l):
# for t in product(*map(range, l)):
# myfunc(l)
nested_loops(print, [1, 2, 3, 4])
# 0 0 0 0
# 0 0 0 1
# 0 0 0 2
# 0 0 0 3
# 0 0 1 0
# 0 0 1 1
# ...
# 0 1 2 1
# 0 1 2 2
# 0 1 2 3
You can of course include steps too. Library function zip can be useful.
def nested_loops_with_steps_v1(myfunc, upperbounds, steps):
for t in product(*(range(0, n, s) for n,s in zip(upperbounds, steps))):
myfunc(*t)
nested_loops_with_steps_v1(print, [1,2,8,10], [1,1,4,5])
# 0 0 0 0
# 0 0 0 5
# 0 0 4 0
# 0 0 4 5
# 0 1 0 0
# 0 1 0 5
# 0 1 4 0
# 0 1 4 5
Or if your steps and upperbounds are already zipped together:
def nested_loops_with_steps_v2(myfunc, l):
for t in product(*(range(0, n, s) for n,s in l)):
myfunc(*t)
nested_loops_with_steps_v2(print, [(1,1),(2,1),(8,4),(10,5)])
# 0 0 0 0
# 0 0 0 5
# 0 0 4 0
# 0 0 4 5
# 0 1 0 0
# 0 1 0 5
# 0 1 4 0
# 0 1 4 5
So I am working on something and I need to replace substrings with spaces, and get every different combination of that substring with the spaces, I want to do this using binary as a comparison.
So e.g.
0 0 0 = A B C
0 0 1 = A B _
0 1 0 = A _ C
0 1 1 = A _ _
1 0 0 = _ B C
1 0 1 = _ B _
1 1 1 = _ _ _ (put in code formatting to keep shape)
I am using python and have this so far, but it just output's an empty array.
Please could somebody help? :)
string ="abcde"
binary5=["0"]
final=[]
for count in range(0,32):
counter=0
count =bin(count)
count=str(count)
count = count.lstrip('-0b')
for i in range(len(count)):
if count[i] == "1":
counter=counter+1
if counter<6:
binary5.append(count)
print(binary5)
for i in range(0,32):
bintest = str(binary5[i])
bintest.split()
string2=string
for x in range(0,len(string)):
try:
if bintest[x] == "1":
string2.split()
string2.pop[x]
string2.insert(x-1," ")
string2.join()
print(string2)
final.append(string2)
except:
pass
print(final)
You have a methodology problem: you specifically throw away your diagnostic information. Therefore, when you have a problem, you have no idea what you did wrong: you ignored the error message.
The try-except block has no relation to your algorithm. Get rid of it, and start debugging your code. The first error is
string2.pop[x]
There is no pop method for type string. Next, you keep splitting strings that have no spaces or punctuation; I'm not sure what you think this is doing.
I have no idea what your code is doing. It's way too complicated. Here's a direct replacement.
import string
from itertools import product
def translate_tuple(tup):
''' Takes a tuple of any length containing 0s or 1s.
Returns a new tuple with the correct letters. '''
return tuple(l if tup[i] == 0 else '_' for i, l in enumerate(string.ascii_letters[:len(tup)]))
def get_pairs(length):
''' Get all pairs of binary and translated text. '''
for binary_tup in product((0, 1,), repeat=length):
yield ' '.join(map(str, binary_tup)), ' '.join(translate_tuple(binary_tup))
for b, t in get_pairs(3):
print(f'{b} = {t}')
Which prints:
0 0 0 = a b c
0 0 1 = a b _
0 1 0 = a _ c
0 1 1 = a _ _
1 0 0 = _ b c
1 0 1 = _ b _
1 1 0 = _ _ c
1 1 1 = _ _ _
You can use arbitrary sized binary numbers by providing a different length to get_pairs()
In [36]: for i in range(10):
...: b, t = next(g)
...: print(f'{b} = {t}')
...:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 = a b c d e f g h i j k l m n o p q r s t
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 = a b c d e f g h i j k l m n o p q r s _
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 = a b c d e f g h i j k l m n o p q r _ t
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 = a b c d e f g h i j k l m n o p q r _ _
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 = a b c d e f g h i j k l m n o p q _ s t
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 = a b c d e f g h i j k l m n o p q _ s _
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 = a b c d e f g h i j k l m n o p q _ _ t
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 = a b c d e f g h i j k l m n o p q _ _ _
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 = a b c d e f g h i j k l m n o p _ r s t
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 = a b c d e f g h i j k l m n o p _ r s _
Explanation
The most important bit is translate_tuple(), but you can use itertools.product to get all the input tuples.
translate_tuple(tup) expects a binary tuple of any length, e.g:
(0, 0, 0)
(0, 1, 0)
(1, 1, 1, 1)
(0, 1, 0, 1, 0)
And returns a new tuple in the format you described:
(0, 0, 0) => ('a', 'b', 'c')
(0, 1, 0) => ('a', '_', 'c')
(1, 1, 1, 1) => ('_', '_', '_', '_')
(0, 1, 0, 1, 0) => ('a', '_', 'c', '_', 'e')
The next function get_pairs() just generates all the binary tuples of a given length, and then yields the string of the binary tuple and the string of the result joined by spaces.
Then you can print out the strings. It would probably be better to yield the raw tuples, and create the strings immediately before printing, but I wanted to keep it mostly in that function.
I have 4 numpy arrays of same shape(i.e., 2d). I have to know the index of the last array (d) where the elements of d are smaller than 20, but those indices of d should be located in the region where elements of array(a) are 1; and the elements of array (b) and (c) are not 1.
I tried as follows:
mask = (a == 1)|(b != 1)|(c != 1)
answer = d[mask | d < 20]
Now, I have to set those regions of d into 1; and all other regions of d into 0.
d[answer] = 1
d[d!=1] = 0
print d
I could not solve this problem. How do you solve it?
import numpy as np
a = np.array([[0,0,0,1,1,1,1,1,0,0,0],
[0,0,0,1,1,1,1,1,0,0,0],
[0,0,0,1,1,1,1,1,0,0,0],
[0,0,0,1,1,1,1,1,0,0,0],
[0,0,0,1,1,1,1,1,0,0,0],
[0,0,0,1,1,1,1,1,0,0,0]])
b = np.array([[0,0,0,1,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,0,0,0],
[0,0,0,1,0,1,0,0,0,0,0],
[0,0,0,1,1,1,0,1,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0],
[0,0,0,0,1,0,1,0,0,0,0]])
c = np.array([[0,0,0,0,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,0,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,0,0,0,1,0,0,0,0,0]])
d = np.array([[0,56,89,67,12,28,11,12,14,8,240],
[1,57,89,67,18,25,11,12,14,9,230],
[4,51,89,87,19,20,51,92,54,7,210],
[6,46,89,67,51,35,11,12,14,6,200],
[8,36,89,97,43,67,81,42,14,1,220],
[9,16,89,67,49,97,11,12,14,2,255]])
The conditions should be AND-ed together, instead of OR-ed. You can first get the Boolean array / mask representing desired region, and then modify d based on it:
mask = (a == 1) & (b != 1) & (c != 1) & (d < 20)
d[mask] = 1
d[~mask] = 0
print d
Output:
[[0 0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 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 0 0 0]
[0 0 0 0 0 0 0 1 0 0 0]]
Working on a project for CS1 that prints out a grid made of 0s and adds shapes of certain numbered sizes to it. Before it adds a shape it needs to check if A) it will fit on the grid and B) if something else is already there. The issue I am having is that when run, the function that checks to make sure placement for the shapes is valid will always do the first and second shapes correctly, but any shape added after that will only "see" the first shape added when looking for a collision. I checked to see if it wasnt taking in the right list after the first time but that doesnt seem to be it. Example of the issue....
Shape Sizes = 4, 3, 2, 1
Python Outputs:
4 4 4 4 1 2 3 0
4 4 4 4 2 2 3 0
4 4 4 4 3 3 3 0
4 4 4 4 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 0 0 0
0 0 0 0 0 0 0 0
It Should Output:
4 4 4 4 3 3 3 1
4 4 4 4 3 3 3 0
4 4 4 4 3 3 3 0
4 4 4 4 2 2 0 0
0 0 0 0 2 2 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 0
What's going on here? Full Code is below...
def binCreate(size):
binlist = [[0 for col in range(size)] for row in range(size)]
return binlist
def binPrint(lst):
for row in range(len(lst)):
for col in range(len(lst[row])):
print(lst[row][col], end = " ")
print()
def itemCreate(fileName):
lst = []
for i in open(fileName):
i = i.split()
lst = i
lst = [int(i) for i in lst]
return lst
def main():
size = int(input("Bin Size: "))
fileName = str(input("Item Size File: "))
binList = binCreate(size)
blockList = itemCreate(fileName)
blockList.sort(reverse = True)
binList = checker(binList, len(binList), blockList)
binPrint(binList)
def isSpaceFree(binList, r, c, size):
if r + size > len(binList[0]):
return False
elif c + size > len(binList[0]):
return False
for row in range(r, r + size):
for col in range(c, c + size):
if binList[r][c] != 0:
return False
elif binList[r][c] == size:
return False
return True
def checker(binList, gSize, blockList):
for i in blockList:
r = 0
c = 0
comp = False
while comp != True:
check = isSpaceFree(binList, r, c, i)
if check == True:
for x in range(c, c+ i):
for y in range(r, r+ i):
binList[x][y] = i
comp = True
else:
print(c)
print(r)
r += 1
if r > gSize:
r = 0
c += 1
if c > gSize:
print("Imcompadible")
comp = True
print(i)
binPrint(binList)
input()
return binList
Your code to test for open spaces looks in binList[r][c] (where r is a row value and c is a column value). However, the code that sets the values once an open space has been found sets binList[x][y] (where x is a column value and y is a row value).
The latter is wrong. You want to set binList[y][x] instead (indexing by row, then column).
That will get you a working solution, but it will still not be exactly what you say you expect (you'll get a reflection across the diagonal). This is because your code updates r first, then c only when r has exceeded the bin size. If you want to place items to the right first, then below, you need to swap them.
I'd suggest using two for loops for r and c, rather than a while too, but to make it work in an elegant way you'd probably need to factor out the "find one item's place" code so you could return from the inner loop (rather than needing some complicated code to let you break out of both of the nested loops).