Project Euler #82 (Python) - python

First of all this is the problem : https://projecteuler.net/problem=82 .
This is my code :
# https://projecteuler.net/problem=82
matrice = open('matrix3.txt','r').read().split('\n')
m = []
for el in matrice:
if el=='':
continue
tmp = el.split(',')
m.append(tmp)
matrix = [[0 for i in range(80)]for j in range(80)]
x,y = 0,0
while(True):
matrix[x][y]=int(m[x][y])
y+=1
if y==80:
y=0
x+=1
if x==80:
break
tmp = [0]*80
x,y = 0,78
while(True):
if x==0:
tmp[x]=min(matrix[x][y+1],matrix[x+1][y]+matrix[x+1][y+1])
if x==79:
tmp[x]=min(matrix[x][y+1],matrix[x-1][y]+matrix[x-1][y+1])
else:
tmp[x]=min(matrix[x][y+1],matrix[x-1][y]+matrix[x-1][y+1],matrix[x+1][y]+matrix[x+1][y+1])
x+=1
if x==80:
for e in range(80):
matrix[e][y]+=tmp[e]
tmp = [0]*80
x=0
y+=-1
if y<0:
break
minimo = 10**9
for e in range(80):
if matrix[e][0]<minimo:
minimo=matrix[e][0]
print(minimo)
The idea behind this code is the following:
I start from the 79th column(78th if you start counting from 0) and I calculate the best(the minimal) way to get from any given entry in that column to the column to the right.
When the column is over I replace it with the minimal results I found and I start doing the same with the column to the left.
Is anyone able to help me understand why I get the wrong answer?(I get 262716)
The same code works for the matrix in the example(It works if you change the indeces of course).

If I understand the question, your code, and your algorithm correctly, it looks like you aren't actually calculating the best way to get from one column to the next because you're only considering a couple of the possible ways to get to the next column. For example, consider the first iteration (when y=78). Then I think what you want is tmp[0] to hold the minimum sum for getting from matrix[0][78] to anywhere in the 79th column, but you only consider two possibilities: go right, or go down and then go right. What if the best way to get from matrix[0][78] to the next column is to go down 6 entries and then go right? Your code will never consider that possibility.
Your code probably works on the small example because it so happens that the minimum path only goes up or down a single time in each column. But I think that's a coincidence (also possibly a poorly chosen example).
One way to solve this problem is using the following approach. When the input is a NxN matrix, define a NxN array min_path. We're going to want to fill in min_path so that min_path[x][y] is the minimum path sum starting in any entry in the first column of the input matrix and ending at [x][y]. We fill in one column of min_path at a time, starting at the leftmost column. To compute min_path[i][j], we look at all entries in the (j-1)th column of min_path, and the cost of getting from each of those entries to (i, j). Here is some Python code showing this solution: https://gist.github.com/estark37/5216851. This is an O(N^4) solution but it can probably be made faster! (maybe by precomputing the results of the sum_to calls?)

Related

How to loop through an xarray and calculating using an index in python

I have a data variable(sst) in an xarray(nino6), first I use enumerate to assign each value of data variable of the array an index, then I want to calculate with the values of data variable using the index. This code calculates with the indizes itself instead of the data variable values, but I just wanted you to show what I tried.
How can I loop through an index but actually calculating with the values?
for i, entry in enumerate(nino6['sst']):
a=((i-1)+i+(i+1))/3
ssta.append(a)
I apologise for my question is very likely to be really simple (I just started programming), but I searched unsuccesfully here and and on youtube.
If you are trying to get the average of every 3 adjacent numbers in sst, you do it like this:
lst = nino6['sst']
ssta = []
for i in range(1,len(lst) - 1):
a = (lst[i-1] + lst[i] + lst[i+1])/3
ssta.append(a)
Notice that in this implementation, the length of ssta will be smaller than the length of sst by 2 because the first and last numbers do not have flanking numbers. You can have other variations, where you just get the average of two numbers for the first and last numbers.

How to use different columns for for loop iteration

So i want to do an iteration a vairable amount of times (a)
I have an excel sheet where that iteration is already programmed and i want to do the same now in python 3 spyder.
I decided to calculate the first row externally. The iteration should now look like this:
da,air core diameter (2,1) is has the input t_new (1,5), delta p, spray pressure (2,2) has input da,air core diameter (2,1), t_new (2,5) has the input delta p, spray pressure (2,2) and so on for a given number of iterations.
My code looks as follows up until now (everything else is defined properly beforehand):
a = [b for b in range(14)] # number of iterations -1
arr = np.array([[da_iter], [ps_iter], [t_mod_iter]]).reshape(1,3) # external calculated values first row
arr_zeros = np.zeros([len(a), 3]) # filling array with 0's based on iteration number
arr_iter = np.vstack((arr, arr_zeros)) #iteration array with 1st row calculated values
i = 0 #row index
j = 0 #column index
for i in range(len(arr_iter)):
np.append(arr_iter, do_in-2*arr_iter[i,j+2]) #calculating new da out of t_mod
np.append(arr_iter, ml**2*gs*0.5*pl*((dsc/(2*pl*(hsc*din*arr_iter[i+1,j]/2)))**2+(1/(pl*(ao-np.pi/4*arr_iter[i+1,j]**2)))**2)) #calculating new ps out of new da
np.append(arr_iter, k*(1738.7*ul**2-79.898*ul+2.0122)*((do_in*ml*ul)/(pl*arr_iter[i+1,j+1]))**0.25) #calculation new t_new out of spray pressure
i = i+1
print(arr_iter)
But that doesnt seem to work properly since i only get out arr_iter as it was before. Unfortunatley i also didnt found sth usefull how to iterate over changing rows using a for loop.
Does somebody have a better idea how to do it or sees my mistake in the loop?
Thank you very much in advance
First thing, you don't need i=i+1 as for loop already doing the same.
Secondly, I think you want to replace zeros in arr_iter so in for loop, you should write something like
np.append(arr_iter[i, j], 2nd_variable)
Alternatively you can simply do the following to update arr_iter matrix, rather than append.
arr_iter[i][j] = new_variable

