How to get minimum odd number using functions from list - python

I'm trying to get the minimum odd number using python. I used lambda, loops and other methods to get minimum odd number but i was not able to get that using functions. here is my code
z= [1,8,-4,-9]
def min_odd(x):
for i in x:
if (i%2!=0):
return min(i)
y = min_odd(z)
print (y)
Can some please tell me what i was missing here.

The min() function expects an iterable like a list which it will then yield the smallest element from.
E.g. min([1,0,3]) gives 0.
So if you want to use it, you must create a list (or other iterable) of the odd numbers that you can then pass into it:
def min_odd(x):
odds = []
for i in x:
if i % 2 != 0:
odds.append(i)
return min(odds)
note that we could also use a list-comprehension:
def min_odd(x):
return min([i for i in x if i % 2 != 0])
which both work.
An alternative method would be to store the current minimum odd value in a variable and update this variable if we come across a smaller odd value:
def min_odd(x):
min_v = float('inf')
for i in x:
if i % 2 != 0 and i < min_v:
min_v = i
return min_v

Try:
min([val for val in z if val % 2 != 0])

It seems your code logics are wrong. First off, you seem to have an indentation error in the return statement. Second off, the min() function requires a collection of items (like an array for example) or a series of arguments to determine the minimum in that series. You can try multiple things.
Use another variable to store a temporary minimum. Replace it every time you find a smaller odd value ( for every i in x... if the value is odd and is smaller than the previous odd value, replace it) and have it started with the first odd number you can find.
Take all the odd numbers and add them to another array on which you will apply the min function.
Hope this proves useful!

You could pass a generator into the min() function:
def min_odd(iterable):
return min(i for i in iterable if i % 2)
I didn't write i % 2 != 0 because any odd number will return 1 which has a Boolean value of True.
I added a parameter to the function that takes the iterable so it can be used for any iterable passed in.

min operates on an iterable. i is not an iterable in your code; it's the last element of the list.
You can achieve what you want with a filter, though:
min(filter(lambda e: e%2 != 0, x))

Related

Why isn't my function for getting the smallest value from a list working

I made a function for getting the smallest value from a list but it is not working properly and returning the wrong value. It prints out 5. What is wrong with it?
def finding_least_num(a_list):
first = 0
for i in a_list:
while first < len(a_list)-1:
if i < a_list[first]:
min_num = a_list[first]
first = first + 1
first = 0
print(min_num)
finding_least_num([3,7,5,2,9])
I am not sure why there are a lot of inner if and while statements. #Swishy has diagnosed the problem you are sticking with correctly. if you are insisting on not using min function, you can try code below:
def finding_least_num(a_list):
first = float('inf')
for value in a_list:
if value < first:
first = value
return first
which results in 2 in the case of using [3,7,5,2,9] as an input for the function.
Note that float("inf") is referring to the maximum number available in python.
if i < a_list[first]:
This is your problem, this instead needs to be:
if min_num > a_list[first]
It doesn't work because you are not checking against the lowest number you have saved already in min_num. You also need to initialize min_num to the first record in the array.
def finding_least_num(a_list):
first = 0
for i in a_list:
print("testing i = ", i)
while first < len(a_list)-1:
print("first = ", first)
if i < a_list[first]:
print ("checking if i < ", a_list[first])
print("i", i)
min_num = a_list[first]
print("minimum number here is ", min_num)
first = first + 1
first = 0
print(min_num)
finding_least_num([3,7,5,2,9])
I rewrote your code with comments and run it. Copy this into your interpreter and you will see the error and the reason why you received 5 each time. You will realize that your first for loop takes the first index of the array you passed to the function and tests it against the second while loop (let's call it chosen index). For each cycle the selected index is tested if it is less than the chosen index. If true set the minimum number as the chosen index. If you test the new code I have up there with the prints you will discover the last minimum number recorded is what was returned after the two loops completed. Python has many methods to help in these instances. For example min() is a very good way to simplify things. Another good way is to sorted() the array and return the first or last index depending on the order of the sorting.

In python, how can i make a binary search function with range and some conditions

The biggest problem for me is to express the value of mid according to the range.
plz I need a help Even if it's not a perfect answer, I need a hint. I don't even know if the reason I'm having a hard time is that Python is awkward or that I'm stupid.
def bsearch(ss, x): #just call bsearch_range
return bsearch_range( ss, x, range(len(ss)) )
def bsearch_range(ss, x, r): #ss is list, r=range(len(ss))
left,right=0,0
while len(r)>0:
mid= (r.start+(r.stop-1)) // 2
if ss[mid]==x:
left,right=mid,mid+1
return range(left,right)
elif x<ss[mid]:
right=right-1
else:
left=left+1
return range(left,right)
First. The bsearch function is a binary search function that tells you the range you want to find in range.
Second. Lists are sorted and may contain duplicate numbers.
For example) list ss=[1,2,2,2,3,6]
So. If duplicate elements exist in the list, we need to express the range of duplicate elements.
For example) list ss[1,2,2,2,3,6] , bsearch(ss,2)==range(1,4)
Third. If the element you want to find does not exist in the list, you should be able to tell the place where it should be in range.
For example) ss[1,2,2,2,3,6] bsearch(ss,7)==range(6,6)
Looking at your code, I believe you did not fully understand how the "normal" binary search algorithm works. (What is r for? It does not change throughout the loop body, so the while loop goes on forever...)
As a hint, this is what binary search in Python looks like:
def bi_search_left(array: list[int], x: int) -> int:
a, b = 0, len(array)
while a < b:
mid = (a + b) // 2
if array[mid] < x:
a = mid + 1
else:
b = mid
return a
Notice, the name of the function is bi_search_left. That is because it returns the index of the leftmost element matching the value of the x parameter. (Actually, it returns the index at which x needs to be inserted in in order for it to become the first element in the list with this value, so it also works for empty lists.)
By changing the function just a tiny bit, you could get bi_search_right, which, as the name says, returns the rightmost index. Combining these two methods could get you the desired result.
I think that was enough of a hint :)

