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()
Related
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 ?
I am really struggling with this program. I would appreciate any kind of help.
For a natural number we say that it is strange if it is completely composed of digits 2 and 3. The user enters a natural number. The program prints the n-th strange number.
Numbers that are considered strange are 2, 3, 22, 23, 33...
n = int(input())
current_number = 1
counter_strange = 0
counter = 0
while counter_strange < n:
x = current_number
while x < n:
k = x % 10
if k != 2 or k != 3:
counter += 1
else:
break
if counter >= 1:
counter_strange += 1
current_number += 1
print(current_number-1)
Strange numbers come in blocks. A block of 2 1-digit numbers, followed by a block of 4 2-digit numbers, then 8 3-digit numbers. You can do the math and determine which block of k-digit numbers a given index n is, and how far into that block it lies. Convert that distance into a base-2 number, zero-filled to k digits, then replace 0 by 2 and 1 by 3. Convert the result back to an int:
from math import log2, ceil
def strange(n):
"""returns the nth strange number"""
#first determine number of digits:
k = ceil(log2(n+2)) - 1
#determine how far is in the block of strange k-digit numbers
d = n - (2**k - 1)
#convert to base 2, zfilling to k digits:
s = bin(d)[2:].zfill(k)
#swap 2,3 for 0,1:
s = s.replace('0','2').replace('1','3')
#finally:
return int(s)
for n in range(1,10): print(n,strange(n))
Output:
1 2
2 3
3 22
4 23
5 32
6 33
7 222
8 223
9 232
You can use a while loop with itertools.product in a generator function. Using a generator will allow you to create a stream from which you can access strange numbers on the fly:
import itertools
def strange():
c = 0
while True:
yield from map(''.join, itertools.product(*([['2', '3']]*(c:=c+1))))
s = strange()
for _ in range(10):
print(int(next(s)))
Output:
2
3
22
23
32
33
222
223
232
233
while I was working on the Python practice, I found a question that I cannot solve by myself.
The question is,
Input one integer(n), and then write the codes that make a triangle using 1 to 'n'. Use the following picture. You should make only one function, and call that function various times to solve the question. The following picture is the result that you should make in the codes.
Receive one integer as an argument, print the number from 1 to the integer received as a factor in a single line, and then print the line break character at the end. Once this function is called, only one line of output should be printed.
So by that question, I found that this is a question that requires the
recursion since I have to call your function only once.
I tried to work on the codes that I made many times, but I couldn't solve it.
global a
a = 1
def printLine(n):
global a
if (n == 0):
return
for i in range(1, a + 1):
print(i, end=" ")
print()
a += 1
for k in range(1, n+1):
print(k, end=" ")
print()
printLine(n - 1)
n = int(input())
printLine(n)
Then I wrote some codes to solve this question, but the ascending and descending part is kept overlapping. :(
What I need to do is to break two ascending and descending parts separately in one function, but I really cannot find how can I do that. So which part should I have to put the recursive function call?
Or is there another way can divide the ascending and descending part in the function?
Any ideas, comments, or solutions are appreciated.
Thx
You can use the below function:
def create_triangle(n, k: int = 1, output: list = []):
if n == 1:
output.append(n)
return output
elif k >= n:
output.append(" ".join([str(i) for i in range(1, n + 1)]))
return create_triangle(n - 1, k)
else:
output.append(" ".join([str(i) for i in range(1, n + 1)[:k]]))
return create_triangle(n, k + 1)
for i in create_triangle(5):
print(i)
Output:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4
1 2 3
1 2
1
# function to print all the numbers from 1 to n with spaces
def printLine(k):
# create a range. if k is 4, will create the range: 1, 2, 3, 4
rng = range(1, k + 1)
# convert each number to string
str_rng = map(lambda x: str(x), rng)
# create one long string with spaces
full_line = " ".join(str_rng)
print(full_line)
# capture input
n = int(input())
# start from 1, and up to n, printing the first half of the triangle
for i in range(1, n):
printLine(i)
# now create the bottom part, by creating a descending range
for i in range(n, 0, -1):
printLine(i)
Using default parameter as a dict, you can manipulate it as your function variables, so in that way, you can have a variable in your function that keeps the current iteration you are at and if your function is ascending or descending.
def triangle_line(n, config={'max':1, 'ascending':True}):
print(*range(1, config['max'] + 1))
if config['ascending']:
config['max'] += 1
else:
config['max'] -= 1
if config['max'] > n:
config['ascending'] = False
config['max'] = n
elif config['max'] == 0:
config['ascending'] = True
config['max'] = 1
Each call you make will return one iteration.
>>> triangle_line(4)
1
>>> triangle_line(4)
1 2
>>> triangle_line(4)
1 2 3
>>> triangle_line(4)
1 2 3 4
>>> triangle_line(4)
1 2 3 4
>>> triangle_line(4)
1 2 3
>>> triangle_line(4)
1 2
>>> triangle_line(4)
1
Or you can run on a loop, two times your input size.
>>> n = 4
>>> for i in range(0,n*2):
... triangle_line(n)
...
1
1 2
1 2 3
1 2 3 4
1 2 3 4
1 2 3
1 2
1
Given an integer. for each individual digit that is greater than 4, i need to add it to all the next digits that greater than 4.
For example: a = 4567; the result should be 0 + (5) + (5+6) + (5+6+7) = 34
So far in my code, I was able to get the sum for single digit only. If the integer is greater 10, it will only give the sum of the very first digit. Any idea why this happening?
def morethanfour(number):
num = 0
num = [int(d) for d in str(number)] #seperate into individual digit
total = 0
for i in range (len(num)):
if num[i] > 4:
total = sum(x for x in range(5, num[i]+1)) #adding the sum
return total
num = 9
print(morethanfour(num))
the result when num = 9 is 35 (5+6+7+8+9)
However, when num = 178, it gave me 0
Try this:
>>> def morethanfour(number):
return sum(sum(range(5,x+1)) for x in map(int,str(number)) if x>4)
>>> morethanfour(9)
35
>>> morethanfour(4567)
34
>>> morethanfour(178)
44
>>> sum(sum(num[j] for j in range(0, i+1) if num[j] > 4) for i in range(len(num)))
34
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.