Getting fewer outputs than inputs - python

I'm trying to solve "Bad Prices" on Codeforces. The problem asks you to find the number of integers in the array, such that there is a smaller integer after them in the array. Here's a sample test:
5
6
3 9 4 6 7 5
1
1000000
2
2 1
10
31 41 59 26 53 58 97 93 23 84
7
3 2 1 2 3 4 5
The first number is the number of test cases, the following are the testcases, consisting of the length of the array and the array itself.
Here's my code:
for _ in range(int(input())):
count=0
a=input()
x=input().split(' ')
for i in x:
for j in x[x.index(i):]:
if int(i)>int(j):
count+=1
if count%2==0:
print(int(count/2))
else:
print(int(count))
count=0
x=[]
For some reason, the code works, but only for 4 of 5 test cases, completely ignoring the last one. What did I do wrong?

for j in x[x.index(i):]:
index() function always gives you the first occurrence.
Ex: array is 2 1 3 2 4 5 6
x.index(2)=0,x.index(1)=1,x.index(3)=2,x.index(2)=0,x.index(4)=4,x.index(5)=5,
x.index(6)=6.
Though there are multiple occurrences of 2, the index() functions cosiders the first occurrence always. So,When i=2(index=3), j iterates from the index(0) to index(6) and not from index(3) to index(6).
To overcome this you can make use of variable a(length of the array) and change it like this:
for i in range(int(a)):
for j in range(i,int(a)):
if int(x[i])>int(x[j]):
count+=1
if count%2==0:
print(int(count/2))
else:
print(int(count))
These conditions are not necessary.
If you find an element that is smaller than the current element u can increase the count and break from the inner loop and continue the process for the next element.
After the count+=1, you can add a break statement.
Replace the if, else condition with a print(count) statement.
3.
Initializing the count variable with zero at the beginning of a new test case is enough, no need to do it twice. Initializing x=[] will make no difference because the existing data will be overridden when you assign new data to the variable x[]

Tim Roberts identified the issue in the comments, the problem is your use of the index method. As he suggested, using the index generated fromenumerate will allow you to avoid that issue.
Note, slices are not indices, so whereas [cur_index + 1] may be an invalid index, [cur_index + 1:] is always a valid slice even though it may be an empty one.
Example:
num_sets = int(input())
for _ in range(num_sets):
_ = input()
prices_per_day_str = input()
prices_per_day = list(map(int, prices_per_day_str.split()))
bad_price_count = 0
for cur_index, cur_price in enumerate(prices_per_day):
for future_price in prices_per_day[cur_index + 1:]:
if cur_price > future_price:
bad_price_count += 1
break
print(bad_price_count)

Related

My code test does not pass my bubble sort algorithm

Ploblem:
Bubble sorting is an algorithm that sorts sequences of length N in such a way that two adjacent elements are examined to change their positions. Bubble sorting can be performed N times as shown below.
Compare the first value with the second value and change the position if the first value is greater.
Compares the second value with the third value, and if the second value is greater, it changes its position.
...
Compare the N - 1 and N - values ​​and change the position if the value of N - 1 is greater.
"Supchan" I know the result of bubble sorting, of course. However, since N is very large, it takes a long time to perform the above steps K times. Write a program that will help you to find the intermediate process of bubble sorting.
My Code
def bubble(list):
temp = 0
for i in range(0, len(list)):
for j in range(i+1, len(list)):
if (list[i] > list[j]):
temp = list[i]
list[i] = list[j]
list[j] = temp
return list
numbers = input()
items = [int(num) for num in numbers.split()]
print(bubble(items))
Test Condition
N and K are given in the first line.
The second line gives the status of the first sequence. That is, N integers forming the first sequence are given in turn, with spaces between them.
1 ≤ N ≤ 100,000
1 ≤ K ≤ N
Each term in the sequence is an integer from 1 to 1,000,000,000.
Input & Output
input: 3 1 2 5 4
output: 1 2 3 4 5
The code I wrote seems to work fine. However, the grading of the coding test rejects me.
I can not understand the reason because the reason is not listed. Is there a problem with my code?
Try changing the line
numbers = input()
to
numbers = raw_input()
It could be that the test input might be in the form
1 5 6 4 3
instead of
'1 5 6 4 3'
which might cause error while running using input()

Element in zipped for loop being skipped when removing element from list [duplicate]

