Three values for a for loop - python

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.

Related

Counting the number of floats in a list between a range in python

I've been stuck on this task for a while. I've managed to generate 1500 coordinates that give me a float between 0 and 2 (x,y), using the code below.
coordinates = [(random.random()*2.0, random.random()*2.0) for _ in range(15000)]
print(coordinates)
However now I need to create a counter that counts the number of floats between 0 and 1 and outputs it to the user. Ive tried using If statements and while loops. I've also had a snoop around the internet and am unable to find anything of use. Does anyone know how to work this out?
Kind regards.
You can use a simple conditional sum() over your tuples and sum up 1 if x or/and y are smaller then 1:
import random
# your code used 15k tuples, your text says 1.5k - adapt the number to your liking
coordinates = [(random.random()*2.0, random.random()*2.0) for _ in range(1500)]
one_lower_1 = sum(1 for x,y in coordinates if x < 1 or y < 1)
both_lower_1 = sum(1 for x,y in coordinates if x < 1 and y < 1)
x_lower_1 = sum(1 for x,_ in coordinates if x < 1)
y_lower_1 = sum(1 for _,y in coordinates if y < 1)
print(one_lower_1)
print(both_lower_1)
print(x_lower_1)
print(y_lower_1)
Output
1134
383
745
772
This is essentially a generator expression that filters out only those pairs that match the part after if .... from your generated coordinates
I choose the sum(1 ... ) approach because that way you do not have to create a list to take its len() ... it is more memory friendly if you just need the count of elements then producing all the elements.
Alternate way from jpp's comment:
sum(x < 1 or y < 1 for x,y in coordinates)
this works because a sum over 10 True 's give 10 - each True counting as 1:
print(sum(True for _ in range(10))) # 10
This should get you started. It's another list comprehension checking your list of coordinate pairs to see if each x and y is within the interval (0,1).
from random import random
print(len([(x,y) for x,y in [(2*random(),2*random()) for _ in range(1500)] if 0 < x < 1 and 0 < y < 1]))
If your only goal is to count all the pairs such that the x,y pairs are in the interval (0,1) then while loop would be more efficient by avoiding creating lists.
def rand_coordinates(num_of_pairs):
"""Counts the number of randomly generated x,y
pairs in the range of [0,2) where x and y are
contained in the interval from (0,1)"""
count = 0
while num_of_pairs:
x,y = 2*random(),2*random()
if 0 < x < 1 and 0 < y < 1:
count += 1
num_of_pairs -= 1
return count

Joining each element of a list to another element in Python