Find the number from the set that is not present in the array

I was given this question in an interview: You are given a set of numbers {1..N} and an array A[N-1]. Find the number from the set that is not present in the array. Below is the code and pseudocode I have so far, that doesn't work.
I am assuming that there is one (and only one) number in the set that isn’t in the array
loop through each element in the set
loop through each element in the array O(n)
check to see if the number is in the array
if it is, do nothing
else, early return the number
def findMissingNo(arr, s):
for num in s: #loop through each element in the set
for num2 in arr: ##loop through each element in the array O(n)
if (num == num2): #if the number in the set is in the array, break
break
print (num)
return num #if the number in the set is not in the array, early return the number
return -1 #return -1 if there is no missing element
s1 = {1,4,5}
arr1 = [1,4]
findMissingNo(arr1, s1)
By defination, we have a set from 1 to N and a array of size N-1 , contains numbers from 1 to N , with one number missing and we have to find that number
since only 1 number is missing, and set has n element and array has n-1 element. so array is subset of set, with missing element as missing, that means
all_number_of_set = all_number_of_array + missing_number
also
sum_of_all_number_of_set = sum_of_array_number + missing_number
which implies
missing_number = sum_of_all_number_of_set - sum_of_array_number
pseudo code
def findMissingNo(set_, arr_ ):
return sum(set_) - sum(arr_)
If I understood your question well then you are finding the efficient way of finding the set number that do not exist in list. I see you are inner looping which would be O(n^2). I would suggest to make the dict for the list which would be O(n) then find O(1) element in dictionay by looping over set O(n). Considering large list with subset set:
def findMissingNo(arr_list, s_list):
d = dict()
for el in arr_list:
d.update({el: el})
for s in s_list:
try:
d[s]
pass
except KeyError:
return s
return -1
s1 = {1,4,5}
arr1 = [1,4]
findMissingNo(arr1, s1)
Hope it helps:)
Your function is quadratic, because it has to check the whole list for each item in the set.
It's important that you don't iterate over the set. Yes, that can work, but you're showing that you don't know the time complexity advantages that you can get from a set or dict in python (or hashtables in general). But you can't iterate over the list either, because the missing item is ... missing. So you won't find it there.
Instead, you build a set from the list, and use the difference function. Or better, symmetric_difference (^) see https://docs.python.org/3.8/library/stdtypes.html#set
def findMissingNo(arr, s):
d = set(arr) ^ s # symmetric difference
if 1 == len(d):
for item in d:
return item
print (findMissingNo([1,4], {1,4,5}))
5
I took a few shortcuts because I knew we wanted one item, and I knew which container it was supposed to be in. I decided to return None if no item was found, but I didn't check for multiple items.
What about something like:
def findMissingNo(arr, s):
for num in s: # loop through each element in the set
if num in arr:
pass
else:
return num # if the number in the set is not in the array, early return the number
return -1 # return -1 if there is no missing element

Taking the maximum of an arbitrary amount of arguments in Python

