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

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

Related

how does result = k + tri_recursion(k-1) give me an output of triangular numbers?

I'm currently learning about functions and I came across a recursions example on w3schools.com. This code is giving me a list of triangular numbers for an argument k > 0. My question is how exactly is it printing out a list of triangular numbers with "result" defined as result = k + tri_recursion(k-1) in the body of the code. The output for an input of k = 6, for example, gives me 1, 3, 6, 10, 15, 21 but I just don't understand how I'm getting a list of triangular numbers from such a simple setting of the return variable. Help would be much appreciated :)
def tri_recursion(k):
if k > 0:
result = k + tri_recursion(k-1)
print(result)
else:
result = 0
return result
print("\n\nexample result")
tri_recursion(6)
you need create a list to storage numbers:
tri_list = []
def tri_recursion(k):
if k > 0:
result = k + tri_recursion(k-1)
tri_list.append(result)
print(result)
else:
result = 0
return result
print("\n\nexample result")
tri_recursion(6)
print(tri_list)
Then you have:
k = 6
6 + tri_recursion(5)
5 + tri_recursion(4)
4 + tri_recursion(3)
3 + tri_recursion(2)
2 + tri_recursion(1)
1 + tri_recursion(0)
1 + 0 = 1
2 + 1 = 3
3 + 3 = 6
4 + 6 = 10
5 + 10 = 15
6 + 15 = 21
This happens because you are printing the sum of the previous numbers in each return of each recursion

Creating a Rhombus with numbers in python

Create a Rhombus through numbers if i input a number it should print the number of lines as same as input number and print the numbers upto given number, I'm not getting exact solution, Please help me out.
Examples :
If the input is 4
This will be the expected output.
1
1 2 3
1 2 3
1
If the input is 5
This will be the expected output.
1
1 2 3
1 2 3 4 5
1 2 3
1
If the input is 7
This will be the expected output.
1
1 2 3
1 2 3 4 5
1 2 3 4 5 6 7
1 2 3 4 5
1 2 3
1
I have tried,
size = 4
maxlen = len(str(size * size))
m = size * 2 - 1
matrix = [[' ' * maxlen] * m for _ in range(m)]
for n in range(size * size):
r = n // size
c = n % size
matrix[c + r][size - r - 1 + c] = '{0:{1}}'.format(n + 1, maxlen)
print '\n'.join(''.join(row) for row in matrix)
But i'm not getting exact solution. Please help me out..
def pattern_gen(n):
k = n
for i in range(1, n + 1):
if i % 2 != 0:
for j in range(0, int(k/2)):
print(end=" ")
for j in range(1, i+1):
print(j, end="")
print()
k = k - 1
k = 1
if n % 2 != 0:
n = n-1
k = 2
for i in range(n, 0, -1):
if i % 2 != 0:
for j in range(0, int(k/2)):
print(end=" ")
for j in range(1, i+1):
print(j, end="")
print()
k = k + 1

Why is Poisonous plants stack solution giving TLE?

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.

Kadane's Algorithm for 2D array with known boundaries

