python access array errors - python

im working on a an assignment but the few lines keeps on giving me errors that i cannot understand
pick=0
final=0
while True:
if (min_weight>0):
if (sort_ratio[pick]["Weight"]<min_weight):
final = final + sort_ratio[pick]["Cost"]
min_weight = min_weight - sort_ratio[pick]["Weight"]
if (sort_ratio[pick]["Weight"]>min_weight):
pick = pick + 1
if (min_weight == 0):
print (final)
return
the only problem is when the program pass "pick = pick+ 1" it stops and gives "index out of range" error.
Instead of using the increment method i tried to edit the array instead using
sort_ratio.remove(sort_ratio[0]);
but it gives me "cannot interpreted as integer problem"
present code
from operator import itemgetter
import math
raw_input=input;
test_case = int(raw_input());
for inp1 in range (test_case):
min_weight = int(raw_input());
candy_types = int(raw_input());
candy = [];
for inp2 in range (candy_types):
can_weight,can_cost = map(int,raw_input().split());
ratio_candy = (can_cost / int(can_weight));
candy.extend([{"Cost": can_cost, "Ratio": ratio_candy, "Weight": can_weight}]);
sort_ratio = sorted ( candy, key=itemgetter('Ratio'));
pick = 0;
final = 0;
while True:
if (min_weight>0):
if (sort_ratio[pick]["Weight"]<min_weight):
final = final + sort_ratio[pick]["Cost"]
min_weight = min_weight - sort_ratio[pick]["Weight"]
print (final)
print (min_weight)
if (sort_ratio[pick]["Weight"]>min_weight):
pick = pick + 1
if (min_weight==0):
print (final)
break

Related

How to repeat the steps

