I'm trying to use a greedy algorithm to solve the problem of refueling a car minimum number of times on a road trip. Unfortunately my code so far has exceeded the time limit in place for this problem.
I wanted to ask if the problem is coming from my nested while loop, because this seems to be the process that iterates the highest number of times. Here is the code:
def compute_min_refills(distance, tank, stations):
trip = distance
dist_traveled = 0
tank_capacity = tank
refills = 0 ##keeps track of total refills
stations = stations
stations.append(trip)
if tank > trip:
return 0
elif station[-1] - station[-2] > tank:
return -1
else:
dist_traveled = tank
while dist_traveled < trip:
n = 0
while stations[n] <= dist_traveled:
n+=1
if dist_traveled - stations[n-1] <= tank:
refills+=1
else:
return -1
dist_traveled = stations[n-1] + tank
stations = stations[n-1:]
return y
The constraints are as follows:
1 < distance < 10^5
1 < tank < 400
stations is an array containing at most 300 elements.
This is my first time dealing with problems of runtime so any advice even in how to approach the problem would be greatly appreciated.
You have several mistakes. First, you seem to assume that station is sorted, but I don't see where it's guaranteed. Even if it is, your append of append(trip) may break it.
elif station[-1] - station[-2] > tank:
return -1
station[-1] and station[-2] may not matter, because they can be outside trip range. Moreover, they may not even exist.
while stations[n] <= dist_traveled:
n+=1
Possible arrayIndexOutOfBounds.
if dist_traveled - stations[n-1] <= tank:
Same issue.
n = 0
...
stations = stations[n-1:]
Better to just set n = 0 outside outer while loop (and reuse n throughout different iterations).
if dist_traveled - stations[n-1] <= tank
Probably the cause of TL. This condition is satisfied when dist_traveled = stations[n-1] + tank; after that you will assign dist_traveled to the exactly same value as it was before. Test: you have stations at coordinates 0 and tank + 1.
Related
I'm a beginner with Python. I have a 2-d array called infected that stores values that correspond with the index. This bit of code is messy, but basically what I'm trying to do is simulate an infectious disease spreading over a number of days (T). The individual is infectious for infTime many days and then goes into recovery where they are immune for immTime days. There's also a probability value for whether a node will be infected and a value for how many nodes they will be connected to.
My problem is that I'm also trying to track the number of individuals currently susceptible, infected, or immune, but something is going wrong in the elif statement that is marked "# Messing up in this loop". Currently, the program is running through the statement more times than it should, which is throwing off the variables. If I switch the conditions in the elif statement, the program doesn't go through it and will stay at a very low number of infected individuals the entire time. I'm really stuck and I can't find any reason why it's not working how I want it to.
Code:
# Loop through T days, checking for infected individuals and connecting them to beta num of nodes, possibly infecting
infTime = 5 # Time spent infected before becoming immune
immTime = 20 # Time spent immune before becoming susceptible again
numSus = N - count
day = 0
while day < T:
for a in range(len(infected)):
nextnode = random.randint(0, N-1)
if((infected[a][0] == 1) and (infected[a][3] < infTime)):
num = infected[a][1]
for b in range(num-1):
if((a != nextnode) and (infected[nextnode][0] == 0)):
infected[a][3] += 1
chance = round((random.uniform(0, 1)), 2)
if(infected[nextnode][2] > chance):
infected[nextnode][0] = 1
G.add_edge(a, nextnode)
count += 1
numInf += 1
numSus -= 1
elif((a != nextnode) and (infected[nextnode][0] == 1)):
G.add_edge(a, nextnode)
elif((infected[a][0] == 1) and (infected[a][3] == infTime)): # Messing up in this loop
infected[a][3] = 0
infected[a][4] = 1
numImm += 1
numInf -= 1
G.add_edge(a, nextnode)
elif((infected[a][0] == 0) and (1 < infected[a][4] < immTime)):
infected[a][4] += 1
elif((infected[a][0] == 0) and (infected[a][4] == immTime)):
infected[a][4] = 0
numImm -= 1
numSus =+ 1
day += 1
print("Number of infected on day ", day, ": ", count)
I came across the LeetCode problem 2100. Find Good Days to Rob the Bank:
You and a gang of thieves are planning on robbing a bank. You are given a 0-indexed integer array security, where security[i] is the number of guards on duty on the ith day. The days are numbered starting from 0. You are also given an integer time.
The ith day is a good day to rob the bank if:
There are at least time days before and after the ith day,
The number of guards at the bank for the time days before i are non-increasing, and
The number of guards at the bank for the time days after i are non-decreasing.
More formally, this means day i is a good day to rob the bank if and only if security[i - time] >= security[i - time + 1] >= ... >= security[i] <= ... <= security[i + time - 1] <= security[i + time].
Return a list of all days (0-indexed) that are good days to rob the bank. The order that the days are returned in does not matter.
The solution, that I created seems fine to me. Not sure, where I am going wrong with some test cases failing.
class Solution(object):
def goodDaysToRobBank(self, security, time):
"""
:type security: List[int]
:type time: int
:rtype: List[int]
"""
total_guards = len(security)
if time == 0:
return [i for i in range(total_guards)]
left = [1]*total_guards
right = [1]*total_guards
l_pattern_found = False
r_pattern_found = False
for i in range(1, total_guards):
if security[i-1] >= security[i]:
left[i] = left[i-1] + 1
l_pattern_found = True
for i in range(total_guards-2, -1, -1):
if security[i+1] >= security[i]:
right[i] = right[i+1] + 1
r_pattern_found = True
if not l_pattern_found or not r_pattern_found:
return []
days = []
for i in range(time, total_guards-time):
if left[i-1] >= time and right[i+1] >= time:
days.append(i)
return days
Here is what I have done:
Compute the left prefix for the condition mentioned
Compute the right prefix for the condition mentioned
Find the days in the range [time, n-time]
This is failing for the test case as follows:
security = [1,2,5,4,1,0,2,4,5,3,1,2,4,3,2,4,8]
time = 2
The expected output is: [5,10,14] and my output is [4,5,6,10,14]
What is it that I am doing wrong?
The main issue is in this line:
if left[i-1] >= time and right[i+1] >= time:
Here the value of left[i-1] does not guarantee that the current value at security[i] is not greater than security[i-1]. To ensure that, you would need to look at left[i] instead of left[i-1]. For the same reason you should be looking at right[i] instead of right[i+1]. But that means you need to reduce all counts by 1, and initialise your left and right lists with zeroes:
left = [0]*total_guards
right = [0]*total_guards
With those corrections it will work.
I'm a python newbie and currently learning on basics with it. I've come across this task and I would really love to solve it so I can understand how to do similar things in the future. Here is how it goes : Write a function for checking the speed of drivers. This function should have one parameter: speed.
If speed is less than 70, it should print “Ok”.
Otherwise, for every 5km above the speed limit (70), it should give the driver one demerit point and print the total number of demerit points. For example, if the speed is 80, it should print: “Points: 2”.
If the driver gets more than 12 points, the function should print: “License suspended”
This is what I came up with currently, but can't solve bolded part of text. Would appreciate it if you could help me. Thanks !
def speed_check(speed):
warning_point = 0
max_speed = 70
if (speed <= max_speed):
print ("OK")
elif (speed >=130):
print ("Licence suspended, you total warning points is 12.")
elif ("something must go here"):
warning_point +=1
print("Current warning point is {0}".format(warning_point))
speed_check(75)
A global variable will be needed to keep track of how many warning points have been awarded. Below should do it, comment if it makes sense or if there are parts you want explaining.
def speed_check(speed):
global warning_point
max_speed = 70
if speed <= max_speed:
print ("OK")
else:
warning_point += (speed-max_speed) // 5
print("Current warning point is {0}".format(warning_point))
if warning_point >= 12:
print("Licence suspended, you total warning points is at least 12.")
warning_point = 0
speed_check(75)
speed_check(85)
speed_check(115)
You can subtract the speed limit, divide by 5 and then add 1 offset because 1 / 5 = 0
import math
def speed_check(current_speed):
max_speed = 70
if current_speed <= max_speed:
print("OK")
elif (current_speed >=130):
print ("Licence suspended, you total warning points is 12.")
else:
points = math.floor((current_speed - max_speed) / 5) + 1
print("Current warning point is {0}".format(points))
You could divide the speedlimit, 70, and the current speed, 80, by the amount per each point. Then you could just subtract those to get points.
import math
def speed_check(current_speed):
max_speed = 70
if current_speed <= max_speed:
print("OK")
elif (current_speed >=130):
print ("Licence suspended, you total warning points is 12.")
else:
points = (current_speed - max_speed) // 5
print(f"Points: {int(points)}")
PYTHON 3: Hi, so I have this piece of code
for money in range(0, 2501, 500):
print("{} Euro".format(money), end='')
throws = 0
d = trump.possession(board)
while False in d.values():
prevLoc = piece.location
piece.move(trump.throw())
throws += 1
if piece.location < prevLoc:
money += 200
if board.names[piece.location] in d and d[board.names[piece.location]] == False and money >= board.values[piece.location]:
money -= board.values[piece.location]
d[board.names[piece.location]] = True
return throws
and this code takes 0 money to start with, runs the code, looks for amount of throws required to buy the entire board, does the same with 500 starting money, 1000 and so forth
my question is, how can i take the average of the throws to buy the entire board for each starting value? the way my code is now it returns the amount of throws for all the starting values, but simulated once, so it may not be accurate.
I searched a lot, and tried some things but i had problems with this one because I want to like run it, say for example, 2000 times, and get the average for each starting value for the money.
anyone got any tips for this? been struggling on it for a while..
i tried making a for loop from 0 to 2000 and then inside of that another for loop that prints 0-2500 and then uses the code below in a function, appends the return value of throws into a list and sums it up and devides it by 2000, it did not turn out so good...
I'm going to assume this is in a function, due to the return statement. You need to collect outputs into a list and then average that at the end.
def calc_throws(simulations):
throw_list = []
average = lambda x: sum(x)/len(x)
for i, money in enumerate(range(0, 2501, 500)):
print("{} Euro".format(money), end='')
throw_list.append([money, []])
for _ in range(simulations):
throws = 0
d = trump.possession(board)
while False in d.values():
prevLoc = piece.location
piece.move(trump.throw())
throws += 1
if piece.location < prevLoc:
money += 200
if board.names[piece.location] in d and d[board.names[piece.location]] == False and money >= board.values[piece.location]:
money -= board.values[piece.location]
d[board.names[piece.location]] = True
throw_list[i][1].append(throws)
throw_list[i][1] = average(throw_list[i][1])
return throw_list
Rather than a single number, this returns a list of lists like #[[0,20],[500,15],...[2500,3]] (or whatever reasonable numbers are) which gives you the average for each amount of starting money.
start = time.time()
import csv
f = open('Speed_Test.csv','r+')
coordReader = csv.reader(f, delimiter = ',')
count = -1
successful_trip = 0
trips = 0
for line in coordReader:
successful_single = 0
count += 1
R = interval*0.30
if count == 0:
continue
if 26 < float(line[0]) < 48.7537144 and 26 < float(line[2]) < 48.7537144 and -124.6521017 < float(line[1]) < -68 and -124.6521017 < float(line[3]) < -68:
y2,x2,y1,x1 = convertCoordinates(float(line[0]),float(line[1]),float(line[2]),float(line[3]))
coords_line,interval = main(y1,x1,y2,x2)
for item in coords_line:
loop_count = 0
r = 0
min_dist = 10000
for i in range(len(df)):
dist = math.sqrt((item[1]-df.iloc[i,0])**2 + (item[0]-df.iloc[i,1])**2)
if dist < R:
loop_count += 1
if dist < min_dist:
min_dist = dist
r = i
if loop_count != 0:
successful_single += 1
df.iloc[r,2] += 1
trips += 1
if successful_single == (len(coords_line)):
successful_trip += 1
end = time.time()
print('Percent Successful:',successful_trip/trips)
print((end - start))
I have this code and explaining it would be extremely time consuming but it doesn't run as fast as I need it to in order to be able to compute as much as I'd like. Is there anything anyone sees off the bat that I could do to speed the process up? Any suggestions would be greatly appreciated.
In essence it reads in 2 lat and long coordinates and changes them to a cartesian coordinate and then goes through every coordinate along the path from on origin coordinate to the destination coordinate in certain interval lengths depending on distance. As it is doing this though there is a data frame (df) with 300+ coordinate locations that it checks against each one of the trips intervals and sees if one is within radius R and then stores the shortest on.
Take advantage of any opportunity to break out of a for loop once the result is known. For example, at the end of the for line loop you check to see if successful_single == len(coords_line). But that will happen any time the statement if loop_count != 0 is False, because at that point successful_single will not get incremented; you know that its value will never reach len(coords_line). So you could break out of the for item loop right there - you already know it's not a "successful_trip." There may be other situations like this.
have you considered pooling and running these calculations in parallel ?
https://docs.python.org/2/library/multiprocessing.html
Your code also suggests the variable R,interval might create a dependency and requires a linear solution