I have implemented the Kadane's algorithm for a 2D array in Python 2 with known boundaries, but I'm using the implementation for an online contest and the time it takes is more than the time given.
So that made me think if there is maybe another algorithm similar to Kadane's that has a smaller complexity, or if my code can be optimized in a way. My implementation works for any array with dimensions N x M and a subarray with dimensions maxRows x maxCols.
maxSumSubarray.py
import numpy as np
# returns the maximum sum for the given vector using kadane's algorithm, with
# maxRows maximum members in the sum
def kadane1DwithBounds(maxRows):
global temp
m = s = sum(temp[i] for i in xrange(maxRows))
k = 0
for i in xrange(1, N - maxRows + 1):
s -= temp[k]
s += temp[maxRows + i - 1]
k += 1
m = max(m, s)
return m
# prints the maximum "area" given by the values of an NxM array inside a
# subarray with dimensions maxRows x maxCols. temp holds the latest vector to be
# given to kadane1DwithBounds()
def kadane2DwithBounds(maxRows, maxCols):
global temp
for i in xrange(N):
temp[i] = sum(table[i][j] for j in xrange(maxCols))
m = kadane1DwithBounds(maxRows)
k = 0
for j in xrange(1, M - maxCols + 1):
for i in xrange(N):
temp[i] -= table[i][k]
temp[i] += table[i][maxCols + j - 1]
k += 1
m = max(m, kadane1DwithBounds(maxRows))
print m
line = map(int, raw_input().split())
N = line[0]
M = line[1]
maxRows = line[2]
maxCols = line[3]
table = []
temp = np.empty(N, dtype = int)
for _ in xrange(N):
table.append(map(int, raw_input().split()))
kadane2DwithBounds(maxRows, maxCols)
test.txt
4 8 2 3
1 1 2 3 3 1 1 1
2 2 2 2 2 2 2 2
3 3 3 1 1 3 3 4
0 0 1 1 3 2 2 1
Run with
python maxSumSubarray.py < test.txt
it gives
16
which is correct and is the following rectangle:
2 2 2
3 3 4
I've tried with other dimensions too and I'm pretty sure it works fine. Only problem is time/complexity. Any help would be appreciated! Thanks for your time.

Python Nested For Loop Counting Backwards

This is probably a simple problem, but I am trying to created a nested loop that would count up from 0 to 9 in the outer loop, and in the inner loop, start from the value (or index. They are the same in this case) of the outer loop and count backwards.
Here's an example:
i= 0
k= 0
i= 1
k= 1
k= 0
i= 2
k= 2
k= 1
k= 0
i= 3
k= 3
k= 2
k= 1
k= 0
I got this far:
x = range(0,10)
for i in x:
print 'i = ',x[i]
for k in x:
print 'k = ', x[i::-1]
Obviously, the code above doesn't do what I want it to do. For one, the second for loop doesn't start from the value of i in the outer loop and counts backwards. For another, it doesn't print a new k = for every new value.
I think this should be like this:
x = range(0,10)
for i in x:
print 'i = ',x[i]
for k in x[i::-1]:
print 'k = ', k
print("\n")
The result is:
i = 0
k = 0
i = 1
k = 1
k = 0
i = 2
k = 2
k = 1
k = 0
i = 3
k = 3
k = 2
k = 1
k = 0
i = 4
k = 4
k = 3
k = 2
k = 1
k = 0
i = 5
k = 5
k = 4
k = 3
k = 2
k = 1
k = 0
i = 6
k = 6
k = 5
k = 4
k = 3
k = 2
k = 1
k = 0
i = 7
k = 7
k = 6
k = 5
k = 4
k = 3
k = 2
k = 1
k = 0
i = 8
k = 8
k = 7
k = 6
k = 5
k = 4
k = 3
k = 2
k = 1
k = 0
i = 9
k = 9
k = 8
k = 7
k = 6
k = 5
k = 4
k = 3
k = 2
k = 1
k = 0
Basicly, x[i::-1] should be in the for not in the print.
What about just manipulate it with print function?
i = 0
k = 0
while True:
print (i)
print (k)
if 1<k: #tricky part
print ("\n".join([str(h) for h in range(0,k+1)][::-1]))
print ("")
i += 1
k += 1
if i == 10:
break
You are very close. If you are new to the world of python you can take some inspiration from this example where I use list comprehension.
list = lambda k: [ [ i for i in reversed(xrange(j+1)) ] for j in xrange(k+1) ]
Note: If you are using python 3 "xrange" is changed to "range"
Now call:
list(3)
And you'll see that the result is similar to what you are looking for.
[[0], [1, 0], [2, 1, 0], [3, 2, 1, 0]]

Categories

Resources