I have written a piece of code as given below.
import math
import numpy
Theta = 0.5
cList = numpy.arange(-10, 10, 0.05)
NList = [5,10,100,1000]
for N in NList:
for c in cList:
math.floor(Theta + float(c*Theta*(1-Theta))/float(math.sqrt(N))
The last line, for each N in NList and c in cList produces an integer. For such integer produced, I want to create a list starting from 0 to that number, and calculate (N choose K)*(0.5)^N for each element of that list and then sum them.
For instance, let say for some N in NList and c in CList, the last gives 5. Then I want to get a list from 0 to 5, which is [0,1,2,3,4,5] and calculate (N choose k)*(0.5)^N for each of [0,1,2,3,4,5] and then sum the calculated values.
Not sure how to do that. It would be great if someone can help me with that. I tried using range functions etc. but not sure how to do 0,5 and then apply list to it. Thanks.
>>> for x in range(5):
... print x
...
0
1
2
3
4
>>> sum(x * 2 for x in range(5))
20

For loop in CS Circles section 7C coding exercise: One Triangle

Here is an example of a for loop inside another for loop.
Example
This code prints a 5×5 square of ones.
Note: when we multiply a number X by ten and add one, we're essentially putting an extra 1 digit at the end of X. For example, (1867*10)+1=18671.
for i in range(0, 5):
X = 0
for j in range(0, 5):
X = (X*10)+1
print(X)
Modify the previous program in two ways. First, instead of a square, make it draw a triangle shaped like this: ◤. Second, instead of always having 5 lines, it should take the desired size as input from input(). For example, if the input is 3, then the output should be
111
11
1
So far the code that I have got is:
X=input()
for i in range(0, 3):
X = 0
for j in range(0, 3):
X = (X*10)+1
print(X)
However this code outputs:
1
11
111
When the expected output should be:
111
11
1
I can't seem to figure out how to change my code that I have so far to get the expected output?
This can solve the problem for you:
def test(X,_range):
x = X
for j in range(0, _range):
print int(str((x*10) +1) + ("1"*(_range-1-j)))
test(0,3)
>>>
111
11
1
>>>
In every loop step the number starts with (X*10)+1
In the next step X has changed and you add the digit 1 to the right side
If want to reverse it, you need to use ("1"*(_range-1-j))
The for iterator changes the X content every step. (he don't use i and j, "For" only for step derivation )
Here's the solution:
n=int(input())
for i in range(0, n):
X = 0
for j in range(0, n-i):
X = (X*10)+1
print(X)
As you said, 10*X + 1 means putting extra 1 at the end of X. You need an inverse operation: how to remove the last digit of a number. Hint: integer division. Google "python integer division" to get to pages such as Python integer division yields float.
So, then all you've to do is construct 111...11 of the right length, and then iteratively print and remove digits one by one.
This block is very confusing, here's what happens:
X=input()
Get value of X from input.
for i in range(0, 3):
X = 0
Now set the value of X to 0 three times (overwriting your input)
for j in range(0, 3):
X = (X*10)+1
print(X)
Now X is being set to 1, then 11 and then 111.
Even if you meant to nest the for loops, this wont behave right. Instead, you want to get the i value to loop backwards, using the slice operator [::-1]. You should then make j's range be zero to i.
You'll also need to compensate by increasing the value of both numbers in i's range (otherwise the last line will be a zero) but this will work:
for i in range(1, 6)[::-1]:
X = 0
for j in range(0, i):
X = (X*10)+1
print(X)
Note that I moved the print out of the j loop, as that wasn't how the original code was (and generated the wrong output), pay attention to whitespace. Using 4 spaces is preferable to just 2 for reasons like this.
If you are doing CS Circles than these other answers probably contain code you still haven't come in contact with, at least I haven't, so I'll try to explain it with the knowledge I've gathered so far (couple weeks doing CS Circles).
You are ignoring the first loop and it is where your answer lies. Notice that if you put the print command outside of the loop body it would just output:
111
That it because your second loop is not in the body of the first, so python just loops the first one 3x and than moves to the second loop. Instead it should be:
for i in range(0, 3):
X = 0
for j in range (0, 3):
X = (X*10)+1
print(X)
Now the program outputs:
111
111
111
But you want one less digit each time print is called again. This is achieved by subtracting the value of "i" (since it neatly goes from 0 to 2) from second loop's range tail value. So now you have :
for i in range(0, 3):
X = 0
for j in range(0, 3-i):
X = (X*10)+1)
print(X)
Finally the output is:
111
11
1
Protip: use the visualizer in CS Circles, it helps you better understand the way code is executed in python, and can provide insight to your problems. Best of luck!
The easiest way is to use the following code;
p = int(input())
for i in range(0,p):
x = 0
for j in range(i,p):
x = (x*10)+1
print(x)

Python find max number of combinations in binary

Hi I'm trying to figure out a function where given a length n of a list [x1, x2... xn], how many digits would be needed for a base 2 number system to assign a unique code to each value in the list.
For example, one digit can hold two unique values:
x1 0
x2 1
two digits can hold four:
x1 00
x2 01
x3 10
x4 11
etc. I'm trying to write a python function calcBitDigits(myListLength) that takes this list length and returns the number of digits needed. calcBitDigits(2) = 1, calcBitDigits(4) = 2, calcBitDigits(3) = 2, etc.
>>> for i in range(10):
... print i, i.bit_length()
0 0
1 1
2 2
3 2
4 3
5 3
6 3
7 3
8 4
9 4
I'm not clear on exactly what it is you want, but it appears you want to subtract 1 from what bit_length() returns - or maybe not ;-)
On third thought ;-), maybe you really want this:
def calcBitDigits(n):
return (n-1).bit_length()
At least that gives the result you said you wanted in each of the examples you gave.
Note: for an integer n > 0, n.bit_length() is the number of bits needed to represent n in binary. (n-1).bit_length() is really a faster way of computing int(math.ceil(math.log(n, 2))).
Clarification: I understand the original question now ;-) Here's how to think about the answer: if you have n items, then you can assign them unique codes using the n integers in 0 through n-1 inclusive. How many bits does that take? The number of bits needed to express n-1 (the largest of the codes) in binary. I hope that makes the answer obvious instead of mysterious ;-)
As comments pointed out, the argument gets strained for n=1. It's a quirk then that (0).bit_length() == 0. So watch out for that one!
Use the following -
import math
int(math.ceil(math.log(x,2)))
where x is the list length.
Edit:
For x = 1, we need to have a separate case that would return 1. Thanks #thefourtheye for pointing this out.
I am not comfortable with the other answers, since most of them fail at the corner case (when n == 1). So, I wrote this based on Tim's answer.
def calcBitDigits(n):
if n <= 0: return 0
elif n <= 2: return 1
return (n-1).bit_length()
for i in range(10):
print i, calcBitDigits(i)
Output
0 0
1 1
2 1
3 2
4 2
5 3
6 3
7 3
8 3
9 4
x = int(log(n,2))+1
x will be the number of bits required to store the integer value n.
If for some reason you don't want to use .bit_length, here's another way to find it.
from itertools import count
def calcBitDigits(n):
return next(i for i in count() if 1<<i >= n)

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