Python Array out of bounds error - python

I am getting an array error out of bounds issue. I am trying loop through a multi-dimensional array and add the value from the formula to each element. How do i fix the loop so i jump out of the array bounds.
z=int(4.3/7.9)
V =51
T =51
r = 1
c = 1
a=[[0]*c for i in range(r)]
for r in range(1,51):
for c in range(1,51):
a[c][r]=35.74 + 0.6215*T - (35.75*V)**0.16 + (0.4275*T*V)**0.16
print()
#print to html file down below
outfile=open("c:\\data\\pfile.html","w")
outfile.write("<!DOCTYPE html>")
outfile.write("<html>")
outfile.write("<head>")
outfile.write("<title>Kye Fullwood</title>")
outfile.write("<style> table,td{border:1px solid black;border-collaspse:collapse;background-color:aqua;}</style>\r\n")
outfile.write("</head>")
outfile.write("<body>")
outfile.write("<h1>This is a Windchill table</h1>")
outfile.write("<table>")
for V in range(1,51,1):
outfile.write("<tr>")
for TV in range(1,51,1):
outfile.write("<td>"+str(a[r][c])+"</td>\r\n")
outfile.write("</tr>")
outfile.write("</table>")
outfile.write("</body>")
outfile.write("</html>")
outfile.close()
print("complete")

a=[[0]*c for i in range(r)]
basically means a=[[0]] because your code starts with c=1 and r=1. So when you try to access matrix a with indices in range(1,51) you got an "out of range" exception, as there is only one element in your matrix.
To create a 50x50 null matrix, the following python idiom could be used:
a = [[0 for col in range(50)] for row in range(50)]
but I guess from your code that you actually need this one:
a = [[35.74 + 0.6215*T - (35.75*V)**0.16 + (0.4275*T*V)**0.16
for T in range(1,51)] for V in range(1,51)]

When you're initializing your list the way you do above
r = 1
c = 1
a=[[0]*c for i in range(r)]
because at that time c and r are both 1, your list looks like this -- [[0]] -- so you're going to get out of range errors when you try to update any indices in the list other than a[0][0]. Because in this code
for r in range(1,51):
for c in range(1,51):
a[c][r]=35.74 + 0.6215*T - (35.75*V)**0.16 + (0.4275*T*V)**0.16
you're going up to a[51][51], when you initialize the list in the first place you would need both r and c set to at least 52.
For that matter, in this code
for V in range(1,51,1):
outfile.write("<tr>")
for TV in range(1,51,1):
outfile.write("<td>"+str(a[r][c])+"</td>\r\n")
you're just going to be printing the same value 2500 times, because you're never changing r and c in those loops.

Related

Dividing by the power of digit position of integer

Here is what I want to accomplish :
a = 1235
My result r should calculate 1/2 + 2/(2*2) + 3/(2*2*2) + 5/(2*2*2*2), so
r will output 1.6875
I tried..
s = 123
l = list(map(int, str(s))) # converted into list
print(l)
y = [int(x)/(2**s.index(x)) for x in l]
print(y)
but it does not work.
Don't use index (slow and will return the first index over and over, which is wrong), just iterate on the index (plus 1) of the string using enumerate.
Then feed directly to sum.
BTW your code can be simplified to write this directly in one line:
y = sum(int(x)/(2**i) for i,x in enumerate(str(1235),1))
result:
1.6875

Complex behaviour with lists

