Error i not defined in for loop using python - python

I have one array 'barray' of size 'bsize' and another 'carray' of size 'csize'.
The i loop is for barray and j loop is for carray.
I get an error that i is not defined. I want the loops to go from 0 to bsize - 2 in steps of 3, and 0 to csize - 2 in single steps.
How should I relate the size and array to the for loop?
bsize = 960
csize = 960
barray = bytearray(fi.read())
carray= bytearray(f1.read())
for i in range (bsize-2,i+3):
for j in range (csize-2,j+1):

for i in range (0, bsize - 2, 3): #possibly bsize - 1?
for j in range (csize - 2): # possibly csize - 1?
#do your thing
That will loop through the first one incrementing i by 3 every time, and j by 1.
Look at this tutorial or these docs to learn range, it's really useful!
I'm not sure if you want to go through bsize - 2 or just up to it. If through, use size - 1 to get size - 2.
The reason you're getting an error is that you haven't defined the i you're using in the step. As you can see, python's range isn't like a lot of other languages' for constructs. Once you get used to it, though, it's really flexible and easy to use.
Some examples using simple range:
>>> for i in range(0, 14, 3):
... print i
...
0
3
6
9
12
>>> for i in range(1, 5):
... print i
...
1
2
3
4
>>> for i in range(5):
... print i
...
0
1
2
3
4

Related

Python , how to convert this iterations into for loop

this are the iterations
i = 0
s_array[i].append(f_array[i][i])
s_array[i].append(f_array[i+1][i])
s_array[i].append(f_array[i+2][i])
s_array[i+1].append(f_array[i][i+1])
s_array[i+1].append(f_array[i+1][i+1])
s_array[i+2].append(f_array[i][i+2])
I want to convert this iterations into for loop
for example like this
for i in range(something):
for j in range(something):
s_array[i].append(f_array[j][i])
I tried many trial and errors, but didn't got any solution
The equivalent iterations:
for i in range(3):
for j in range(3 - i):
s_array[i].append(f_array[j][i])
For example:
for i in range(3):
for j in range(3 - i):
print(i,"-->", j, i)
print("")
Output:
0 --> 0 0
0 --> 1 0
0 --> 2 0
1 --> 0 1
1 --> 1 1
2 --> 0 2
Since you are trying to append values to an array using loops, you could try nested for loops as you have indicated. Also, since you are appending fewer values as the iterations continue, you could implement a negative step value for one of the range() functions in the loops so that you iterate fewer times.
Try doing something like this:
for i in range(3):
for j in range(3-i):
s_array[i].append(f_array[j][i])
Hopefully, this should solve your problem.

Three values for a for loop

