Why is Poisonous plants stack solution giving TLE? - python

Trying to solve hackerrank problem.
There are plants in a garden. Each of these plants has been added with some amount of pesticide. After each day, if any plant has more pesticide than the plant at its left, being weaker than the left one, it dies. You are given the initial values of the pesticide in each plant. Print the number of days after which no plant dies, i.e. the time after which there are no plants with more pesticide content than the plant to their left.
I have used stacks to solve this problem. Example below:
a = 6 5 8 4 7 10 9
10 > 9 a = 6 5 8 4 7 10 b = 9
7 > 10 a = 6 5 8 4 7 b = 9
4 > 7 a = 6 5 8 4 b = 9
8 > 4 a = 6 5 8 b = 9 4
5 > 8 a = 6 5 b = 9 4
6 > 5 a = 6 5 b = 9 4
after this just make a new list with a = a + b.reverse(). Start the process again and exit when list is sorted in reverse order.
This still is giving me time exceeded. Any idea?
n = int(input())
first_list = input().split()
first_list = [int(i) for i in first_list]
count = 0
second_list = []
data_1, data_2 = 0, 0
while True:
b = []
if sorted(first_list, reverse=True) == first_list:
break
data_1 = first_list.pop()
for i in range(len(first_list)-1):
data_2 = first_list.pop()
if data_1 > data_2:
pass
elif data_1 < data_2:
second_list.append(data_1)
elif data_1 == data_2:
second_list.append(data_1)
second_list.append(data_2)
data_1 = data_2
if len(first_list)>=1 and data_1 < first_list[0]:
first_list.append(data_1)
second_list.reverse()
first_list = first_list + second_list
count += 1
print(count)
Edited code:
n = int(input())
input = [int(i) for i in input().split()]
count, t_length = 0, 0
cmp = input[0]
while True:
length = len(input)
for i in range(1, length):
if input[i] == -1:
t_length += 1
continue
if input[i] > cmp:
cmp = input[i]
input[i] = -1
else:
t_length += 1
cmp = input[i]
if t_length+1 == length:
break
count += 1
cmp, t_length = input[0], 0
print(count)

I agree with Woot4Moo that something doesn't look right, and I suggest you focus more on stack use (instead of doubly linked lists). See this link to the Stock Span problem which helps detail an O(N) solution for tracking differences in a list of prices. This can be extended with a condition for pesticide.
For example, it'd be filling in the gaps of:
import sys
ps = [int(s) for s in list(sys.stdin)[1].strip().split()]
stack = [ps[0]]
max_days = 0
for i in range(1, len(ps)):
days[i] = 1 if ps[i] > ps[i-1] else 0
# TODO - Logic to update days[i]
while len(stack) > 0 and ps[i] <= stack[-1][1]:
(ps_other, days_other) = stack.pop()
stack.append((ps[i], days[i])
max_days = max(max_days, days[i])
print(max_days)
I quickly implemented in O(N^2), and found 80% of tests pass (the rest timing out), so more cleverly using the stack according to the link above should do the job.
import collections
import sys
ps = [int(s) for s in list(sys.stdin)[1].strip().split()]
ps_prev = []
days = 0
while collections.Counter(ps_prev) != collections.Counter(ps):
ps_prev = ps[:]
i = len(ps) - 1
while i > 0:
if ps[i] > ps[i-1]:
ps.pop(i)
i -= 1
days += 1
print(days - 1)
Edit: note that the sketchy sys.stdin use is to cater for the HackerRank test input.

Sorting is N log N and your data structure seems wrong to me. Why would you not use a doubly linked list since the requirement is that it is the left most neighbor. You would simply dereference the pointers that died.

Related

Printing 10 values per line

I'm new to python and have a question
I want to print 10 values per line and I can't figure out how to do it. Here's my attempt at it;
a = 1
b = 15
count = 0
count_end = 10
while count < count_end:
while a < b:
count = count + 1
print(a, end = " ")
a = a + 1
if(count == count_end):
break
The output is 1 2 3 4 5 6 7 8 9 10 but I want the output to go from 1 to 10 on one line and then continue from 11 to 15 on a new line under it. I've seen some people use lists to answer a similar question but I don't want to use lists for this question.
Any help would be greatly appreciated :)
Just use one loop, and then check if count % count_end == 0 to detect every multiple of count_end.
for count, current in enumerate(range(a, b)):
print(current, end=" ")
if count % count_end == 0 or current == b-1:
print()
a = 1
b = 15
count = 0
count_end = 10
while count < count_end:
while a <= b:
count = count + 1
print(a, end = " ")
a = a + 1
if(count == count_end):
print("")
something like this ?