I have very little experience in coding and I'm learning Python in a class. I'm learning about conditionals and loops and have been asked to create a function that'll take an arbitrary amount of arguments and give me the maximum. Obviously I'm not allowed to use the built-in max function.
So far, I have:
def max(x):
current_max = x[1]
for i in x[i]:
if x[i] > current_max:
current_max = x[i]
When I run the code, it gives me no errors, but when I try to run max() it'll only accept one argument. The only idea that came to mind was adding in:
x = input('Enter numbers to compare:')
When I ran this, I got:
UnboundLocalError: local variable 'i' referenced before assignment
And I'm unsure of what I can do at this point as I'm unsure of whether or not I'm not defining the argument correctly or there's just an error in the code defining max(x) that didn't show up in the first time for some reason.
Two things:
1) In Python, you need to add a single * before the argument to indicate that the argument is actually a list of arguments. Without that *, you're function is only going to expect a single argument. EDIT: Ah I just saw you are actually passing a list object into your function, in which case the * isn't needed. If you wanted to support a call such as max(1,3,7,-4) then you would indeed want a *.
2) When iterating through a list, or any other "iterable", you can use for item in list_of_items: to iterate over and examine each item in the list. This is used all the time in Python and is the preferred way (ie. the Pythonic way) to iterate over the list of args in a case such as this.
Here's an example max function that ties it all together (and supports a call such as max(1,5,7,3):
def max(*x):
current_max = x[0] # Note we're assuming at least one argument was passed in. What if nothing was passed in?
for i in x:
if i > current_max:
current_max = i
return current_max
And here's an example max function that supports a call such as max([1,5,7,3]):
def max(x):
current_max = x[0] # Note we're assuming at least one argument was passed in. What if nothing was passed in?
for i in x:
if i > current_max:
current_max = i
return current_max
FYI My examples are not the best solutions to this problem, so I suggest you expand on them for your final solution.
x[i] is executed before the loop is for processed by the compiler so trying to loop through x[i] without i being declared beforehand will result in an error.
Given x where x is the list x = [ 1,2,3,4 ] the following should work
def max(x):
current_max = x[0]
for i in x:
if i > current_max:
current_max = i
return current_max
x = [1,2,3,4]
print max(x)
Your algorithm will work but there are two small problems. First, there is a problem with iterating over an array. Normally you don't need indexes at all, just do:
some_list = [1, 2, 3]
for item in some_list:
print item
# Will print 1, then 2 and finally 3
Also you need to return current_max when you are done with your loop.
Reusing names of builtin functions is not a great idea, so I'd call it my_max or something like that. If you also want to check your arguments and add a docstring, you'll end up with this:
def my_max(x):
""" Return the biggest item in an iterable. """
if len(x) == 0:
raise ValueError("my_max() arg is an empty sequence")
current_max = x[0]
for i in x:
if i > current_max:
current_max = i
return current_max
If you prefer a functional coding style, you can use reduce to reduce your list to the biggest element. Simply define the lambda that returns the biggest element:
def my_max(xs):
return reduce(lambda x, y: x if x > y else y, xs)
If you wonder how Python's built-in max is defined, it's actually written in C like many of Python's built-in functions. You can check it out on GitHub if you're curious. Internally it works just as min, since comparisons are done using something called PyObject_RichCompareBool that can compare two objects in different ways (less, less or equal, equal, not equal, ...)

Recursive Function in Python adding Odd Values in List

My task is to create a recursive function in Python that takes a list and a value of 0 as its inputs and then adds up all of the odd numbers on the list and returns that value. Below is the code that I have and it keeps returning that the list index is out of range. No matter what I do I can not get it to work.
def addodds2(x,y):
total=0
a=x[y]
while y<len(x):
if a%2!=0:
total+=a
return(addodds2(x,y+1))
else:
return(addodds2(x,y+1))
return(total)
print(addodds2([3,2,4,7,2,4,1,3,2],0))
Since you are trying to solve this recursively, I don't think you want that while loop.
When you are trying to solve a problem recursively, you need two parts: you need a part that does some of the work, and you need a part that handles reaching the end of the work. This is the "basis case".
Often when solving problems like this, if you have a zero-length list you hit the basis case immediately. What should be the result for a zero-length list? I'd say 0.
So, here's the basic outline of a function to add together all the numbers in a list:
Check the length, and if you are already at the end or after the end, return 0. Otherwise, return the current item added to a recursive call (with the index value incremented).
Get that working, and then modify it so it only adds the odd values.
P.S. This seems like homework, so I didn't want to just give you the code. It's easier to remember this stuff if you actually figure it out yourself. Good luck!
Your code should be (the comments explain my corrections):
def addodds2(x,y):
total=0
if y<len(x): #you don't need a while there
a=x[y] #you have to do this operation if y<len(x), otherwise you would get the index error you are getting
if a%2!=0:
total+=a
return total+addodds2(x,y+1) #you have to sum the current total to the result returned by the addodds2() function (otherwise you would got 0 as the final result)
return total
print(addodds2([3,2,4,7,2,4,1,3,2],0))
while y<len(x)
So the last y which is smaller than len(x) is y = len(x) - 1, so it’s the very last item of the list.
addodds2(x,y+1)
Then you try to access the element after that item, which does not exist, so you get the IndexError.
This code can be very short and elegant:
def add_odds(lst, i=0):
try:
return (lst[i] if lst[i] % 2 == 0 else 0) + add_odds(lst, i+1)
except IndexError:
return 0
Note that, in a truly functional style, you wouldn't keep track of an index either. In Python, it would be rather inefficient, though, but recursion isn't recommended in Python anyway.
def add_odds2(lst):
try:
return (lst[-1] if lst[-1] % 2 == 0 else 0) + add_odds2(lst[:-1])
except IndexError:
return 0
To make it work with any kind of sequence, you can do the following:
def add_odds3(it):
it = iter(it)
try:
value = next(it)
return (value if value % 2 == 0 else 0) + add_odds3(it)
except StopIteration:
return 0
It's much more efficient, though there's not much sense in using an iterator recursively...
I realize that little of this is relevant for your (educational) purposes, but I just wanted to show (all of) you some nice Python. :)

Categories

Resources