I have a list of integers which I am running through a for-loop to discover if the sum of two of the elements equals another variable t. So if t was equal to 10 and I had a list of integers:
l = [1,2,3,4,5,8,9], then the function should print all the different combinations of numbers (1,9), (2,8).
I feel I am almost there, but something strange happens to the list when I use the .pop() function. The code below is being used to show all the combinations of numbers which need to be calculated, but every other element in the list is skipped.
l = [1,2,5,8,13,15,26,38]
c = 10
for i in l:
first = i
l.pop(0)
for x in l:
second = x
print(first,second)
Here is the output:
1 2
1 5
1 8
1 13
1 15
1 26
1 38
5 5
5 8
5 13
5 15
5 26
5 38
13 8
13 13
13 15
13 26
13 38
26 13
26 15
26 26
26 38
Notice how the 2, 8, 15, and 38 are skipped.
I am using l.pop() so that the second for-loop will not use the original value, and the next iteration can then go on to iterate the next element in the list.
What you are trying to do will not work, as you are modifying the list while you are iterating it. Say the current "pointer" points to the first element. Now you pop the first, so the pointer is at the second. But when the loop advances, the pointer is moved to the third, and the second is skipped.
It seems you want to find combinations from a list. There are a few other ways you can try:
Closest to your current approach: Use a while loop instead of for loop
while l:
first = l.pop(0)
for second in l:
print(first, second)
Or you could just iterate the indices instead of the lists themselves:
for i in range(len(l)):
for k in range(i+1, len(l)):
print(l[i], l[k])
Or just use itertools.combinations
import itertools
for first, second in itertools.combinations(l, 2):
print(first, second)
However, you can do better than that. Since you are looking for a pair of numbers that adds up to some target number, just subtract the first from the target to get the second and see if that second number is in the list of numbers. Use a set to make this lookup happen in constant time, reducing your overall time complexity from O(n²) to O(n).
numbers = set([1,2,5,8,13,15,26,38])
target = 10
for first in numbers:
second = target - first
if second > first and second in numbers:
print(first, second)
you need to choose another approach. You are not permitted to remove elements from the list while iterating over it using a for loop.

how to increment the iterator from inside for loop in python 3?

for i in range (0, 81):
output = send command
while True:
last_byte = last_byte - offset
if last_byte > offset:
output = send command
i+
else:
output = send command
i+
break
I want to increase the iterator every time the send command is executed. Right now it only increases by one when the for loop is executed. Please advise
for i in range(0,10):
print(i)
i +=2
print("increased i", i)
I ran this code and it produced out from 0 to 9. I was expecting it would increase the iterator by 2.
Save a copy of the iterator as a named object. Then you can skip ahead if you want to.
>>> myiter = iter(range(0, 10))
>>> for i in myiter:
print(i)
next(myiter, None)
...
0
2
4
6
8
You can't do this inside a for loop, because every time the loop is restarted it reassigns the variable i regardless of your changes on the variable.
To be able to manipulate your loop counting variable, a good way is to use a while loop and increase the throwaway variable manually.
>>> i = 0
>>> while i < 10 :
... print(i)
... i += 2
... print("increased i", i)
...
0
('increased i', 2)
2
('increased i', 4)
4
...
Additionally, if you want to increase the variable on a period rather than based on some particular condition, you can use a proper slicers to slice the iterable on which you're looping over. For instance, if you have an iterator you can use itertools.islice() if you have a list you can simply use steps while indexing (my_list[start:end:step]).
range() has an optional third parameter to specify the step. Use that to increment the counter by two. For example:
for i in range(0, 10, 2):
print(i)
print("increased i", i)
The reason that you cannot increment i like a normal variable is because when the for-loop starts to execute, a list (or a range object in Python 3+) is created, and i merely represents each value in that object incrementally.
#ilaunchpad Sorry I know it's too late to post this but here is what you were looking for
i=0
for J in range(0,10):
print(i)
i = i + 2
print("increased i", i)
You should not use the same variable throughout in the For statement.
Output
vaibhav#vaibhav-Lenovo-G570:~$ python3 /home/vaibhav/Desktop/Python/pattern_test.py
0
2
4
6
8
10
12
14
16
18
increased i 20
How about this?
for i in range(10):
if i == 3:
i += 1
continue
print(i)
Just adding the continue makes the counter go up - the print result is:
0
1
2
4
5
6
7
8
9
Note that without the continue, the 4 will be printed twice.
I think this answers the question.
I wrote something like this.
while True:
if l < 5:
print "l in while", l
l += 1
else:
break
Now I am having a full control but the backdrop is that I have to check all the conditions.
As there are no answers that allow to use the result of the next iterator, here is my proposed solution, that works with many lists and iterables by using either the enumerate() function or just the iter() function:
x = [1, True, 3, '4', 5.05, 6, 7, 8, 9, 10]
x_enum = enumerate(x)
for idx, elem in x_enum:
if idx == 1: # Example condition to catch the element, where we want to iterate manually
print('$: {}'.format(elem))
idx, elem = next(x_enum)
print('$: {}'.format(elem))
else:
print(elem)
will print:
1
$: True # As you can see, we are in the if block
$: 3 # This is the second print statement, which uses the result of next()
4
5.05
6
7
8
9
10
This is also possible with a simple iterator:
x_iter = iter(x)
for elem in x_iter:
if elem == '4': # Example condition to catch the element, where we want to iterate manually
print('$: {}'.format(elem))
elem = next(x_iter)
print('$: {}'.format(elem))
else:
print(elem)