How to implement stack in python?

This problem may use the concept of stack in python.
My code is as follows, but it always get Time Limit Exceed (TLE) error.
I think the problem is the algorithm I design is too slow due to two loops.
I would like to know how to implement the concept of stack and use only one loop in this problem. Please instruct me and help me to revise the code, thank you so much.
Input: including one line, which contains several integers, representing the score of each time, and the numbers are separated by spaces
Output: including one line, which contains several integers, representing the interval frequency when increase happens of each score(if the score does not increase, it returns 0), and the numbers are separated by spaces
inp = [int(i) for i in input().split()]
#create a function to calculate intervals
def cal_interval(lst):
lenth = len(inp)
output_lst = []
for i in range(lenth):
#set counter
count = 1
#set iteraion number
iter_num = 0
for j in range(i+1, lenth):
iter_num += 1
if inp[j] > inp[i]:
output_lst.append(count)
break
else:
count += 1
if iter_num == (lenth-i-1):
output_lst.append(0)
break
#last number
output_lst.append(0)
#from int list transformed into str list
output_lst = [str(i) for i in output_lst]
#join by spaces
space = ' '
interval_str = space.join(output_lst)
return interval_str
print (cal_interval(inp))
there are two sets of test data as follows,
Sample Input 1: 89 56 78 9 81 7
Sample Output 1: 0 1 2 1 0 0
Sample Input 2: 76 3 60 57 11 72 73 86 27 91 56 58 21 2
Sample Output 2: 7 1 3 2 1 1 1 2 1 0 1 0 0 0
You can actually do this using slicing with some comprehensions, also next will be useful as you can supply it a default:
def get_intervals(data):
for score, *nums in (data[i:] for i in range(len(data))):
yield next((i for i, n in enumerate(nums, 1) if n > score), 0)
All I’m doing here is each iteration, score is the next number in data and nums is the rest after it. Then using next it’s grabbing the first value’s index in nums if the value is above score otherwise defaulting to 0.
So with that all you need to do in place of cal_interval is print the result of get_intervals joined:
print(' '.join(get_intervals([89, 56, 78, 9, 81, 7])))
print(' '.join(get_intervals( [76, 3, 60, 57, 11, 72, 73, 86, 27, 91, 56, 58, 21, 2])))
Results:
0 1 2 1 0 0
7 1 3 2 1 1 1 2 1 0 1 0 0 0
def stack():
while(f==1):
print("1. Push\n2. Pop\n3. Peek\n4. Traverse\n5. Quit")
print("Enter any input: ")
a = input()
if a != '':
a = int(a)
switch(a)
def switch(a):
global top
if a == 1:
print("Enter the Element To push")
b = input()
print(top)
top += 1
ar.append(b)
print(b,"item was Pushed")
elif a == 2:
poped()
print("item was Poped")
elif a == 3:
c = ar[top]
print("Peek value is:",c)
elif a == 4:
print("Traversing all items")
for i in ar:
print(i)
elif a ==5:
print("Quit")
global f
f=2
else:
print("Invalid Value")
def poped():
if top == -1:
print("Stack is Empty / Pop not performed")
else:
ar.pop()
top -= 1
# Driver Code
f = 1
top = -1
ar = []
stack()

How to make this run 'faster'? Or is that the right terminology?

I am new to python and I submitted this code for a Hackerrank problem Arrays and Simple Queries, but for a large number of test cases the program is 'terminated due to timeout'. How can I make this more efficient?
I've pasted the main swap function below.
(Repeats M times)
temp = input()
temp = temp.split(" ")
i = int(temp[1])-1
j = int(temp[2])-1
rep = (i-1)+1
if(temp[0]=='1') :
rep = (i-1)+1
while(i<=j) :
count = i-1
ex1 = count
ex2 = i
for k in range(0,rep) :
arr[ex1], arr[ex2] = arr[ex2], arr[ex1]
ex1 = ex1-1
ex2 = ex2-1
i = i+1
else :
rep = (N-(j+1))
while(j>=i) :
count = j+1
ex1 = count
ex2 = j
for k in range(0,rep) :
arr[ex1], arr[ex2] = arr[ex2], arr[ex1]
ex1 = ex1+1
ex2 = ex2+1
j=j-1
Instead of using many loops, you can try simply concatenating slices:
def query(lst, t, start, end):
# Convert to proper zero-indexed index
start -= 1
if t == '1':
return lst[start:end] + lst[:start] + lst[end:]
elif t == '2':
return lst[:start] + lst[end:] + lst[start:end]
# Get the input however you want
N, M = map(int, input().split())
arr = list(map(int, input().split()))
assert len(arr) == N
for _ in range(M):
t, start, end = input().split()
arr = query(arr, t, int(start), int(end))
print(abs(arr[0] - arr[N - 1]))
print(*arr)
Input:
8 4
1 2 3 4 5 6 7 8
1 2 4
2 3 5
1 4 7
2 1 4
Output:
1
2 3 6 5 7 8 4 1

