Adding condition in list in python - python

I don't know how to add extra conditions to this code.
(Only using randint)
For example with list [1, 2, 3, 4, 0] I need to generate random number except the last one (covered in my code) but the next condition is, it can not choose an index number which has a value of 0. So for list [3, 3, 0, 3, 3, 7] it can only consider indexes 0,1,3,4 (not 2 and 5 because I can not include the last number and index with value 0).
My code so far:
import random
our = [2, 3, 4, 0]
random_index = random.randint(0, len(our)-2)
random_number = our[random_index]
print(random_number)
I will be very glad for any help.

You can create a second list that stores the valid index values.
import random
our = [3, 3, 0, 3, 3, 7]
index = []
for i in range(0, len(our)-1) :
if our[i] != 0 :
index.append(i)
# index: [0, 1, 3, 4]
random_index = random.choice(index)
EDIT: You can perform a sanity check for a non-zero value being present.
The any() function returns True if any element of an iterable is True. 0 is treated as False and all non-zero numbers are True.
valid_index = any(our[:-1])
if valid_index:
index = []
for i in range(0, len(our)-1) :
if our[i] != 0 :
index.append(i)

You can use a while loop to check if the number equals 0 or not.
import random
our = [3, 6, 2, 0, 3, 0, 5]
random_number = 0
while random_number == 0:
random_index = random.randint(0, len(our)-2)
random_number = our[random_index]
print(random_number)

Related

Python loops with break/continue

Given a set of integers numbers = [10, 0, 11, 5, 3, 0, 6, 0, 2, 0, 6, 9] containing at least two zeros. Print the sum of numbers from the given set located between the last two zeros (if the last zeros are in a row, then print 0).
My attempt:
numbers = [10, 0, 11, 5, 3, 0, 6, 0, 2, 0, 6, 9]
index_of_first_zero = 0
i = 0
while i < len(numbers):
if numbers[i] == 0:
index_first_zero = 1
break
i += 1
index_of_last_zero = len(numbers) - 1
i = len(numbers) - 1
while i >= 0:
if numbers[i] == 0:
index_of_last_zero = i
break
i -= 1
summa = 0
while i in range(index_of_first_zero+1, index_of_last_zero):
summa += numbers[i]
print("Summa =", summa)
But unput is Summa = 0
Can you help me please?
It's much easier to reverse the list and look for the first two zeros.
>>> numbers = [10, 0, 11, 5, 3, 0, 6, 0, 2, 0, 6, 9]
>>> numbers_rev = reversed(numbers)
>>> sum_ = 0
>>>
>>> for x in numbers_rev:
... if x == 0:
... break
>>>
>>> for x in numbers_rev:
... if x == 0:
... break
... sum_ += x
>>>
>>> sum_
2
Alternative:
numbers = [10, 0, 11, 5, 3, 0, 6, 0, 2, 5, 6, 0, 6, 9]
numbers_rev = numbers[::-1]
sum_ = 0
for x in numbers_rev[numbers_rev.index(0)+1:]:
if x == 0:
break
sum_ += x
This should do the trick...
a = [10, 0, 11, 5, 3, 0, 6, 0, 2, 0, 6, 9]
i1 = a[::-1].index(0)
i2 = a[::-1].index(0,i1+1)
print("Summa =",sum(a[len(a)-i2:len(a)-i1]))
I hope this makes it clear :)
#take your original list
numbers = [10, 0, 11, 5, 3, 0, 6, 0, 2, 0, 6, 9]
#reverse the list
numbes = numbers.reverse()
#make clear that the first zero has not been encountered
encountered_zero = False
#set the temporary sum to 0
cur_sum = 0
#for every number in your list
for number in numbers:
#if it's a zero, and you haven't passed any yet
if number == 0 and not encountered_zero:
#mark it
encountered_zero = True
#skip the rest of the iteration
continue
#if you have already encountered a zero
if encountered_zero == True:
#add every number to the sum
cur_sum += number
#if you encounter another zero
if encountered_zero == True and number == 0:
#break out of the loop, you're done
break
#here you have your answer
summa = cur_sum
print("Summa =", summa)
There are a few mistakes in your program...
One mistake in your program is that in the final part you're telling the script: "While the variable i is in the iterator range do [...]"
However, you should put a for loop there, not a while, changing it to:
summa = 0
for i in range(index_of_first_zero+1, index_of_last_zero):
summa += numbers[i]
print("Summa = ", summa)
Now that part of the program should work properly, because i in the for loop will be replaced with the values in the range iterator.
Instead, with the while, i takes index_of_last_zero as value, so it will never be in the range iterator.
However, the second error is a logical one: you have to sum the numbers between the last two zeros, not between the first and the last one, so the best thing to do is to reverse the list as other users already answered, so the entire program has to change:
original_list = [10, 0, 11, 5, 3, 0, 6, 0, 2, 0, 6, 9]
reversed_list = reversed(original_list)
my_sum = 0
for num in reversed_list:
if num == 0:
# it breaks here because it found the first zero,
# and then it will continue the cycle from the next element
break
# Now it won't loop again from the beginning, but from where it broke before.
for num in reversed_list:
if num == 0:
break
my_sum += num
print(my_sum) # -> 2
This program will work, thanks to #timgeb, and works with reversed() which is a built-in function that returns an Iterator object.
Here will be clarified to you what is an Iterator and how to work with it.
Anyway, I'll put here another solution that won't use that function.
original_list = [10, 0, 11, 5, 3, 0, 6, 0, 2, 0, 6, 9]
reversed_list = [] # we'll create it manually
my_sum = 0
# let's create here the reversed_list
for i in range(len(original_list) - 1, 0, -1):
reversed_list.append(original_list[i])
while i < len(reversed_list):
if reversed_list[i] == 0:
# it breaks here because it found the first zero,
# and we store the index of the first zero.
index_first_zero = i
break
i += 1
# Now it won't loop again from the beginning, but from where it broke before.
for i in range(index_first_zero, len(reversed_list)):
if reversed_list[i] == 0:
break
my_sum += reversed_list[i]
print(my_sum) # -> 2