I need to make some strange and complex calculation with lists. I have tried and I have endeavored to get it up and running, but it runs into error. better saying quite difficult to achieve that behavior.
I have following lists.
A = [1,1,1,2,2,2]
B = [3,3] # B list is length of numbers 1 and 2.
E = [10,10]
C = 1
D = []
I have this code, but not really working:
for k in B:
for j in E:
for i in range(len(A)-k):
print(i)
if i == 0:
D.append(C)
else:
D.append(C+(E[k]))
print(D)
Explaining to achieve results.
I want to have a for-loop, which enables to append values to my empty list, which looks at first 3 values in the beginning of list A by taking B[0]= 3, do something with first 3 values. And looks at B[1]= 3, ie. take the last 3 values in the list A, then do something to them and append them all in order to empty list.
First 3 values:
When A[0] is selected, I want to have D[0] = C, and in case A[1] and A[2], B list should be B[1]= C + 1*E[0] and B[2]= C + 2*E[0].
Last 3 values:
When A[3] is selected, I want to have D[3] = C, and in case A[4] and A[5], B list should be B[4]= C + 1*E[1] and B[5]= C + 2*E[1].
Expected output:
[1,11,21,1,11,21]
I want to get it programmatically, in case changing A list to A = [1,1,2,2] and B = [2,2] or something else.
Initialization of your lists
A = [1,1,1,2,2,2]
B = [3,3] # B list is length of numbers 1 and 2.
E = [10,10]
C = 1
D = []
we want to count in A starting the first time from 0, the next times from the previous start plus how many items we have used, hence we initialize start
start = 0
We start a loop on the elements b of B, counting them in k, we extract from A the elements we need and update the start position for the next pass
for k, b in enumerate(B):
sub_A = A[start:start+b]
start = start+b
Now an inner loop on the elements a of the sub-list, counting them with i, note that for the first item i is zero and so we append C+0*E[k]=C, as requested
for i, _ in enumerate(sub_A):
D.append(C+i*E[k])
To see everything without my comments
start = 0
for k, b in enumerate(B):
sub_A = A[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
D.append(C+i*E[k])

How to compare 4 consecutive elements in a list?

I am new to coding so I apologize in advance if what I am asking is simple or doesn't make much sense but I will try to elaborate as much as I can. First of all this is not for any work or project I am simply studying to learn a bit of coding for my satisfaction. I've been trying to find some real life problems to apply into coding (pseudo code mostly but python language would also be kind of understandable to me).
I wanted to be able to have a list of x elements and compare 4 of them sequentially.
For example, myList = [a, b, c, d, e, f, g, h, i, j, k, l]
First I want to compare a,b,c and d.
If b>a, c>b, d>c and d> all of 3 previous ones (d>a, d>b, d>c) I want to do something otherwise go to next comparison.
Then I wanted to compare b,c,d and e.
Similarly if c>b, d>c, e>d and e> all of 3 previous ones (e>b, e>c, e>d) I want to do something otherwise go to next comparison.
What if my list contains infinite elements? myList = [:]
Where do I start? Do I have to have a starting point?
I am guessing I have to use a for loop to iterate through the list but I honestly can't figure out how to iterate through the first 4 elements and then continue from the second element in 4 element batches.
Since I am currently studying the Arrays and lists maybe there is some functionality I am missing? Or I simply my brain can grasp it.
I tried looking at other posts in stackoverflow but honestly I can't figure it out from other people's answers. I would appreciate any help or guidance.
Thanks in advance.
You can use the built-in all() function for this problem:
myList = [5, 4, 3, 6, 3, 5, 6, 2, 3, 10, 11, 3]
def do_somthing():
#your code here
pass
for i in range(len(myList)-4):
new_list = myList[i:i+4] #here, using list slicing to jump ahead four elements.
if all(new_list[-1] > b for b in new_list[:-1]) and all(new_list[:-1][c] > new_list[:-1][c+1] for c in range(len(new_list)-2)):
do_something()
L = [...]
# get all the valid indices of the elements in the list, except for the last 4. These are the indices at which the 4-element windows start
for i in range(len(L)-4):
window = L[i:i+4] # the 4 elements you want to compare
print("I am considering the elements starting at index", i, ". They are:", window)
a,b,c,d = window
if d>a>b>c<d and d>b:
print("The checks pass!")
Now, there is a simpler way to do this:
for a,b,c,d in (L[i:i+4] for i in range(len(L)-4):
if d>a>b>c<d and d>b:
print("The checks pass!")
to consume just one item at a time from an iterator and operate on 4 lagged elements try a circle buffer:
# make a generator as example of 'infinte list'
import string
agen = (e for e in string.ascii_lowercase)
# initialize len 4 circle buffer
cb = [next(agen) for _ in range(4)] # assumes there are at least 4 items
ptr = 0 # initialize circle buffer pointer
while True:
a,b,c,d = (cb[(i+ptr)%4] for i in range(4)) # get current 4 saved items
# some fuction here
print(a,b,c,d)
# get next item from generator, catch StopIteration on empty
try:
cb[ptr] = next(agen)
except StopIteration:
break
ptr = (ptr + 1)%4 # update circle buffer pointer
a b c d
b c d e
c d e f
d e f g
e f g h
f g h i
g h i j
h i j k
i j k l
j k l m
k l m n
l m n o
m n o p
n o p q
o p q r
p q r s
q r s t
r s t u
s t u v
t u v w
u v w x
v w x y
w x y z
'some function' could include a stopping condition too:
# random.choice() as example of 'infinte iterator'
import string
import random
random.choice(string.ascii_lowercase)
# initialize len 4 circle buffer
cb = [random.choice(string.ascii_lowercase) for _ in range(4)] # assumes there are at least 4 items
ptr = 0 # initialize circile buffer pointer
while True:
a,b,c,d = (cb[(i+ptr)%4] for i in range(4)) # get current 4 saved items
# some fuction here
print(a,b,c,d)
if a<b<c<d: # stopping condition
print("found ordered string: ", a,b,c,d)
break
# get next item from generator, catch StopIteration on empty
try:
cb[ptr] = random.choice(string.ascii_lowercase)
except StopIteration:
break
ptr = (ptr + 1)%4 # update circle buffer pointer
o s w q
s w q k
w q k j
q k j r
k j r q
j r q r
r q r u
q r u v
found ordered string: q r u v
Since you can index a list, how about start from index 0, compare the 0th, (0+1)th, (0+2)th, and (0+3)th elements. Then, by the next round, increase your index to 1, and compare the 1st, (1+1)th, (1+2)th, and (1+3)th elements, and so on. For the nth round, you compare the n, n+1, n+2, and (n+3)th elements, until you reach the 4th element before the end. This is how you generally do stuff like 'testing m elements each time from a sequence of length n', and you can easily expand this pattern to matrices or 3d arrays. The code you see in other answers are basically all doing this, and certain features in Python make this job very easy.
Now, 'what if the list contains infinite elements'? Well, then you'll need a generator, which is a bit advanced at this stage I assume, but the concept is very simple: you let a function read that infinite stream of elements in a (might be infinite) loop, set a cursor on one of them, return (yield) the element under the cursor as well as the 3 elements following it each time, and increase the cursor by one before the next loop starts:
def unsc_infinity(somelist):
cur = 0
while True:
yield somelist[c:c+4]
cur = cur + 1
infinity_reader = unsc_infinity(endless_stream)
next(infinity_reader)
# gives the 0, 1, 2, 3 th elements in endless_stream
next(infinity_reader)
# gives the 1, 2, 3, 4 th elements in endless_stream
next(infinity_reader)
# ...
And you can loop over that generator too:
for a, b, c, d in unsc_infinity(endless_stream):
if d>a>b>c<d and d>b:
do_something()
Hope that helps a bit for you to build a mental model about how this kind of problems are done.

'float' object is unsubscriptable

thats what I get:
TypeError: 'float' object is unsubscriptable
Thats what I did:
import numpy as N
import itertools
#I created two lists, containing large amounts of numbers, i.e. 3.465
lx = [3.625, 4.625, ...]
ly = [41.435, 42.435, ...] #The lists are not the same size!
xy = list(itertools.product(lx,ly)) #create a nice "table" of my lists
#that iterttools gives me something like
print xy
[(3.625, 41.435), (3.625, 42.435), (... , ..), ... ]
print xy[0][0]
print xy[0][1] #that works just fine, I can access the varios values of the tuple in the list
#down here is where the error occurs
#I basically try to access certain points in "lon"/"lat" with values from xy through `b` and `v`with that iteration. lon/lat are read earlier in the script
b = -1
v = 1
for l in xy:
b += 1
idx = N.where(lon==l[b][b])[0][0]
idy = N.where(lat==l[b][v])[0][0]
lan/lot are read earlier in the script. I am working with a netCDF file and this is the latitude/longitude,read into lan/lot.
Its an array, build with numpy.
Where is the mistake?
I tried to convert b and v with int() to integers, but that did not help.
The N.where is accessing through the value from xy a certain value on a grid with which I want to proceed. If you need more code or some plots, let me know please.
Your problem is that when you loop over xy, each value of l is a single element of your xy list, one of the tuples. The value of l in the first iteration of the loop is (3.625, 41.435), the second is (3.625, 42.435), and so on.
When you do l[b], you get 3.625. When you do l[b][b], you try to get the first element of 3.625, but that is a float, so it has no indexes. That gives you an error.
To put it another way, in the first iteration of the loop, l is the same as xy[0], so l[0] is the same as xy[0][0]. In the second iteration, l is the same as xy[1], so l[0] is the same as xy[1][0]. In the third iteration, l is equivalent to xy[2], and so on. So in the first iteration, l[0][0] is the same as xy[0][0][0], but there is no such thing so you get an error.
To get the first and second values of the tuple, using the indexing approach you could just do:
x = l[0]
y = l[1]
Or, in your case:
for l in xy:
idx = N.where(lon==l[0])[0][0]
idy = N.where(lat==l[1])[0][0]
However, the simplest solution would be to use what is called "tuple unpacking":
for x, y in xy:
idx = N.where(lon==x)[0][0]
idy = N.where(lat==y)[0][0]
This is equivalent to:
for l in xy:
x, y = l
idx = N.where(lon==x)[0][0]
idy = N.where(lat==y)[0][0]
which in turn is equivalent to:
for l in xy:
x = l[0]
y = l[1]
idx = N.where(lon==x)[0][0]
idy = N.where(lat==y)[0][0]

python -- IndexError: list index out of range / dividing lists

I'm not great at programming and I've been driving myself crazy trying to figure this out.
I have a program to calculate binding energies that stores values in lists. At a certain point one list is divided by a different one, but I keep getting this error:
Traceback (most recent call last):
File "semf.py", line 76, in <module>
BpN = BpN(A, Z)
File "semf.py", line 68, in BpN
bper = B[i]/A[i]
IndexError: list index out of range
The relevant code is below, sorry there's so much of it:
A = 0.0
def mass_A(Z):
"""
ranges through all A values Z, ..., 3Z+1 for Z ranging from 1 to 100
"""
a = 0.0
a = np.arange(Z, 3*Z+1)
return a
def semf(A, Z):
"""
The semi-empirical mass formula (SEMF) calculates the binding energy of the nucleus.
N is the number of neutrons.
"""
i = 0
E = []
for n in A:
# if statement to determine value of a5
if np.all(Z%2==0 and (A-Z)%2==0):
a5 = 12.0
elif np.all(Z%2!=0 and (A-Z)%2!=0):
a5 = -12.0
else:
a5 = 0
B = a1*A[i] - a2*A[i]**(2/3) - a3*(Z**2 / A[i]**(1/3)) - a4*( (A[i] - 2*Z)**2 / A[i] ) + a5 / A[i]**(1/2)
i += 1
E.append(B)
return E
def BpN(A, Z):
"""
function to calculate the binding energy per nucleon (B/A)
"""
i = 0
R = []
for n in range(1,101):
bper = B[i]/A[i]
i += 1
R.append(bper)
return R
for Z in range(1,101):
A = mass_A(Z)
B = semf(A, Z)
BpN = BpN(A, Z)
It seems like somehow, the two lists A and B aren't the same length, but I'm not sure how to fix that issue.
Please help.
Thanks
In Python, list indices start from zero and not from one.
It's hard to be sure without seeing your code in its entirety, but range(1,101) looks suspect. If the list has 100 elements, the correct bounds for the loop are range(0,100) or, equivalently, range(100) or, better still, range(len(A)).
P.S. Since you're using Numpy already, you should look into rewriting your code using Numpy arrays instead of using lists and loops. If A and B were Numpy arrays, your entire troublesome function could become:
return B / A
(This is element-wise division of B by A.)

Categories

Resources