How to do C++ style(indexed) nested loops in python? - loops

What is the equivalent of the following in python?
for (i=0; i<n; i++)
for (j=i+1; j<n; j++)
//do stuff with A[i], A[j]
Or in some sense, the following. It should also remove the element from A at the completion of each round of the loop.
for a in A:
for a' in A/{a}: #i.e. rest of the elements of A
#do something with a,a'
#remove a from A
Is there a pythonic way of doing this without using enumerate()?
Edits:
Sorry for the bad description.
In the first example, I mean to use i & j only as indices. Their values do not matter. Its just a rough c++ equivalent of the latter.
The outer loop is executed n times. The inner loop is executed (n-1), (n-2)...0 times for each iteration of the outer loop.
Maybe this might help (pseudocode):
function next_iteration(list):
head = first element
tail = remaining elements #list
each element in tail interacts with head one by one
next_iteration(tail)
PS: All code samples above are pseudocodes. I'm trying to express something that is still a bit vague in my mind.

I intepret what you're asking as
How can I iterate over all pairs of distinct elements of a container?
Answer:
>>> x = {1,2,3}
>>> import itertools
>>> for a, b in itertools.permutations(x, 2):
... print a, b
...
1 2
1 3
2 1
2 3
3 1
3 2
EDIT: If you don't want both (a,b) and (b,a), just use itertools.combinations instead.

Since your two questions are different, here is solution for your second problem:
for i in xrange(len(A)):
for j in xrange(len(A)):
if i != j:
do_stuff(A[i], A[j])
or using itertools (I think using the included batteries is very pythonic!):
import itertools
for a, b in itertools.permutations(A, 2):
do_stuff(a, b)
This applies do_stuff to all combinations of 2 different elements from A. I you want to store the result just use:
[do_stuff(a, b) for a, b in itertools.permutations(A, 2)]

How about:
for i in range(0,n):
for j in range (i+1,n):
# do stuff

for i in range(0,n):
for j in range(i+1,n):
# do stuff

Still can't leave comments.. but basically what the other two posts said - but get in the habit of using xrange instead of range.
for i in xrange(0,n):
for j in xrange(i+1,n):
# do stuff

You could make the inner loop directly over a slice. Not saying this is any better, but it is another approach.
for i in range(0,len(x)):
a = x[i]
for b in x[i+1:]:
print a, b

Another way to approach this is - if n is an sequence that provides the iterable interface, then in Python you can simplify your code by iterating over the object directly:
for i in n:
for some_var in n[n.index(i):]: # rest of items
# do something
I hope I understood your loop correctly, because as others have stated - they don't do the same thing.

For the first one of your questions, as already mentioned in other answers:
for i in xrange(n):
for j in xrange(i+1, n):
# do stuff with A[i] and A[j]
For the second one:
for i, a in enumerate(A):
for b in A[i+1:]:
# do stuff with a and b

Your psuedocode almost has it:
function next_iteration(list):
head = first element
tail = remaining elements #list
each element in tail interacts with head one by one
next_iteration(tail)
Python code:
def next_iteration(lst):
head, tail = lst[0], lst[1:]
for item in tail:
print(head, item)
if tail:
next_iteration(tail)
Which, when tried with next_iteration([1, 2, 3]), prints:
1 2
1 3
2 3

You can use xrange to generate values for i and j respectively as show below:
for i in xrange(0, n):
for j in xrange(i + 1, n):
# do stuff

In the first for-loop, enumerate() walks through the array and makes the index,value of each element available to the second for-loop. In the second loop, range() makes j = i+1 --> len(a) available. At this point you'd have exactly what you need which is i & j to do your operation.
>>> a = [1,2,3,4]
>>> array_len = len(a)
>>> for i,v in enumerate(a):
... for j in range(i+1, array_len):
... print a[i], a[j]
...
1 2
1 3
1 4
2 3
2 4
3 4
>>>

Related

How to handle errors in hash tables in python 3?