how to gete sum of duplicate in list in python?

how do i check how what is the duplicate numbers and what their sum?
I am working on a project and I cant get it.
list = [1, 3, 5, 2, 1, 6, 5, 10, 1]
You can iterate the list and count how many times each element is met, then it's easy to check which elements are repeated (they have counter greater than 1), and the sum would be simply element_value*count
li = [1, 3, 5, 2, 1, 6, 5, 10, 1]
counters = {}
for element in li:
counters[element] = counters.get(element, 0) + 1
for element, count in counters.items():
if count >= 2:
print('Repeated element', element, 'sum=', element*count)
You can set up a separate set to check which items have already been seen, and for those where this is the case you add them to a sum:
sum = 0
li = [1, 3, 5, 2, 1, 6, 5, 10, 1]
seen_numbers = set()
for n in li:
if n not in seen_numbers:
seen_numbers.add(n)
else:
sum += n
Note that this will add a number that is already in the list each time it recurs, i.e., a number that appears three times will be added to sum twice. I don't know if that's what you want.
If you need the single results you can construct a list where each element is a tuple. Each tuple contains the number, the count and the sum.
from collections import Counter
data = [1, 3, 5, 2, 1, 6, 5, 10, 1]
result = [(value, count, value*count) for value, count in Counter(data).items() if count > 1]
print(result)
If you need to find only the full total of all values that appear more than once:
print(sum(value*count for value, count in Counter(data).items() if count > 1))

Unexpected behavior of python code while solving a hackerranks problem called Lily's Homework

