Wrong output in Python - as per my logic - python

Can someone tell me why my program is working weird. I am trying to sort list1 in ascending order. This code is part of my quick sort program I am trying to write. As per my logic which I am applying in this code, and I checked manually too, the output should be [1,2,3,4,5]. However the output is coming out to be [1,2,2,4,5]. Can you tell what's going wrong?
list1=[3,2,1,5,4]
n_list1=len(list1)
count=0
for position1, item1 in enumerate(list1[0:n_list1]):
temp=item1
count=count+1
for position2 in range(count,n_list1):
if list1[position1]>list1[position2]:
list1[position1]=list1[position2]
list1[position2]=temp
temp=list1[position1]
print list1
EDIT: What I am trying to do is like this:
I start comparing the first element with the following (n-1) elements and swap the smallest element with the first one. Now I go to 2nd element and compare it with the following (n-2) elements and swap with the smallest element among those (n-2) elements. Like this I move forward.
Note: This is part of my quicksort program and it is not in itself quicksort. This part is for the list1 to which I assign numbers less than pivot. Another code will be for list2 where I will assign numbers greater than pivot.

Since you do count = count + 1 right before the innermost for, you never get to reach the first position of list1 (list1[0]), which is the element "3".
[Edit] Looking more carefully at your code, there seems to be a lot of confusion. For instance, on
list1[position1]=list1[position2]
list1[position2]=temp
temp=list1[position1]
You're losing list1[position1]: you're overwriting it with list[position2], before trying to save it at the temp variable. Try moving temp=list1[position1] to the first line after the if.
And, honestly, your implementation is overly complicated. I suggest you try writing it in pseudo-code, try to actually understand what's going on, and then re-implement it.

The answer provided by rbp is absolutely correct!
Also, I guess you could simplify the above by remove count itself, also directly enumerate the list and use the python idiom - a, b = b, a to swap the values
list1=[3,2,1,6,5,4]
n_list1 = len(list1)
for position1, item1 in enumerate(list1):
for position2 in range(position1,n_list1):
if list1[position1]>list1[position2]:
list1[position1] , list1[position2] = list1[position2], list1[position1]
print list1
Output:
[1, 2, 3, 4, 5, 6]
[Edit: About the idiom]
>>> a = 4
>>> b = 5
>>> a , b = b, a
>>> a
5
>>> b
4
>>> c = 5
>>> d = 6
>>> t = c
>>> c = d
>>> d = t
>>> c
6
>>> d
5
>>>

A small improvement to pyfunc's correct answer...
This line
for position2 in range(position1,n_list1)
can be
for position2 in range(position1+1,n_list1)
and will save you a little time.

Related

Can someone explain what the mylist[a][b] does in this Python code?

mylist = [ [2,4,1], [1,2,3], [2,3,5] ]
a=0
b=0
total = 0
while a <= 2:
while b < 2:
total += mylist[a][b]
b += 1
a += 1
b = 0
print (total)
I don't understand what mylist[a][b] does.
I tried adding print statements and checked each of the outputs, but I still can't figure out what it does.
The output with print statement I got was:
(each printed output every time it goes through the loop:)
2
4
1
2
2
3
(total)
14
I thought each output were the items inside the lists in mylist, but realized it's not. I also tried changing the numbers inside the lists, I still don't understand. Can someone simply explain it to me please?
The object between the [ and ] brackets is a "list" and a list can be made of other lists.
When you want to get the value from a list at a particular position, you use the [n] notation, where the n is the position (starting at zero).
If the object at position n is also a list, then you can extract items from that sub-list by again using the square brackets.
So, if I have a list l = [ [1,2,3], [4,5,6] ] then l[0] is equal to [1,2,3] and therefore l[0][1] is equal to 2.
The code you posted is looping over the lists inside the list and then the items inside each of those inner lists.
Okay, You can visualise this code mylist[a][b] as (mylist[a])[b]. So 1st part will get a value of position [a] from my list and then it will get a value of position [b] of mylist[a]. For an example:
mylist = [ [2,4,1], [1,2,3], [2,3,5] ]
Let's say a=1 , b=0
If you want to print mylist[a][b]. It will 1st get [1, 2, 3] then it will get the value at 0 position of the list. So the final output should be 1

Doing math with numbers in a list