In my program I have total of 3 steps.
To find the mean
Split the given list using the mean value
If the threshold value > epsilon then update mean value and repeat the step 2 again with updated mean value, else finished.
I have achieved above two steps anyhow. Third step I have achieved only half and struggling in how to repeat the step 2 till the threshold value will be less than epsilon.
My code is below:
import numpy as np
store_list = [1,2,3,1,2,3,1]
# Step 1
mean_value = np.mean(store_list)
print("Mean Value : " + str(mean_value))
# Step 2
small_list = [i for i in store_list if i <= mean_value]
big_list = [i for i in store_list if i > mean_value]
print(small_list)
print(big_list)
toe_1 = np.mean(small_list)
toe_2 = np.mean(big_list)
print("toe value 1 : " + str(toe_1))
print("toe value 2 : " + str(toe_2))
toe_sum = np.sum([toe_1, toe_2])
toe_cap = np.divide(toe_sum, 2)
print("toe cap : " + str(toe_cap))
# Step 3
new_threshold = np.subtract(mean_value, toe_cap)
print(new_threshold)
epsilon_value = 0.1
if new_threshold > epsilon_value:
mean_value = toe_cap
print("new mean : " + str(mean_value))
My output of above is:
Mean Value : 1.8571428571428572
[1, 1, 1]
[2, 3, 2, 3]
toe value 1 : 1.0
toe value 2 : 2.5
toe cap : 1.75
new threshold : 0.1071428571428572
new mean : 1.75
In this case I have to repeat the step 2 again considering new mean. I am new to Python.
I'm not able to numpy but i can imagine that all you need is a recursive runner function, i don't want to break the structure of your code, therefore i did not try to optimize the code. You can try the following code, i tried, it works:
import numpy as np
def step2(store_list, mean_value):
small_list = [i for i in store_list if i <= mean_value]
big_list = [i for i in store_list if i > mean_value]
toe_1 = np.mean(small_list)
toe_2 = np.mean(big_list)
toe_sum = np.sum([toe_1, toe_2])
toe_cap = np.divide(toe_sum, 2)
return small_list, big_list, toe_1, toe_2, toe_cap
def step3(mean_value, toe_cap):
new_threshold = np.subtract(mean_value, toe_cap)
print(new_threshold)
epsilon_value = 0.1
if new_threshold > epsilon_value:
return True, toe_cap
else:
return False, mean_value
def my_run(store_list, mean_value):
small_list, big_list, toe_1, toe_2, toe_cap = step2(store_list, mean_value)
print(small_list)
print(big_list)
print("toe value 1 : " + str(toe_1))
print("toe value 2 : " + str(toe_2))
print("toe cap : " + str(toe_cap))
condition, mean_value = step3(mean_value, toe_cap)
if condition:
print("new mean : " + str(mean_value))
my_run(store_list, mean_value)
def main():
store_list = [1, 2, 3, 1, 2, 3, 1]
mean_value = np.mean(store_list)
print("Mean Value : " + str(mean_value))
my_run(store_list, mean_value)
if __name__ == '__main__':
main()
There are 2 types of loops in python. for loops and while loops. You can achieve a "loop" by doing recursion which is just calling a function inside the same function, having a correct exit statement, like this:
def print_10_times(num, count=0):
if count < 10:
print(num)
count += 1
print_10_times(num, count)
print_10_times(5) # will print '5' 10 times
Although there are easier ways to do loops in python. The easiest loop to do when you know how many loops you will need to do beforehand, is the for loop. The above example could be executed like this:
def print_10_times(num):
for i in range(10):
print(num)
print_10_times(5) # will print '5' 10 times
The other loop you can do is the while loop. To use it you will have to have a correct exit statement in the beggining of it. If you wanted to execute the above example with a while loop it would have to look something like this:
def print_10_times(num):
i = 0
while i < 10:
print(num)
print_10_times(5) # will print '5' 10 times
For you code to work you will need to have an exit statement for every loop you'd want to use. For example maybe you wanted those 3 steps to run 2 times. You could do this:
import numpy as np
store_list = [1,2,3,1,2,3,1]
for i in range(2):
# Step 1
mean_value = np.mean(store_list)
print("Mean Value : " + str(mean_value))
# Step 2
small_list = [i for i in store_list if i <= mean_value]
big_list = [i for i in store_list if i > mean_value]
print(small_list)
print(big_list)
toe_1 = np.mean(small_list)
toe_2 = np.mean(big_list)
print("toe value 1 : " + str(toe_1))
print("toe value 2 : " + str(toe_2))
toe_sum = np.sum([toe_1, toe_2])
toe_cap = np.divide(toe_sum, 2)
print("toe cap : " + str(toe_cap))
# Step 3
new_threshold = np.subtract(mean_value, toe_cap)
print(new_threshold)
epsilon_value = 0.1
if new_threshold > epsilon_value:
mean_value = toe_cap
print("new mean : " + str(mean_value))
But this will output the same thing 2 times.
I have achieved above two steps anyhow. Third step I have achieved only half and struggling in how to repeat the step 2 till the threshold value will be less than epsilon.
You can do this with a simple while loop:
import numpy as np
store_list = [1,2,3,1,2,3,1]
# Step 1
mean_value = np.mean(store_list)
print("Mean Value : " + str(mean_value))
# Step 2
toe_cap = 3
e = np.exp(1)
while toe_cap > e:
small_list = [i for i in store_list if i <= mean_value]
big_list = [i for i in store_list if i > mean_value]
print(small_list)
print(big_list)
toe_1 = np.mean(small_list)
toe_2 = np.mean(big_list)
print("toe value 1 : " + str(toe_1))
print("toe value 2 : " + str(toe_2))
toe_sum = np.sum([toe_1, toe_2])
toe_cap = np.divide(toe_sum, 2)
print("toe cap : " + str(toe_cap))
# Step 3
new_threshold = np.subtract(mean_value, toe_cap)
print(new_threshold)
epsilon_value = 0.1
if new_threshold > epsilon_value:
mean_value = toe_cap
print("new mean : " + str(mean_value))
This loop will end when toe_cap is smaller than e (Euler's number). I assigned toe_cap a value greater than e so that the loop is run at least 1 time.
There is no problem with this because the toe_cap value isn't used in any calculations and is only reassigned in the end of the loop. It's purpose here is to be used to have a correct exit statement.
If there is any possibility that the toe_cap value will never go below e, then you would have to add a different exit statement, probably according to the number of loops that you think will be enough.

Is there any way to replace (input) zeros with a function of (1/2)?

I am trying to replace the value of 0 with .5, or 1/2 when it has been input initially.
For example, I am trying to have it done before the functions are added. I need to redefine the value of 0 for the input only, and only for the single instance of 0 itself. Not values of 10+.
Here is the project information:
IN = input("Enter IN: ")
N = input("Enter N: ")
NP = input("Enter NP: ")
### These two lines are the part I can't get to work:
if digit == float(0):
digit = float(.5)
###
init = (float(IN)*(float(1)/float(2)))
baselimiter = - (float(N)*(float(1)/float(2))) + ((float(IN)*
(float(1)/float(2))) * (float(NP)*(float(1)/float(2))))
lset = init + baselimiter
limitconverto1 = (lset / init) * (init / lset)
infalatetoinput = (((init * float(IN))) / init )
limit = limitconverto1 * infalatetoinput
result = limit
print(result)
So here is a code that does what you want.
Now to be honest, it works but I don't understand WHY you do that. You do a bunch of weird calculations like multiplying and dividing by the same number...
IN = float(input("Enter IN: "))
N = float(input("Enter N: "))
NP = float(input("Enter NP: "))
# The part that interests you.
IN = 0.5 if IN == 0 else IN
N = 0.5 if N == 0 else N
NP = 0.5 if NP == 0 else NP
init = IN * 1/2
baselimiter = -N*1/2 + IN*1/2*NP*1/2 # Removed all the superfluous float() and parenthesis.
lset = init + baselimiter
limitconverto1 = (lset / init) * (init / lset) # That's just always 1. What is intended here?
infalatetoinput = (((init * float(IN))) / init ) # That's always IN. Same question?
limit = limitconverto1 * infalatetoinput # Equivalent to 1 x IN...
result = limit
print(result) # Your result is always IN...
You can use one-liners when you declare the variables:
IN = (float(input("...")) if float(input("...")) != 0 else .5)
One-liners are for loops or if statements (or both) that are in one line instead of multiple lines when declaring variables. They can only be used for the declaration of variables. The one-liner I suggested is would be in multiple lines:
if float(input("...")) != 0:
IN = float(input("..."))
else:
IN = .5 #You don't need to say float(.5) since .5 is a float anyway.
More about One-Liners: One-Liners - Python Wiki
I hope this edit of my previous answer fully answers your question, for more clarification I will be available on the comments

Traveling Salesman with GA, mutation, crossover

For school last semester, I wrote a python program to solve the traveling salesman problem. For those not familiar with what it is, the wolfram alpha explanation does a pretty good job of explaining it.
This was one of the first programs I wrote in Python, and so far I LOVE the language, coming from a C++/Java background. Anyway, I used a lot of inefficient methods/programming practices to get it working, so I wanted to go back and improve. I used a genetic algorithm with mutations and ordered crossovers. First, I create a list of random unique nodes with a given length and a given number of strategies. The GA runs through a given number of generations of these strategies, changing a random selection of strategies by using ordered crossover and an inverse mutation between two random indices. Each strategy has a given probability of a mutation and another probability of crossover. After this, the algorithm chooses two strategies at random, takes the best one, then compares it to the best solution found so far. The end goal of the program is to find the shortest distance through all the nodes.
Here is my original, inefficient, working code
Here is my newer, efficient, not working code:
import random
import math
import pprint
from matplotlib import pyplot as plt
def create_nodes(num_nodes, num_rows):
elements = range(1, num_nodes + 1)
return [random.sample(elements, num_nodes) for _ in range(num_rows)]
def mutate(table, node_table, mutate_probability, cross_probability):
for next_id, row in enumerate(table, 1):
nodes = len(row)
# print
# print "Original: ", row
#mutation
if random.random() > mutate_probability:
mini, maxi = sorted(random.sample(range(nodes),2))
row[mini:maxi+1] = row[mini:maxi+1][::-1]
# print "After mutation: ", row
# print "Between: ", mini, maxi
#crossover
if random.random() > cross_probability:
try:
next_row = table[next_id]
# print "Parent: ", next_row
except IndexError:
pass
else:
half_length = nodes//2
mini = random.randint(0, half_length)
maxi = mini + half_length - 1 + (nodes % 2)
crossed = [None] * nodes
# print "Before crossed: ", row
crossed[mini:maxi+1] = next_row[mini:maxi+1]
# print "Cross with: ", crossed
iterator = 0
for element in row:
if element in crossed:
continue
while mini <= iterator <= maxi:
iterator += 1
crossed[iterator] = element
iterator += 1
row[:] = crossed
# print "After crossed: ", row
# print "Between: ", mini, maxi
def sample_best(table, node_table):
t1, t2 = random.sample(table[1:], 2)
return distance(t1, t2, node_table)
def distance(s1, s2, node_table):
distance1 = sum_distances(s1, node_table)
distance2 = sum_distances(s2, node_table)
if distance1 < distance2:
return s1, distance1
else:
return s2, distance2
def sum_distances(strategy, node_table):
dist = 0
first_row, second_row = node_table
for idx_next_node, node1 in enumerate(strategy, 1):
try:
node2 = strategy[idx_next_node]
except IndexError:
node2 = strategy[0]
dist += math.hypot(
first_row[node2-1] - first_row[node1-1],
second_row[node2-1] - second_row[node1-1])
return dist
def draw_graph(node_table, strategy):
graphX = [node_table[0][index - 1] for index in strategy]
graphY = [node_table[1][index - 1] for index in strategy]
plt.scatter(graphX, graphY)
plt.plot(graphX, graphY)
plt.show()
def main(nodes=8, strategies=100, generations=10000, mutateP=.7, crossP=.7):
#create node locations
node_table = create_nodes(nodes, 2)
# for i in range(2):
# print node_table[i]
#create first generation
table = create_nodes(nodes, strategies)
# for i in range(strategies):
# print i
# print table[i]
print "TOP MEN are looking through:"
print strategies, "strategies in", generations, "generations with",
print nodes, "nodes in each strategy..."
best_score = None
for count in range(generations):
mutate(table, node_table, mutateP, crossP)
# crossover(table, node_table, crossP)
strategy, score = sample_best(table, node_table)
if best_score is None or score < best_score:
best_strategy = strategy
best_score = score
if count % 100 == 0:
print "Foraged", count, "berries"
print "Best we got so far:", best_score, "with: ", best_strategy
# if count % 2 == 0:
# print count
# for i in range(strategies):
# print table[i]
print "=========================================================================="
print "Best we could find: ", best_score, "for strategy", best_strategy
draw_graph(node_table, best_strategy)
main()
The new code is what I'm having trouble with. The mutation and crossover seem to be working correctly, but the algorithm isn't even coming close to finding a solution and I have no idea why. Thanks for the help in advance, I really appreciate it!

Codechef - NZEC Error in python code

The code runs fine on my machine, but when i compile it on codechef it gives a NZEC(Runtime Error).
The link to the problem : https://www.codechef.com/problems/PPTEST
About my solution: I have calculated the percentile of each test case based on their time and point values. Then I have sorted the entries in each test case based on the percentile.
import sys
def check(x):
if not(x in range(1,100)):
sys.exit(1)
T = input()
check(T)
N_W = []
C_P_T = {}
tp = []
tt = []
for i in range(0,T):
tp.append(0)
tt.append(0)
N_W.append(map(int, raw_input().split()))
check(N_W[i][0])
check(N_W[i][1])
C_P_T[i] = []
for j in range(0,N_W[i][0]):
C_P_T[i].append(map(int, raw_input().split()))
check(C_P_T[i][j][0])
check(C_P_T[i][j][1])
check(C_P_T[i][j][2])
C_P_T[i][j].append(N_W[i][1]-C_P_T[i][j][2])
C_P_T[i][j].append(C_P_T[i][j][1]*C_P_T[i][j][0])
C_P_T[i][j].pop(0)
C_P_T[i][j].pop(0)
C_P_T[i][j].pop(0)
tp[i]+= C_P_T[i][j][1]
tt[i]+=C_P_T[i][j][0]
for i in range(0,T):
C_P_T[i].sort(key = lambda x : x[0] , reverse = True)
item_time = C_P_T[i][0][0]
percentile_time = (C_P_T[i][0][0]/float(tt[i]))*((len(C_P_T[i])-1)/float(len(C_P_T[i])))
for j in range(0,N_W[i][0]):
if C_P_T[i][j][0] == item_time:
C_P_T[i][j].append(percentile_time)
else:
item_time = C_P_T[i][j][0]
percentile_time = (C_P_T[i][j][0]/float(tt[i]))*((len(C_P_T[i])-j-1)/float(len(C_P_T[i])))
C_P_T[i][j].append(percentile_time)
for i in range(0,T):
C_P_T[i].sort(key = lambda x : x[1] , reverse = True)
item_points = C_P_T[i][0][1]
percentile_points = (C_P_T[i][0][1]/float(tp[i]))*((len(C_P_T[i])-1)/float(len(C_P_T[i])))
for j in range(0,N_W[i][0]):
if C_P_T[i][j][1] == item_points:
C_P_T[i][j].append(percentile_points)
else:
item_points = C_P_T[i][j][1]
percentile_points = ((C_P_T[i][j][1])/float(tp[i]))*((len(C_P_T[i])-j-1)/float(len(C_P_T[i])))
C_P_T[i][j].append(percentile_points)
C_P_T[i][j].append(C_P_T[i][j][2]+C_P_T[i][j][3])
C_P_T[i][j].append(N_W[i][1]-C_P_T[i][j][0])
C_P_T[i][j].pop(2)
C_P_T[i][j].pop(2)
C_P_T[i].sort(key = lambda x : x[2],reverse = True)
for i in range(0,T):
points = 0
for j in range(0,N_W[i][0]):
if N_W[i][1]-C_P_T[i][j][3] >= 0:
points+=C_P_T[i][j][1]
N_W[i][1]-=C_P_T[i][j][3]
print points
NZEC means "non-zero exit code", so that is probably happening in sys.exit(1) in your check() function. What you are receiving from input() is either not an integer or not in the right range.
Update: I notice that you use range(1, 100) for validity testing.
But the problem description at codechef states that 1 ≤ T ≤ 100. That is equivalent to range(1, 101)
So, codechef could be passing your code a perfectly valid 100, and your code would reject it, probably with the exact error you are seeing.

Matlab to Python conversion - Can't assign to function call

I have recently been trying to convert a piece of Matlab code into Python code.
I have made most of the changes that I need to however, the issue I am having is the line where it says:
y(index(m)) = 1-x(index(m));
I get the error:
"Can't assign to function call"
However I am not sure how to restructure it in order to remove this error.
I have had a look around and people mention "get item" and "set item" however I have tried to use them, but I can't get them to work (probably because I can't figure out the structure)
Here is the full code:
import numpy
N = 100;
B = N+1;
M = 5e4;
burnin = M;
Niter = 20;
p = ones(B,Niter+1)/B;
hit = zeros(B,1);
for j in range(1,Niter):
x = double(rand(1,N)>0.5);
bin_x = 1+sum(x);
index = ceil(N*rand(1,M+burnin));
acceptval = rand(1,M+burnin);
for m in range(1,M+burnin):
y = x;
y(index(m)) = 1-x(index(m));
bin_y = 1+sum(y);
alpha = min(1, p(bin_x,j)/p(bin_y,j) );
if acceptval(m)<alpha:
x = y; bin_x = bin_y;
end
if m > burnin: hit(bin_x) = hit(bin_x)+1; end
end
pnew = p[:,j];
for b in range(1,B-1):
if (hit(b+1)*hit(b) == 0):
pnew(b+1) = pnew(b)*(p(b+1,j)/p(b,j));
else:
g(b,j) = hit(b+1)*hit(b) / (hit(b+1)+hit(b));
g_hat(b) = g(b,j)/sum(g(b,arange(1,j)));
pnew(b+1) = pnew(b)*(p(b+1,j)/p(b,j))+((hit(b+1)/hit(b))^g_hat(b));
end
end
p[:,j+1] = pnew/sum(pnew);
hit[:] = 0;
end
Thanks in advance
The round brackets () indicate a function. For indexing you need [] square brackets - but that is only the first of many, many errors... I am currently going through line by line, but it's taking a while.
This code at least runs... you need to figure out whether the indexing is doing what you are expecting since Python arrays are indexed from zero, and Matlab arrays start at 1. I tried to fix that in a couple of places but didn't go through line by line - that's debugging.
Some key learnings:
There is no end statement... just stop indenting
When you import a library, you need to reference it (numpy.zeros, not zeros)
Lists are indexed from zero, not one
Indexing is done with [], not ()
Creating an array of random numbers is done with [random.random() for r in xrange(N)], not random(N).
... and many other things you will find as you look through the code below.
Good luck!
import numpy
import random
N = int(100);
B = N+1;
M = 5e4;
burnin = M;
Niter = 20;
p = numpy.ones([B,Niter+1])/B;
hit = numpy.zeros([B,1]);
g = numpy.zeros([B, Niter]);
b_hat = numpy.zeros(B);
for j in range(1,Niter):
x = [float(random.randint(0,1)>0.5) for r in xrange(N)];
bin_x = 1+sum(x);
index = [random.randint(0,N-1) for r in xrange(int(M+burnin))];
#acceptval = rand(1,M+burnin);
acceptval = [random.random() for r in xrange(int(M+burnin))];
for m in range(1,int(M+burnin)):
y = x;
y[index[m]] = 1-x[index[m]];
bin_y = 1+sum(y);
alpha = min(1, p[bin_x,j]/p[bin_y,j] );
if acceptval[m]<alpha:
x = y; bin_x = bin_y;
if m > burnin:
hit[bin_x] = hit[bin_x]+1;
pnew = p[:,j];
for b in range(1,B-1):
if (hit[b+1]*hit[b] == 0):
pnew[b+1] = pnew[b]*(p[b+1,j]/p[b,j]);
else:
g[b,j] = hit[b+1]*hit[b] / [hit[b+1]+hit[b]];
g_hat[b] = g[b,j]/sum(g[b,numpy.arange(1,j)]);
pnew[b+1] = pnew[b]*(p[b+1,j]/p[b,j])+((hit[b+1]/hit[b])^g_hat[b]);
p[:,j+1] = pnew/sum(pnew);
hit[:] = 0;

Categories