Is there a more efficient an robust way to create a minimum proximity algorithm for a distance matrix?

I am trying to make an algorithm that propagates from point to point in a distance matrix using the smallest distance in the proximity. The code has two conditions: the minimum distance must be no less than 0 and each point must be visited once and return to the starting position.
This is my code in its entirety:
def totalDistance(aList):
path = []
for j in range(0,len(aList)):
k=j
order = []
for l in range(0,len(aList)):
order.append(k)
initval= min(x for x in aList[k] if x > 0 )
k = aList[k].index(initval)
for s in range(0,len(aList)):
for t in range(0,len(aList[s])):
aList[s][k] = 0
path.append(order)
return path
The code is meant to return the indexes of the points in within the closes proximity of the evaluated point.
aList = [[0,3,4,6],[3,0,7,3],[4,7,0,9],[6,3,9,0]] and represents the distance matrix.
When running the code, I get the following error:
initval= min(x for x in aList[k] if x > 0 )
ValueError: min() arg is an empty sequence
I presume that when I make the columns in my distance matrix zero with the following function:
for s in range(0,len(aList)):
for t in range(0,len(aList[s])):
aList[s][k] = 0
the min() function is unable to find a value with the given conditions. Is there a better way to format my code such that this does not occur or a better approach to this problem all together?
One technique and a pointer on the rest that you say is working...
For preventing re-visiting / backtracking. One of the common design patterns for this is to keep a separate data structure to "mark" the places you've been. Because your points are numerically indexed, you could use a list of booleans, but I think it is much easier to just keep a set of the places you've been. Something like this...
visited = set() # places already seen
# If I decide to visit point/index "3"...
visited.add(3)
Not really a great practice to modify your input data as you are doing, and especially so if you are looping over it, which you are...leads to headaches.
So then... Your current error is occurring because when you screen the rows for x>0 you eventually get an empty list because you are changing values and then min() chokes. So part of above can fix that, and you don't need to zero-ize, just mark them.
Then, the obvious question...how to use the marks? You can just use it as a part of your search. And it can work well with the enumerate command which can return index values and the value by enumeration.
Try something like this, which will make a list of "eligible" tuples with the distance and index location.
pts_to_consider = [(dist, idx) for idx, dist in enumerate(aList[k])
if dist > 0
and idx not in visited]
There are other ways to do this with numpy and other things, but this is a reasonable approach and close to what you have in code now. Comment back if stuck. I don't want to give away the whole farm because this is probably H/W. Perhaps you can use some of the hints here.

for loop iteration-population conflict

I am new in python and I am trying to learn it by myself. I am currently working on a code, which gives me index error because somehow for loop does not populate my data. I am supposed to iterate a value and with it, I depend on the previous value to produce the new value. Normally this was easy with matlab, only with x(:,k) but python does not work the same way and I will really be grateful for any help that does not judge my level of knowledge in python. Here how it goes:
x = np.matrix([[1.2],[.2]]) # prior knowledge
A = np.matrix([[1, 1], [0, 1]])
B = np.matrix([[.5], [1]])
U = -9
t1 = range(1,100,1)
for k, val in enumerate(t1):
x[:,k] = A*x[:,k-1] + B*U
To my understanding, the error 'IndexError: index 1 is out of bounds for axis 1 with size 1' pops up because the for loop does not populate the data 'x' and therefore, there is no value for neither 'k-1' nor 'k'.
What I should do is to iterate and store 'x' values and pick the relevant previous value each time to obtain new value with given equation till the end of loop. As you can see, I have a column matrix and I should have a column matrix each time. I hope I could make myself clear.
Thank you
The first line is the initial value of x, the second, third, fourth and fifth lines are the values that are used in for loop to calculate iterations for x.
What I am trying to implement is code for kaman filter in general. In this system, the current value x(k) is calculated with previous value x(k-1) with given equation x(k) = Ax(k-1) + BU. Each x(k) value becomes x(k-1) in next iteration until loop is executed. Here, I am expecting to have (2,k) matrix after every loop because record of values are essential for other calculations. And to use the previous value in current value, I need to access to (k-1)th value.
The question was solved by juanpa.arrivillaga (https://stackoverflow.com/users/5014455/juanpa-arrivillaga) Thank you.

Compute mean of last X elements of a list in Python2.7

Is there an elegant way or function to compute the mean of the last X elements of a list?
I have a list register that increases in size at each iterations :
register = np.append(register, value)
I want to create another list in which an i element corresponds to the mean of the X last elements in register
register_mean[i] = np.mean(register[i-X:i])
The tricky part is for the first X iterations, when there isn't X values yet in register. For these specific cases, I would like it to compute the mean on the firsts values of register, and only take the first value of register as first value of register_mean.
This could be done during the iterations or after, when register is complete.
I know there is lots of similar questions but haven't found one that answered this particular problem
Could it be something as simple as
if X < i:
register_mean[i] = np.mean(register[:i])
This just averages however many prior points there are until you have enough to average X points
Perhaps I misinterpreted your intent!
If I understand your question correctly, this should do the work:
X = 4 # Span of mean
register_mean = [np.mean(register[max(i-X, 0): max(i-X, 0) + 1]) for i in range(len(register))]
It will essentially create a moving average of the register elements between i - X and i; however, whenever i - X is negative, it will only take the values between 0 and i + 1.

Categories

Resources