Returning the product of numbers betweeen max and min in list, and simplify the loop

I have some array elements which were separated by a space,
for ex: -7 5 -1 3 9, 3 14 -9 4 -5 1 -12 4, -5 1 2 3 4 5 6 7 8 -3.
The task was to find the product of numbers which are located between maximum and minimum of them. And I made something to calculate it
n = "-7 5 -1 3 9"
t = [int(i) for i in n.split()] # transform to list
if t.index(max(t)) < t.index(min(t)): # loop to cut numbers which are not
for i in range(len(t)): # between our max and min numberes in list
if t.index(max(t)) > i:
t.pop(i)
for i in range(len(t)):
if t.index(min(t)) < i:
t.pop(i)
elif t.index(min(t)) < t.index(max(t)):
for i in range(len(t)):
if t.index(min(t)) > i:
t.pop(i)
for i in range(len(t)):
if t.index(max(t)) < i:
t.pop(i)
t.pop(t.index(min(t)))
t.pop(t.index(max(t)))
def product(list): # fuction to return product of a list
p = 1
for i in list:
p *= i
return p
print(product(t)) # and print it
It looks a little cumbersome, and I have similar problem, is there any way to simplify that loop. Thank you in advance for your attention.
If you are open to using NumPy, you can solve the problem in literally two lines of code:
import numpy as np
n="-5 1 2 3 4 5 6 7 8 -3"
t = [int(i) for i in n.split()]
t = np.array(t) # Convert the list to a numpy array
t[t.argmin() : t.argmax() + 1].prod() # Get the range and the product
If you have more than one max element and want to go as far as the right-most of them, the code can be modified accordingly:
t[t.argmin() : t.size - t[::-1].argmax()].prod()
You could try something like this
n = "-7 5 -1 3 9"
n_list = n.split(" ")
n_list = list(map(int, n_list)) #In case of python3 use -- n_list = map(int, n_list)
max = max(n_list)
min = min(n_list)
result = 1
for i in range(len(n_list)):
if n_list[i] > min and n_list[i] < max:
result = result * n_list[i]
print(result);
I created a generator, which takes one argument, an iterable and yields values that are within range of min, max of this iterable. The product is computed as usual:
from itertools import chain
def values(iterable):
lst = list(int(i) for i in chain.from_iterable(i.split() for i in n))
_min, _max = min(lst), max(lst)
for i in lst:
if _min < i < _max:
yield i
n = ['7 5 -1 3 9', '3 14 -9 4 -5 1 -12 4', '-5 1 2 3 4 5 6 7 8 -3']
p = 1
for i in values(n):
p *= i
print(p)
Output:
-1234517760000

Function returning incomplete value

def sum_2_array(list1):
item = 10
numlist = list()
for i in list1:
num = list1.pop()
diff = item-num
if diff in list1:
return num, diff
print sum_2_array([2,3,5,8,7])
This function computes the minimum absolute diff between the elements of an array.The error is that it is returning just one value .
Can anayone please check and tell me where I am going wrong
Please run below code & see if it works. I have Used simple logic
def sum_2_array(list1):
item = 10
j = 0
for i in list1:
print "this is value of J = ", j
num = list1[j]
print "this is value of num = ", num
diff = item - num
print "this is vale of diff = ", diff
if diff in list1:
print num
print diff
j += 1
print sum_2_array([2, 3, 5, 8, 7])
Code you were running in that when it comes to third item in the list i.e 5. At the same time it pops out this item from the list. Because you are using list1.pop(). So it unable to find 5 in the list that's why you are getting only two values. Use code I gave & check if it works.
I got following result from that
this is value of J = 0
this is value of num = 2
this is vale of diff = 8
2
8
this is value of J = 1
this is value of num = 3
this is vale of diff = 7
3
7
this is value of J = 2
this is value of num = 5
this is vale of diff = 5
5
5
this is value of J = 3
this is value of num = 8
this is vale of diff = 2
8
2
this is value of J = 4
this is value of num = 7
this is vale of diff = 3
7
3

Categories

Resources