i want to be able to add, subtract, divide, multiply etc with integers in a list and in order.
I know you can use sum() to add, but i also want to be able to subtract, etc in order... so i tried making a for loop idk if thats the right thing to do, but it doesn't give me the right output and it really confuses me because it really seems like it should work. I was wondering if anyone knows how to fix this or explain why its not giving me the same output as i expected.
my_list = [100, 15, 3]
for i in my_list:
i -= i
print(i)
# 100 - 15 - 3 = 82
# Wanted output: 82
# Actual output: 0
my_list = [100, 15]
for i in my_list:
i += i
print(i)
# 100 + 15 = 115
# Wanted output: 115
# Actual output: 30
There are two main issues with your code:
i can't be your loop variable and the sum, because it will be overwritten all the time. So make two variables.
Your first task is different from the second. The sum is easy: take all the values of the list and add them, so the order is irrelevant. For your subtraction it's different because you have to take the first value and subtract all others, so it's basically +100-15-3, which means that also the order of the values in the list matter.
There are more elegant ways to solve it, but for the beginning this should be better to understand.
my_list = [100, 15, 3]
my_difference = my_list[0] #initialize with the first value of your list
my_list_sub = my_list[1:] #make a new list with the remaining numbers
for val in my_list_sub:
my_difference=my_difference-val
print(my_difference)
my_list = [100, 15]
my_sum = 0 #initialize your sum with 0
for val in my_list:
my_sum=my_sum+val
print(my_sum)
As others already pointed out: The "running"/temporary variable is overwritten in every loop. You can try this out with a simple test:
for entry in [0, 'a', 13.37]:
print(entry)
It's always a good idea of trying out what happens in simple cases to learn what is going on.
But your idea of solving this with a loop is absolutely fine. If you want to re-use this functionallity later, it is also nice to wrap that in a function.
Assume integer values my_values = [100, 50, 123, 51, 124, 121] in the following examples.
Lets first tacle the sum.
def calculate_sum(values: list) -> int:
result = 0
for entry in values:
result += entry
return result
Check that it does what we want with
print(calculate_sum(my_values))
print(sum(my_values))
Now difference is 'almost' like summing up, but you want to sum up all values but the first one, and then compute the difference to the first one (a-b-c-d = a-(b+c+d)). Great, that we have already a method for summing up stuff, so we could simply do
def calculate_difference(values: list) -> int:
first, *other = values
return first - calculate_sum(other)
Note the *-marker in front of the other variable. When assigning a list two multiple variables, they are "unpacked" by python. Thus a, b, c = [0, 1, 2] would assign 0 to a and so on. However, when we do a, b = [0, 1, 2], then python complains because there are too many variables to unpack in the list (3 > 2). With the asterisk we simply tell python to put all other values, not used so far, into this special variable again. a, b, *rest = [1, 2, 3, 4, 5, 6] is also possible.
Ok, computing the product is as easy as summing up, just replace += by *= in the method. And for the quotient we can do the same as for the difference, since a * 1/b * 1/c * 1/d = a / (b*c*d). However, note that if the divisor is zero, python will raise an Error DivisionByZero, as this is not legal. Also, the result of the method is float and no longer int.

Count the unique elements in a list without set

I am currently attempting to make a program that will count and print the number of unique elements in a list.
My code:
def solution(N, A):
yee = 1
for i in range(1, len(A)):
j = 0
for j in range(i):
if(A[i] == A[j]):
yee-=1
if(i==j+1):
yee +=1
print(yee)
N = int(input())
A = []
n = 0
for e in input().split():
if(n<N):
A.append(int(e))
n+=1
solution(N, A)
With the list containing (1 2 3 1 4 2 5 6 7 8) the output is supposed to be 6. However, my program is returning 8. I believe this is due to the program counting the 1 and 2, even though they are not technically unique in the problem. I'm sure it's and easy fix, but I just can't seem to figure it out. Any help would be greatly appreciated!!
The only way you would get the output of 6 for (1, 2, 3, 1, 4, 2, 5, 6, 7, 8) would be if you wanted to count the number of elements that appear exactly once, as opposed to the number of unique elements (there are 8 elements, of which two are repeated more than once).
You could do this in a one-liner:
def num_single_elements(A):
return len(list(e for e in A if A.count(e) == 1))
Similarly if you need to keep check of the number of elements further on in your code, I like dictionary comprehension for this kind of problem:
dict_A = {x:A.count(x) for x in A}
print(len([x for x in dict_A if dict_A[x] == 1]))
As Green Cloak Guy said, you seem to be looking for the number of elements which appear exactly once, and his answer contains a solution to that. Here's a simple solution for finding the number of unique elements:
def unique_elements(A):
return len([ 1 for (index, a) in enumerate(A) if A.index(a) == index ])
The idea here is to count up the first occurrence of each unique value.
enumerate allows us to get the index of the item, as well as the item itself, as we iterate;
A.index(a) gives the index of the first time the value of a appears in A.
So, if we count up all the times index equals A.index(a), we're counting the first time an item appears which has never appeared before, which is equal to the number of unique elements.

How to find the max of 3 indexes in a list?

Short and simple, let's say I have this list:
a = [["Bob","5","10","7","4.5","6.3","6.4"],["Charles","3","4","5","5.2","8.34","356.444"]]
I want to find to find the highest value of index 1,2 and 3 only (so the highest value out of 5,10 and 7 and then the highest out of 3, 4 and 5.
I'm not familiar with max(), however I have tried
for b in a:
c = max(b[1],b[2],b[3])
print(c)
And to no surprise it does not work.
How would I do this in the simplest way? I'm sure there is probably an easy method, if what I have said makes sense.
You can do this:
>>> [max(map(float, el[1:4])) for el in a]
[10.0, 5.0]
This returns a list with the max of the 3 indexes (1,2,3) for each entry in the list.
Your original code was not working because you were calling max() on the numbers (as strings) before converting them. Therefore, changing
c = max(b[1],b[2],b[3])
to
c = max(int(b[1]),int(b[2]),int(b[3]))
would also give you the result you expected.

How do I perform math on every other number in a list?

E.g.: How do I change
a = [1,2,3,4]
to this:
a = [2,2,6,4]
so every other element is doubled?
If you want to do it in place, you can use slice assignment:
>>> a[::2] = [x*2 for x in a[::2]]
>>> a
[2, 2, 6, 4]
You can loop through every other index:
for index in range(0, len(your_list), 2):
your_list[index] *= 2
You can also do it using slice assignment, as #mgilson notes:
your_list[::2] = [x*2 for x in your_list[::2]]
While this is certainly more concise, it may also be more confusing for the average person reading through the code - assigning to a slice with a non-default skip factor isn't very intuitive.
There is another way to take two steps at a time a little more intuitive, like this
for i in range(len(yourList)/2):
yourList[2*i] = 2*yourList[2*i]
Though I do like the neat tricks used in the other answers, perhaps a more verbose and less-language specific explanation of what's going on is as follows:
for i in range(0, len(a)): # Iterate through the list
if i%2 == 0: # If the remainder of i รท 2 is equal to 0...
a[i] = a[i] * 2 # Change the current element to twice what it was

Categories

Resources