Getting a basic error in Hash tables
n = int(input("Enter the length of the array "))
a = [0 for i in range(n)]
for i in range(0,n):
a[i] = int(input("Enter elements of array: "))
# maxi = max(a)
# print(maxi)
has = [[0 for i in range(n)]
for j in range(2)]
for i in range(0,n):
if(a[i]>=0):
has[a[i]][0] = 1
else:
has[abs(a[i])][1] = 1
search = int(input("Enter the element to be searched: "))
# if(search>0):
def search1(search):
if(search>0):
if(a[search][0] == 1):
print("Present")
else:
print("Absent")
else:
search = abs(search)
if(a[search][1] == 1):
print("Present")
else:
print("absent")
Can anyone please help me out if why is this happening?
Error: list index out of range
This code first takes an array of input from the user and the numbers are then stored in a hash table based on positive or negative numbers. Then the search algorithm is made based on index itself to give the time complexity of O(1). But in between, I am getting a list index out of range error. Please help to solve the following error.
So, you are simulating a hash using a list, right? Here is the problem: The expression
[[0 for i in range(n)]
for j in range(2)]
generates a list of lists. If your print it, you'll see that is has two items (two lists), so an indexing operation like a[i] with i > 1 won't work. Maybe you wanted to generate a list with a different structure?
[[0 for i in range(2)]
for j in range(n)]
Or you can change the indexing logic, e.g. has[1][abs(a[i])] = 1.
In general, it helps to print the state of the variables in between to stay informed about what's going on.

Nested for-loops and their formats

I am using Python 2.7. From previous posts, I am learning Python and I have moved from arrays and now I am working on loops. I am also trying to work with operations using arrays.
A1 = np.random.random_integers(35, size=(10.,5.))
A = np.array(A1)
B1 = np.random.random_integers(68, size=(10.,5.))
B = np.array(B1)
D = np.zeros(10,5) #array has 10 rows and 5 columns filled with zeros to give me the array size I want
for j in range (1,5):
for k in range (1,5):
D[j,k] = 0
for el in range (1,10):
D[j,k] = D[j,k] + A[j] * B[k]
The error I am getting is : setting an array element with a sequence
Is my formatting incorrect?
Because A, B and D are all 2D arrays, then D[j,k]
is a single element, while A[j] (the same as A[j,:]) is a 1D array which, in this case, has 5 elements. Similar for B[k] = B[k,:], i.e. also a 5 element array.
A[j] * B[k] is therefore also five element array, which can not be stored in the place of a single element, and you therefore get the error: setting an array element with a sequence.
If you want to select single elements from A and B, then the last line should be
D[j,k] = D[j,k] + A[j,k] * B[j,k]
Some further comments on your code:
# A is already a numpy array, so 'A = np.array(A1)' is redundant and can be omitted
A = np.random.random_integers(35, size=(10.,5.))
# Same as above
B = np.random.random_integers(68, size=(10.,5.))
D = np.zeros([10,5]) # This is the correct syntax for creating a 2D array with the np.zeros() function
for j in range(1,5):
for k in range(1,5):
# D[j,k] = 0 You have already defined D to be zero for all elements with the np.zeros function, so there is no need to do it again
for el in range(1,75):
D[j,k] = D[j,k] + A[j] * B[k]
EDIT:
Well, I do not have enough reputation to comment on your post #Caroline.py, so I will do it here instead:
First of all, remember that python uses zero indexing, so 'range(1,5)' gives you '[1,2,3,4]', which means that you would not reach the first index, i.e. index 0. Thus you would probably want to use 'range(0,5)', which is the same as just 'range(5)', instead.
I can see that you changed the el range from 75 to 10. If you don't use el to anything, it just means that you add perform the last line 10 times.
I don't know what you want to do, but if you want to store the multiple of A and B in D, then this should be right:
for j in range(10):
for k in range(5):
D[j,k] = A[j,k] * B[j,k]
or just
D = A * B

Gnuplot: Nested “plot” iteration (“plot for”) with dependent loop indices

I have recently attempted to concisely draw several graphs in a plot using gnuplot and the plot for ... syntax. In this case, I needed nested loops because I wanted to pass something like the following index combinations (simplified here) to the plot expression:
i = 0, j = 0
i = 1, j = 0
i = 1, j = 1
i = 2, j = 0
i = 2, j = 1
i = 2, j = 2
and so on.
So i loops from 0 to some upper limit N and for each iteration of i, j loops from 0 to i (so i <= j). I tried doing this with the following:
# f(i, j, x) = ...
N = 5
plot for [i=0:N] for [j=0:i] f(i, j, x) title sprintf('j = %d', j)
but this only gives five iterations with j = 0 every time (as shown by the title). So it seems that gnuplot only evaluates the for expressions once, fixing i = 0 at the beginning and not re-evaluating to keep up with changing i values. Something like this has already been hinted at in this answer (“in the plot for ... structure the second index cannot depend on the first one.”).
Is there a simple way to do what I want in gnuplot (i.e. use the combinations of indices given above with some kind of loop)? There is the do for { ... } structure since gnuplot 4.6, but that requires individual statements in its body, so it can’t be used to assemble a single plot statement. I suppose one could use multiplot to get around this, but I’d like to avoid multiplot if possible because it makes things more complicated than seems necessary.
I took your problem personally. For your specific problem you can use a mathematical trick. Remap your indices (i,j) to a single index k, such that
(0,0) -> (0)
(1,0) -> (1)
(1,1) -> (2)
(2,0) -> (3)
...
It can be shown that the relation between i and j and k is
k = i*(i+1)/2 + j
which can be inverted with a bit of algebra
i(k)=floor((sqrt(1+8.*k)-1.)/2.)
j(k)=k-i(k)*(i(k)+1)/2
Now, you can use a single index k in your loop
N = 5
kmax = N*(N+1)/2 + N
plot for [k=0:kmax] f(i(k), j(k), x) title sprintf('j = %d', j(k))