Link to the problem: https://www.hackerrank.com/challenges/lilys-homework/forum
Summary: We have to find the minimum no. of swaps required to convert an array into sorted array. It can be sorted in ascending or descending order. So, here is the array I want to sort:
arr = [3, 4, 2, 5, 1]
We sort it in ascending order we need 4 swaps, and 2 swaps when in descending order.
For descending: -Swap 5 and 3 and then swap 3 and 2
Now, I have written a python code to solve this test case. Here is the code:
arr = [3, 4, 2, 5, 1]
arr2 = arr[:]
count = 0; count2 = 0; n = len(arr)
registry = {}
for i in range(n):
registry[arr[i]] = i
sorted_arr = sorted(arr)
#######################first for loop starts#########################
#find no. of swap required when we sort arr is in ascending order.
for i in range(n-1):
if arr[i] != sorted_arr[i]:
index = registry[sorted_arr[i]]
registry[sorted_arr[i]],registry[arr[i]]= i, index
temp = arr[i]
arr[i],arr[index]=sorted_arr[i],temp
count = count + 1
###################first for loop ends#######################
# re-initalising registry and sorted_arr for descending problem.
registry = {}
for i in range(n):
registry[arr2[i]] = i
sorted_arr = sorted(arr2)
sorted_arr.reverse()
print(arr2) #unsorted array
print(registry) #dictionary which stores the index of the array arr2
print(sorted_arr) #array in descending order.
#find no. of swap required when array is in descending order.
for i in range(n-1):
print('For iteration i = %i' %i)
if arr2[i] != sorted_arr[i]:
print('\tTrue')
index = registry[sorted_arr[i]]
registry[sorted_arr[i]],registry[arr[i]]= i, index
temp = arr2[i]
arr2[i],arr2[index]=sorted_arr[i],temp
print('\t '+ str(arr2))
count2 = count2 + 1
else:
print('\tfalse')
print('\t '+ str(arr2))
print('######Result######')
print(arr)
print(count)
print(arr2)
print(count2)
Here's the problem:
When I run the code, the second for loop i.e. the for loop for descending gives wrong value of count which is 3. But, when I comment the first for loop, i.e. the for loop for ascending it gives correct value of count which is 2.
I want to know why for loop 2 changes output when for loop 1 is present.
The output I get when loop 1 is NOT commented.
arr2: [3, 4, 2, 5, 1]
Registry: {3: 0, 4: 1, 2: 2, 5: 3, 1: 4}
sorted_arr: [5, 4, 3, 2, 1]
For iteration i = 0
True
[5, 4, 2, 3, 1]
For iteration i = 1
false
[5, 4, 2, 3, 1]
For iteration i = 2
True
[2, 4, 3, 3, 1]
For iteration i = 3
True
[2, 4, 3, 2, 1]
######Result######
[1, 2, 3, 4, 5]
4
[2, 4, 3, 2, 1]
3
The error is in your second loop, where you have:
registry[sorted_arr[i]],registry[arr[i]]= i, index
This should be:
registry[sorted_arr[i]],registry[arr2[i]]= i, index
Generally, it is a bad idea to work with such arr and arr2 variables. Instead make two functions, and pass arr as argument to the function call. The function should then make a local copy of that array ( [:]) before mutating it. All other variables should be local to the function. That way the two algorithms use their own variable scope and there is no risk of "leaking" accidently a wrong variable into the other algorithm.

I need to know why this is the output for these python condition

numbers=[i**3 for i in range (10) if i**3%3==1]
print(numbers)
#gets 1,64,343
Why is 1, 64, 343 the answer?
This is equivalent to the code:
for i in range(10):
if (i*i*i) % 3 == 1:
numbers.append(i*i*i)
print (numbers)
You are checking if the remainder obtained when the cube of a number from 1 to 10 is divided by 3 is equal to 1. If it is, you are adding it to a list and printing it.
The meaning of **
ex: 2**3= 2*2*2 #this means 2 to the power 3 = 8
The meaning of %
ex: 5%2= 1 #the sign means module, that means the remaining value after divide 5 by 2, it is one.
in your way, the correct path to write the for each is
for i in range(0,10):
value = i**3
if(value%3 == 1):
print("the value is {0}".format(value))
so the result is :
the value is 1
the value is 64
the value is 343
bit explanation inside the for loop
first get the i = 0, at this point value = 0*0*0 = 0, then value%3=0
then get the i=1, at this point value = 1*1*1 = 1 ,the 'value%3' means 1%3 = 1, so the answer i 1
.... like this see about other conditions also. hope this will help to you.
first i is in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
then if (i*i*i) rem 3 is equal to 1
it selects (i*i*i)
and for [1,4,7]: (1*1*1)%3==1, (4*4*4)%3==1 and (7*7*7)%3==1:
1*1*1=1 and 1/3=0 :remainder=1
4*4*4=64 and 64/3=21 :remainder=1
7*7*7=343 and 343/3=114 :remainder=1
so the output is:
[1*1*1, 4*4*4, 7*7*7] which is [1, 64, 343]
your code:
numbers=[i**3 for i in range (10) if i**3%3==1]
print(numbers)
and this code:
numbers=[]
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
if (i*i*i) % 3 == 1:
numbers.append(i*i*i)
print(numbers)
output this:
[1, 64, 343]

Add a 0 or 1 based on a value in a certain column