Python, For loop counter do not update?

I am writing a simple program which gives the list of all prime no. less than a given no. N.
I am facing a problem that my for loop counter check in the function primes_gen else clause do not updates. Though, when i use the same logic without a function, as mention in the second code snippet, everything works correct.
Logic applied:-
when n passed to function is <= 2, blank list is returned
when n is > 2, range(3,n,2) identifies all the odd number. This is step 1 marked in first code snippet.
second for loop, marked with step 2, checks if no. is divisible to the all no.'s less than i. If yes then check counter is incremented by +1 and this loop is ended with 'continue'
if check remains zero till the end of the for loop then i is appended to the list and the finally after completion of the loop list is returned.
Problem:-
-The list i got as a result was [2] which is wrong ans. so I wrote step 3, as marked in 1st snippet, and i found that my check counter do not updates after the 'continue', as shown in the output. when same logic is applied without a function as written in second code snippet everything works correct.
I am not able to get what is going wrong here, why does check do not updates after continue?
contents =['10']
def prime_gen(n):
num_list=[2]
if n <=2:
return []
else:
for i in range(3,n,2): #step 1
check=0
for u in (2,i): #step 2
if i%u == 0:
check += 1
continue
print (check,i) #step 3
if check == 0:
num_list.append(i)
return num_list
if __name__== '__main__':
for j in range(len(contents)):
print (int(contents[j]))
num_list = prime_gen(int(contents[j]))
print (str(num_list).replace('[','').replace(']',''))
Output
10
1 3
1 5
1 7
1 9
2
Expected ans is (when step 3 above is commented)
10
2, 3, 5, 7
Second code without function
contents = ['10'] #to-check
for i in range(len(contents)):
target = int(contents[i])
num_list= [2]
for j in range(3,target,2):
check = 0
for u in range(2,j):
if j%u == 0:
check +=1
continue
if check == 0:
num_list.append(j)
#print (num_list)
print (str(num_list).replace('[','').replace(']',''))
output
2, 3, 5, 7
Your problem took a second to find, but is very simple to solve. The issue is at your "Step 2". You have the line
for u in (2,i): #step 2
That iterates u through all the variables in the tuple you provide, namely 2 and i. Of course, i%i will be 0, so check will always be true. What you want instead is this:
for u in range(2,i): #step 2
This will iterate u through all the variables between 2 and i, as you intend.
See these two examples:
>>> i = 7
>>> for u in (2,i): print u,
2 7
>>> for u in range(2,i): print u,
2 3 4 5 6
Basically, you just forgot to use range in your for loop, and that's going to give you wildly different results than what you actually want.

Control the index of a Python for loop

How do you control the index of a python for loop? (or can you? or should you?)
For Example:
for i in range(10):
print i
i = i + 1
Yields:
0
1
2
3
4
5
6
7
8
9
I want it to yield:
0
2
3
4
5
6
7
8
9
10
I really do apologize if I'm just completely off track with this question, and my brain is completely failing me at the moment and the solution is obvious.
Why am I asking?
This is irrelevant to the question, but relevant to the why I need the answer.
In a Python script I'm writing, I am doing something like this:
for i in persons:
for j in persons[-1(len(persons) - i - 1:]:
if j.name in i.name:
#remove j.name
else:
#remove i.name
#For every person (i), iterate trough every other person (j) after person (i)
#The reason I ask this question is because sometimes I will remove person i.
#When that happens, the index still increases and jumps over the person after i
#So I want to decrement the index so I don't skip over that person.
Maybe I am going about this completely the wrong way, maybe I should use a while loop and control my indices.
How do you control the index of a python for loop? (or can you? or should you?)
You can't / shouldn't - the loop control variable will be reassigned at the end of each iteration to the next element of whatever it is you are iterating over (so that i = i + 1 has no effect, since i will be reassigned to something different for the next iteration anyway). If you want to control the index like that, you should use a while-loop:
i = 0
while i < 10:
print i
i = i + 1
Although, Python's range function is more flexible than you might realize. For instance, to iterate in steps of 2 you can simply use something like
for i in range(0, 10, 2):
print i
Check out the docs on range here, or from the docstr:
range([start,] stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
To get range from 0-10, just do:
> for i in range(0, 11):
> print i
> 0
> 1
> 2
> 3
> 4
> 5
> 6
> 7
> 8
> 9
> 10
By the way, it's pointless to do the i = i + 1, cause every iteration in the for loop will change i again. Whatever you set it to in the loop, will get overwritten every time the loop starts over.

Categories