Efficient method of merging two neighboring indicies in Scala

What would be a most efficient method of merging two neighboring indicies in Scala? What I have in mind a nasty while loops with copying.
For example, there's a buffer array A, with length N. The new array need be generated such that for A(i) = A(i) + A(i+1), where i < N
For example, merging and summing the second and third element, and generate a new array.
ArrayBuffer(1,2,4,3) => ArrayBuffer(1,6,3)
UPDATE:
I think I come up with some solution, but doesn't like it much. Any suggestion to improve would be highly appreciated.
scala> val i = 1
i: Int = 1
scala> ArrayBuffer(1,2,4,3).zipWithIndex.foldLeft(ArrayBuffer[Int]())( (k,v)=> if(v._2==i+1){ k(k.length-1) =(k.last+v._1);k; }else k+= v._1 )
The simplest way to get neighbors is to use sliding method.
a.sliding(2, 1).map(_.sum)
where the first argument is a size and the second one is step.
If you want to keep the first and the last element intact something like this should work:
a.head +: a.drop(1).dropRight(1).sliding(2, 1).map(_.sum).toArray :+ a.last
If you want to avoid copying and array on append/prepend you can rewrite it as follows:
val aa = a.sliding(2, 1).map(_.sum).toArray
aa(0) = a.head
aa(aa.size - 1) = a
or use ListBuffer which provides constant time prepend and append.
It should be also possible to use Iterators:
val middle: Iterator[Int] = a.drop(1).dropRight(1).sliding(2, 1).map(_.sum)
(Iterator(a.head) ++ middle ++ Iterator(a.last)).toArray // or toBuffer

Arrays from nested for loops in maxima

Using MAxima I want to create 11 arrays in maxima. I am trying something like this:
for n:1 step 1 while n<=11 do( for j:1 while j<=21 do( if i<j then aa[n][i,j]:i+j+n));
This compiles fine but I can not use it how I would like. Say for example I want value 2,2 in the 5th array, I try the following but it does not work:
aa[5][2,2];
Any help is appreciated,
Ben
Your code fragment is missing any loop over i or other assignment to i.
You might consider using 'genmatrix' to construct a matrix, and then a loop over n to generate several matrices. E.g.:
foo : lambda ([i, j], if i < j then i + j + n else 0);
for n:1 thru 11 do aa[n] : genmatrix (foo, 21, 21);
Then I get
aa[5][2, 2];
=> 0
aa[5][2, 3];
=> 10
grind (aa[10]);
=> matrix([0,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],
[0,0,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],
[0,0,0,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],
[0,0,0,0,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35],
[0,0,0,0,0,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],
[0,0,0,0,0,0,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],
[0,0,0,0,0,0,0,25,26,27,28,29,30,31,32,33,34,35,36,37,38],
[0,0,0,0,0,0,0,0,27,28,29,30,31,32,33,34,35,36,37,38,39],
[0,0,0,0,0,0,0,0,0,29,30,31,32,33,34,35,36,37,38,39,40],
[0,0,0,0,0,0,0,0,0,0,31,32,33,34,35,36,37,38,39,40,41],
[0,0,0,0,0,0,0,0,0,0,0,33,34,35,36,37,38,39,40,41,42],
[0,0,0,0,0,0,0,0,0,0,0,0,35,36,37,38,39,40,41,42,43],
[0,0,0,0,0,0,0,0,0,0,0,0,0,37,38,39,40,41,42,43,44],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,40,41,42,43,44,45],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,42,43,44,45,46],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,43,44,45,46,47],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,46,47,48],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,48,49],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,50],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,51],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])$

Resources