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.
Related
coding challenge screenshot
This is from Facebook/Meta Careers page practice problems
here is my current solution so far 2/32 test cases passed, has anyone been able to get 32/32?
from typing import List
# Write any import statements here
def getMinCodeEntryTime(N: int, M: int, C: List[int]) -> int:
# Write your code here
dial_1 = 1
dial_2 = 1
count = 0
code = C
if len(code) > 0:
for number in code:
print("before: dial_1, dial_2: ", dial_1, dial_2)
fwd_1 = abs(number - dial_1)
rev_1 = N - abs(number - dial_1)
fwd_2 = abs(number - dial_2)
rev_2 = N - abs(number - dial_2)
# Dial 1 calc: fwd vs rev
if fwd_1 > rev_1:
count_1 = rev_1
else:
count_1 = fwd_1
# Dial 2 calc: fwd vs rev
if fwd_2 > rev_2:
count_2 = rev_2
else:
count_2 = fwd_2
# Dial 1 vs Dial 2 movement decision
if count_1 > count_2:
dial_2 = number
count += count_2
else:
dial_1 = number
count += count_1
print("after: dial_1, dial_2: ", dial_1, dial_2, "+/-", count)
return count
Your algorithm is greedy. You always move the closest deal to the next number. Sometimes, you have to make a suboptimal move to get the best overall answer. (There are times greedy algorithms are optimal, but not here.)
Try writing a recursive function:best(n, other) gives you the number of moves to solve steps numbers Cn+1 to the end, assuming the two dials are at Cn and other. This will be a nice recursive function. Now rewrite the recursion in terms of dynamic programming.
Please don't expect anyone to write the code for you.
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'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.
I am currently passing the sample tests and 2 of the other 10 cases so 4 out of 12. However, I don't make it through all of the data. I am getting a Terminated due to timeout error which means that my solution isn't fast enough.
def stockmax(prices):
total = 0
for index, price in enumerate(prices):
if index < len(prices) - 1:
section = max(prices[index+1:])
if prices[index] < section:
total += section - prices[index]
return total
I tried to do everything in only one loop. But how exactly can speed this type of question up. I also tried to cut some lines of the code but it is equally as inefficient.
def stockmax(prices):
total = 0
for index, price in enumerate(prices):
if index < len(prices) - 1 and prices[index] < max(prices[index+1:]):
total += max(prices[index+1:]) - prices[index]
return total
Though it passes the same amount of test cases.
I also tried to use heapq but it passes the same test cases and fails due to time.
def stockmax(prices):
total = 0
for index, price in enumerate(prices):
if index < len(prices) - 1:
section = heapq.nlargest(1,prices[index+1:])[0]
if prices[index] < section:
total += section - prices[index]
return total
https://www.hackerrank.com/challenges/stockmax/topics/dynamic-programming-basics
for details on the problem.
https://hr-testcases-us-east-1.s3.amazonaws.com/330/input09.txt?AWSAccessKeyId=AKIAJ4WZFDFQTZRGO3QA&Expires=1538902058&Signature=3%2FnfZzPO8XKRNyGG0Yu9qJIptgk%3D&response-content-type=text%2Fplain
for a link of some test cases but will expire after a while.
Problem
Your algorithms have become so good at predicting the market that you now know what the share price of Wooden Orange Toothpicks Inc. (WOT) will be for the next number of days.
Each day, you can either buy one share of WOT, sell any number of shares of WOT that you own, or not make any transaction at all. What is the maximum profit you can obtain with an optimum trading strategy?
For example, if you know that prices for the next two days are prices = [1,2], you should buy one share day one, and sell it day two for a profit of 1. If they are instead prices = [2,1], no profit can be made so you don't buy or sell stock those days.
Function Description
Complete the stockmax function in the editor below. It must return an integer that represents the maximum profit achievable.
stockmax has the following parameter(s):
prices: an array of integers that represent predicted daily stock prices
Input Format
The first line contains the number of test cases t.
Each of the next t pairs of lines contain:
The first line contains an integer n, the number of predicted prices for WOT.
The next line contains n space-separated integers prices [i], each a predicted stock price for day i.
Constraints
1 <= t <= 10
1 <= n <= 50000
1 <= prices [i] <= 100000
Output Format
Output lines, each containing the maximum profit which can be obtained for the corresponding test case.
Sample Input
3
3
5 3 2
3
1 2 100
4
1 3 1 2
Sample Output
0
197
3
Explanation
For the first case, you cannot obtain any profit because the share price never rises.
For the second case, you can buy one share on the first two days and sell both of them on the third day.
For the third case, you can buy one share on day 1, sell one on day 2, buy one share on day 3, and sell one share on day 4.
Clearly, for any price we can buy, we would want to sell it at the highest price. Fortunately, we are given that highest price. So, iterating backwards, we know the highest future price seen at any point we visit in our travel "back in time."
Python code:
def stockmax(prices):
n = len(prices)
highest = prices[n - 1]
m = [0] * n
# Travel back in time,
# deciding whether to buy or not
for i in xrange(n - 2, -1, -1):
# The most profit buying stock at this point
# is what we may have made the next day
# (which is stored in m[i + 1])
# and what we could make if we bought today
m[i] = m[i + 1] + max(
# buy
highest - prices[i],
# don't buy
0
)
# Update the highest "future price"
highest = max(highest, prices[i])
return m[0]
If you can use Numpy, then something similar to the below should be rather quick (I believe it's the same idea as the answer from #גלעד ברקן).
import numpy as np
with open('.../input09.txt') as fd:
numtests = int(fd.readline().strip())
counter = 0
numvals = 0
vals = None
steps = None
for line in fd:
if (counter % 2 == 0) :
numvals = int(line.strip())
else:
vals = np.fromstring(line, dtype=int, sep=' ', count=numvals)
assert len(vals) == numvals
cum_max = np.maximum.accumulate(vals[::-1])
np.roll(cum_max, -1)
cum_max[len(cum_max) - 1] = 0
delta = (cum_max - vals)
print('#', counter + 1, 'sum:', np.sum(delta * (delta > 0)))
counter += 1
it runs almost instantly on tests from the input09.txt.
Here is my solution written in ruby.
The solution obtained perfect score.
def solution(a)
gain = 0
i = a.count - 1
min = false
mi = false
while i > 0
s = a.delete_at(i)
unless min
mi = a.index(a.min)
min = a[mi]
end
g = s - min
gain = g if g > gain
i -= 1
min = false if i == mi
end
gain
end
The problem:
There are 3 paths where only one leads home.
The first path gets you lost for 3 days, then you're back to the beginning where you have to pick another path.
The second path gets you lost for 2 days, then you're back at the beginning and you have to pick another path.
The last door leads you home in 1 day.
Basically you keep going until you pick the last path. I'm trying to find the average time it takes to get home by simulating 1000 tries.
Here is what I have thus far:
days=0
for i in range(1000):
door=["a","b","c"]
numpy.random.choice(path)
if numpy.random.choice(path)=="a":
days=+2
if numpy.random.choice(path)=="b":
days=+3
if numpy.random.choice(path)=="c":
days=+1
print(steps)
As is, my code will just print out a value from 1-3 as the days.
I'm having trouble figuring out how to pick one and then accumulate it into the days and then restarting the loop until it picks path C.
I've done research and think a while loop might work but I don't know how to apply that.
You can use a while loop that keeps iterating while you are stuck and then when door 'a' is selected it adds the 1 to get home but then the person is no longer stuck so it drops out of the while loop. Then before entering the while loop again, just set stuck = True and the process continues always adding to the total number of days, then at the end just take the average.
import numpy
days=0
door=["a","b","c"]
N = 1000
for i in range(N):
stuck = True
while stuck:
if numpy.random.choice(door)=="a":
days += 2
if numpy.random.choice(door)=="b":
days += 3
if numpy.random.choice(door)=="c":
days += 1
stuck = False
print('Average number of days taken to get home: ', days / N)
I hope this helps!
Here's the code you're looking for:
import numpy
def runOnce():
days = 0
door=["a","b","c"]
while(True):
path = numpy.random.choice(door)
if path=="a":
days+=2
if path=="b":
days+=3
if path=="c":
days+=1
return days
total = 0
for i in range(1000):
total += runOnce()
print(total / 1000.0)
This code must solve your problem:
import random
doors = ['a', 'b', 'c']
total_days = 0
runs = 1000
for i in range(runs):
days = 0
choice = None
while choice != 'c':
choice = random.choice(doors)
if choice == 'a':
days += 2
if choice == 'b':
days += 3
if choice == 'c':
days += 1
total_days += days
avg_days = total_days / runs
print(avg_days)
I'm not quite sure on your rules, but this is my attempt
import numpy as np
def choose_path():
p =np.random.randint(3)
#print("Path = {}".format(p))
return p
N = 100000
days=0.0
for i in range(N):
#make sure you don't take the wrong path twice
taken = [False, False, False]
path = choose_path()
while(path != 2):
if(path==0):
if(not(taken[path])):
taken[path] = True
days += 2.0
if(path==1):
if(not(taken[path])):
taken[path] = True
days += 3.0
path = choose_path()
days += 1.0
# print("Days = {}".format(days))
print("Average for {} iterations = {}".format(N, days/N))
In contrast to the some of the other codes my guy doesn't take the same route twice. I'm not sure how you problem is defined. My solution seems to be 3.5.
Some of the mistakes you made are:
=+ is an assignment of a positive number a = +3 or a = -3
+= is an increment a = a + 3 <=> a += 3
you define door, but never use it
you never define steps but you use it
I think you should come up with an algorithm first and then implement it.
There are a few problems with your code. For example, you define a door list of possible choices, but then you pass path to the choice function. At the end of your program you print steps, but that's not defined anywhere. Instead, you should be printing days, or days / 1000. You need to pay attention to things like that when you're programming!
As others have shown, you need to do this with two loops. Each iteration of the outer loop performs a trial. The inner loop chooses paths until you get home and adds the day counts to the current total.
In your code, each if test generates a fresh random choice on top of the one you make at the start of the loop. That's not right. Just make the choice at the top of the loop, determine how many days to add to the count, and if you're home, break out of the loop.
We can do this in a simpler way. Rather than choosing from 'a', 'b', or 'c', just choose from 1, 2, or 3, the number of days each path takes. And as I said earlier, there's no need to use Numpy for this, we can just call the random module functions directly instead of letting Numpy do it on our behalf.
Here's a short demo.
from random import randint
trials = 10000
days = 0
for n in range(trials):
while True:
path = randint(1, 3)
days += path
if path == 1:
break
print(days, days / trials)
typical output
59996 5.9996
We can get a more accurate estimate to the true expected time by performing multiple runs and averaging the results. We could do that by wrapping the previous code in an extra loop, but it makes the code more readable if instead we wrap the old code in a function, and call that function in a loop. Like this:
from random import randint
def sim(trials):
days = 0
for n in range(trials):
while True:
path = randint(1, 3)
days += path
if path == 1:
break
return days
num = 10
trials = 10000
total = 0
for i in range(num):
days = sim(trials)
x = days / trials
print(i, x)
total += x
print('Final', total / num)
typical output
0 5.9732
1 6.007
2 6.0555
3 5.9943
4 5.9964
5 5.9514
6 6.0689
7 6.0457
8 5.9859
9 5.9685
Final 6.00468
It looks like the true expected value is 6 days. Actually, it's not hard to show that mathematically.
Let d equal the expected number of days to get home. 1/3 of the time we get home in 1 day, 1/3 of the time we get back to the start in 2 days and so we still have d days before we get home, and 1/3 of the time we get back to the start in 3 days and so, once again we still have d days before we get home.
We can put that into an equation:
d = (1/3)*1 + (1/3)*(2 + d) + (1/3)*(3 + d)
3*d = 1 + 2 + d + 3 + d
3*d = 6 + 2*d
d = 6