I would like to have three values increment at different speeds. My overall goal is to emulate this pattern:
0,0, 0
0,1, 1
0,2, 2
1,0, 3
1,1, 4
1,2, 5
2,0, 6
2,1, 7
2,2, 8
The first two numbers are easy. I would solve it like this:
for x in range(3):
for y in range(3):
print(x, y)
>>> 0 0
>>> 0 1
>>> 0 2
>>> 1 0
>>> 1 1
>>> 1 2
>>> 2 0
>>> 2 1
>>> 2 2
This is the pattern that I want.
The question is how do I increment the third number by one each time, while still having the first two numbers increment in the way that they are?
Basically, how can I make the third number increment by one each time the for loop goes?
Since we have all these answers, I will post the most straightforward one
count = 0
for x in range(3):
for y in range(3):
print(x, y, count)
count += 1
You don't need nested loops for this. You can use itertools.product to get your first two numbers, and enumerate to get your last one.
from itertools import product
for i, (u, v) in enumerate(product(range(3), repeat=2)):
print(u, v, i)
output
0 0 0
0 1 1
0 2 2
1 0 3
1 1 4
1 2 5
2 0 6
2 1 7
2 2 8
itertools.product is a very handy function. It basically performs nested loops efficiently, but its main benefit is that they don't look nested, so you don't end up with massively indented code. However, its real strength comes when you don't know how many nested loops you need until runtime.
enumerate is probably even more useful: it lets you iterate over a sequence or any iterable and returns the iterable's items as well as an index number. So whenever you need to loop over a list but you need the list items and their indices as well, it's more efficient to use enumerate to get them both at once, rather than having a loop that uses range to produce the index and then using the index to fetch the list item.
The third number counts how many total iterations you had so far. For each increment in X it gains the total size of Y's loop, and to that you need to add the value of Y:
X_SIZE = 3
Y_SIZE = 3
for x in range(X_SIZE):
for y in range(Y_SIZE):
print(x, y, x * Y_SIZE + y)
single variable. single loop.
for i in range(9):
print(i // 3, i % 3, i)
// is floor division and % is modulus (the remainder, in most cases)
Personally, I like this solution because it plainly explains the underlying pattern, and can therefore be easily altered or extended to other patterns.
Try this:
for x in range(3):
for y in range(3):
print(x, y, x * 3 + y) # Python 3.x
print x, y, x * 3 + y # Python 2.x
Hope this helps.
You can use simply a count variable for this
count = 0
for x in range(3):
for y in range(3):
print(x, y, ' ' ,count) # use ' ' for making exact look what OP asked..lol
count = count + 1
This looks more natural to me :)
x_range = 3
y_range = 3
for x in range( x_range*y_range ):
print(x // x_range, x % x_range, x)
Similar to what cwharris wrote.

Pythonic way to iterate through a range starting at 1

Currently if I want to iterate 1 through n I would likely use the following method:
for _ in range(1, n+1):
print(_)
Is there a cleaner way to accomplish this without having to reference n + 1 ?
It seems odd that if I want to iterate a range ordinally starting at 1, which is not uncommon, that I have to specify the increase by one twice:
With the 1 at the start of the range.
With the + 1 at the end of the range.
From the documentation:
range([start], stop[, step])
The start defaults to 0, the step can be whatever you want, except 0 and stop is your upper bound, it is not the number of iterations. So declare n to be whatever your upper bound is correctly and you will not have to add 1 to it.
e.g.
>>> for i in range(1, 7, 1): print(i)
...
1
2
3
4
5
6
>>> for i in range(1, 7, 2): print(i)
...
1
3
5
A nice feature, is that it works in reverse as well.
>>> for i in range(7, 0, -1): print(i)
...
7
6
5
4
3
2
1
If you aren't using it as an index but for something that can have positive or negative values, it still comes in handy:
>>> for i in range(2, -3, -1): print(i)
...
2
1
0
-1
-2
>>> for i in range(-2, 3, 1): print(i)
...
-2
-1
0
1
2
range(1, n+1) is not considered duplication, but I can see that this might become a hassle if you were going to change 1 to another number.
This removes the duplication using a generator:
for _ in (number+1 for number in range(5)):
print(_)
for i in range(n):
print(i+1)
This will output:
1
2
...
n
Not a general answer, but for very small ranges (say, up to five), I find it much more readable to spell them out in a literal:
for _ in [1,2,3]:
print _
That's true even if it does start from zero.
range(1, n+1) is common way to do it, but if you don't like it, you can create your function:
def numbers(first_number, last_number, step=1):
return range(first_number, last_number+1, step)
for _ in numbers(1, 5):
print(_)

How to make a triangle using a for loop in Python

I'm new to programming and have been experimenting with for loops to try and figure out how to make different shapes however I have encountered a problem that I cannot solve.
So far I have been able to create a rectangle of 1's as shown below in a 5X5
for i in range(0, 5):
X = 0
for j in range(0, 5):
X = (X*10)+1
print(X)
I would like to be able to modify this code using a for loop to be able to create a triangle like so...
1 1 1
1 1
1
How would I go about doing this? Is there also a way that I could input n and dependant on whatever number is input the program creates a triangle of that size? for example I input a 5 and it creates a triangle like...
11111
1111
111
11
1
Ive tried various different things but i'm unable to figure it out.
def triangle(c, n):
for i in xrange(n, 0, -1):
print c * i
triangle("X", 5)
prints:
XXXXX
XXXX
XXX
XX
X
don't try to modify it.
make a new one
def generateLine(size):
line = ""
for i in range(0, size):
line = line+"1"
return line
for i in range(6, 0):
print generateLine(i)

Formulation of a recursive solution (variable for loops)

Please consider the below algorithm:
for(j1 = n upto 0)
for(j2 = n-j1 upto 0)
for(j3 = n-j1-j2 upto 0)
.
.
for (jmax = n -j1 - j2 - j_(max-1))
{
count++;
product.append(j1 * j2 ... jmax); // just an example
}
As you can see, some relevant points about the algo snippet above:
I have listed an algorithm with a variable number of for loops.
The result that i calculate at each innermost loop is appended to a list. This list will grow to dimension of 'count'.
Is this problem a suitable candidate for recursion? If yes, i am really not sure how to break the problem up. I am trying to code this up in python, and i do not expect any code from you guys. Just some pointers or examples in the right direction. Thank you.
Here is an initial try for a sample case http://pastebin.com/PiLNTWED
Your algorithm is finding all the m-tuples (m being the max subscript of j from your pseudocode) of non-negative integers that add up to n or less. In Python, the most natural way of expressing that would be with a recursive generator:
def gen_tuples(m, n):
if m == 0:
yield ()
else:
for x in range(n, -1, -1):
for sub_result in gen_tuples(m-1, n-x):
yield (x,)+sub_result
Example output:
>>> for x, y, z in gen_sums(3, 3):
print(x, y, z)
3 0 0
2 1 0
2 0 1
2 0 0
1 2 0
1 1 1
1 1 0
1 0 2
1 0 1
1 0 0
0 3 0
0 2 1
0 2 0
0 1 2
0 1 1
0 1 0
0 0 3
0 0 2
0 0 1
0 0 0
You could also consider using permutations, combinations or product from the itertools module.
If you want all the possible combinations of i, j, k, ... (i.e. nested for loops)
you can use:
for p in product(range(n), repeat=depth):
j1, j2, j3, ... = p # the same as nested for loops
# do stuff here
But beware, the number of iterations in the loop grows exponentially!
the toy example will translate into a kind of tail recursion so, personally, i wouldn't expect a recursive version to be more insightful for code review and maintenance.
however, to get acquainted to the principle, attempt to factor out the invariant parts / common terms from the individual loop and try to identify a pattern (and best prove it afterwards!). you should be able to fix a signature of the recursive procedure to be written. flesh it out with the parts inherent to the loop body/ies (and don't forget the termination condition).
Typically, if you want to transform for loops into recursive calls, you will need to replace the for statements with if statements. For nested loops, you will transform these into function calls.
For practice, start with a dumb translation of the code that works and then attempt to see where you can optimize later.
To give you an idea to try to apply to your situation, I would translate something like this:
results = []
for i in range(n):
results.append(do_stuff(i, n))
to something like this:
results = []
def loop(n, results, i=0):
if i >= n:
return results
results.append(do_stuff(i, n))
i += 1
loop(n, results, i)
there are different ways to handle returning the results list, but you can adapt to your needs.
-- As a response to the excellent listing by Blckgnht -- Consider here the case of n = 2 and max = 3
def simpletest():
'''
I am going to just test the algo listing with assumption
degree n = 2
max = dim(m_p(n-1)) = 3,
so j1 j2 and upto j3 are required for every entry into m_p(degree2)
Lets just print j1,j2,j3 to verify if the function
works in other general version where the number of for loops is not known
'''
n = 2
count = 0
for j1 in range(n, -1, -1):
for j2 in range(n -j1, -1, -1):
j3 = (n-(j1+j2))
count = count + 1
print 'To calculate m_p(%d)[%d], j1,j2,j3 = ' %(n,count), j1, j2, j3
assert(count==6) # just a checkpoint. See P.169 for a proof
print 'No. of entries =', count
The output of this code (and it is correct).
In [54]: %run _myCode/Python/invariant_hack.py
To calculate m_p(2)[1], j1,j2,j3 = 2 0 0
To calculate m_p(2)[2], j1,j2,j3 = 1 1 0
To calculate m_p(2)[3], j1,j2,j3 = 1 0 1
To calculate m_p(2)[4], j1,j2,j3 = 0 2 0
To calculate m_p(2)[5], j1,j2,j3 = 0 1 1
To calculate m_p(2)[6], j1,j2,j3 = 0 0 2
No. of entries = 6

Categories

Resources