I hope anyone can help me with the following. I have a list called: 'List'. And I have a list called X.
Now I would like to check whether the value in the third column of each row in List is smaller than (<) X or equal/bigger than X. If the value is smaller I would like to add a 0 to the 6th column and a 1 if it is equal/bigger. And for each X I would like the answers to be added to the upfollowing columns to List. So in this case there are 4 X values. So as a result 4 columns should be added to List. My code below probably shows I'm quite an amature and I hope you can help me out. Thank you in advance.
List = [(3,5,6,7,6),(3,5,3,2,6),(3,6,1,0,5)]
X= [1,4,5,6]
for item in X:
for number in row[3] for row in List:
count = 0
if number < item:
List[5+count].append(0)
count += 1
return List
else:
List[5+count].append(1)
count += 1
return List
return List
First, you should know that tuples (parenthesis enclosed lists) are immutable, so you can not change anything about them once they're defined. It's better to use a list in your case (enclosed by []).
List = [[3,5,6,7,6],[3,5,3,2,6],[3,6,1,0,5]]
X= [1,4,5,6]
for item in X: # loop on elements of X
for subList in List: # loop on 'rows' in List
if subList[2] < item: # test if 3rd element is smaller than item in X
subList.append(0); # push 0 to the end of the row
else:
subList.append(1); # push 1 to the end of the row
List = [(3,5,6,7,6),(3,5,3,2,6),(3,6,1,0,5)]
X= [1,4,5,6]
scores = []
for item in List:
scores.append(tuple(map(lambda x: 0 if item[2] < x else 1, X)))
result = []
for item, score in zip(List, scores):
result.append(item + score)
print(result)
# [(3, 5, 6, 7, 6, 1, 1, 1, 1), (3, 5, 3, 2, 6, 1, 0, 0, 0), (3, 6, 1, 0, 5, 1, 0, 0, 0)]
Your indentation is off (you should unindent everything starting with your for statement.
You can't append to tuples (your rows inside the List variable are actually tuples).
Since you are not in a function, return does not do anything.
Since indices start with 0, you should use row[2] for 3rd row.
There are more elements in your X than the number of rows in List.
That being said, you can also use list comprehensions to implement this. Here is a one-liner that does the same thing:
>>> List = [(3,5,6,7,6),(3,5,3,2,6),(3,6,1,0,5)]
>>> X = [1,4,5,6]
>>> print [tuple(list(t[0])+[0]) if t[0][2] < t[1] else tuple(list(t[0]) + [1]) for t in zip(List, X)]
will print
[(3, 5, 6, 7, 6, 1), (3, 5, 3, 2, 6, 0), (3, 6, 1, 0, 5, 0)]
List = [[3,5,6,7,6],[3,5,3,2,6],[3,6,1,0,5]]
X= [1,4,5,6]
elems = [row[3] for row in List]
for i in range(len(elems)):
for x in X:
if elems[i] < x:
List[i].append(0)
else:
List[i].append(1)
print List
And you cannot use return if you are not using functions.
return needs to be called from inside a function. It exits the function and the value specified by return is given back to the function.
So you can't use it in your program.
In the list, each row is actually known as a tuple. Tuples don't have the append function so you can't use that to add to the end of a row.
Also, you can't have two for loops in a single line. (Which is not a problem since we only need one to achieve your output)
I've modified your code so that it looks similar so it's easier for you to understand.
List = [(3,5,6,7,6),(3,5,3,2,6),(3,6,1,0,5)]
X= [1,4,5,6]
for item in X:
n = 0
for row in list:
if row[3] < item:
list[n] = list[n] + (0,)
else:
list[n] = list[n] + (1,)
n = n+1
print List
You need to add with (0,) or (1,) to show that it's a tuple addition. (Or else python will think that you're adding a tuple with an integer)
agree with Selcuk
[edited #1: Thanks #Rawing, I mistyped > as <]
Here is AlmostGr's version simplified:-
List = [[3, 5, 6, 7, 6], [3, 5, 3, 2, 6], [3, 6, 1, 0, 5]]
X = [1, 4, 5, 6]
for num in X:
for item in List:
if num > item[2]:
item.append(0)
else:
item.append(1)
it runs for all elements in X and produces the output:
[[3, 5, 6, 7, 6, 1, 1, 1, 1], [3, 5, 3, 2, 6, 1, 0, 0, 0], [3, 6, 1, 0, 5, 1, 0, 0, 0]]

Categories