For my problem I have to write a min function that can take up to 4 numeric arguments but must have at least 2. The third and fourth arguments have to be set to None if they aren't passed a value. The function should return the smallest value of those passed and must work with either 2, 3, or 4 values.
This is what I have:
def min(num1, num2, num3=None, num4=None):
if num1<num2:
result=num1
elif num2<num1:
result=num2
elif num3>None:
if num3<num1 and num3<num2:
result=num3
else:
min_num=num4
return result
When I run it in python and enter 4 values, it doesn't return the minimum number. It just returns a random number from the four arguments I entered. Can anyone help me out?
You are using elif which only executes if if condition is false. So, you can fix by using all if conditions. Also, you have default value to None which you can compare using != None. You can try something like:
def minimum(num1, num2, num3=None, num4=None):
# this first if else will check with num1 and num2 only
if num1 < num2:
result = num1
else:
result = num2
# after checking between num1 and num2
# the result will be checked with num3
# if num3 is provided
if num3 is not None and num3 < result:
result = num3
# if num4 also provided then the result will be compared with it
if num4 is not None and num4 < result:
result = num4
return result
Your logic is flawed in several ways. Draw the logic tree your want, the way you would do it with a list of numbers, and implement that, rather than what you've posted here.
if num1<num2:
result=num1
elif num2<num1:
result=num2
elif ...
Look at the logic here: the only way you get to the last two arguments is if num1 == num2. If you feed your function (5, 7, 1, 0), it will return 5.
elif num3>None:
What are you trying to do here? None is not a valid numerical value; this is an illegal comparison. Try
if num3 is not None and ...
Suggested logic: keep track of the smallest number so far in a separate variable; compare each value against that.
This can be a solution in order to avoid the ifs and using an in-built function.
def my_min(num1, num2, num3=None, num4=None):
my_numbers = [num1, num2, num3, num4]
return min(my_numbers)
print(my_min(4, 3, 2, 1))
First of all, you shouldn't use the min() as your function name, because it is a keyword of python.
Secondly, the number of "if-else" conditions should be minimal, it is too much, you might need to think about other options.
def custom_min(num1, num2, num3=None, num4=None):
min_value = num1
for num in [num2, num3, num4]:
if !(num is None) and min_value>num:
min_value = num
return min_value
print(custom_min(1, 2))
print(custom_min(2, 1, 4))
print(custom_min(2, 1, 4, 0))
The output is:
1
1
0
Related
Still new to python and this problem is driving me crazy I know I'm missing something really obvious but I just can't figure it out :/ Here is the problem:
Write a function called main that prompts/asks the user to enter two integer values.
Write a value returning function named max that accepts two integer values as arguments and returns the value that is the greater of the two. For example, if 30 and 25 are passed as arguments to the function, the function should return 30.
Call the max function in the main function
The main function should display the value that is the greater of the two.
This is my code, unsure of where I went wrong
def main():
num1 = int(input('Enter the first number'))
num2 = int(input('Enter the second number'))
return num1, num2
max(n1, n2)
print(max)
def max(n1, n2):
return max
main()
When you call a the max function you need to read the returned value. What you're printing at the end of main is the max function itself. The issue would be clearer if you renamed the max function "getMax".
A second issue is that no code is executed after return in a function. So the main function stops on the fourth line when it returns num1 and num2.
You've got a lot of it there. Here's how to pull it all together:
def get_max(n1, n2):
return n1 if n1 > n2 else n2
def main():
num1 = int(input('Enter the first number> '))
num2 = int(input('Enter the second number> '))
print(f"The maximum of {num1} and {num2} is {get_max(num1, num2)}")
main()
Result:
Enter the first number> 345
Enter the second number> 333
The maximum of 345 and 333 is 345
I know the instructions say to create a function named max, but that's the name of a very commonly used function in the standard Python library. It's best that you avoid redefining built in functions by reusing their names.
Here's what you want:
def main():
num1 = int(input('Enter the first number: '))
num2 = int(input('Enter the second number: '))
result = max(num1, num2)
print(result)
def max(n1, n2):
if n1 > n2:
return n1
else:
return n2
main()
If you want to use the built-in max() function under the function you created, rename your function to something different to avoid a recursion error.
def max_num(num1, num2, num3):
return max(num1, num2, num3)
if num1 == num2 or num1 == num3 or num2 == num3:
return "It's a tie"
This code isn't returning "It's a tie" when it should be. Might be a simple error as new to coding but struggling to understand.
Thanks!
This code is never reaching the conditional statement because the return statement will always exit the function. Instead write:
def max_num(num1, num2, num3):
m = max(num1, num2, num3)
if num1 == num2 or num1 == num3 or num2 == num3:
return "It's a tie"
else:
return m
This will return "It's a tie" if any two of the numbers are the same, otherwise the largest of the three.
Alternatively this is a more efficient way of writing it:
def max_num(num1, num2, num3):
if num1 == num2 or num1 == num3 or num2 == num3:
return "It's a tie"
else:
return max(num1, num2, num3)
This means the maximum is only calculated if there is no tie so the function is more efficient.
You (roughly) wrote:
return a_value
if condition:
return different_value
return None
Please understand that the initial return
prevents the rest of the code from running.
We call it "unreachable code".
The flow of control transfers when we
hit the return, so subsequent
statements are never even considered
for evaluation.
Also, falling off the end of a
Python function (the else clause of your if)
will default to returning a None object.
You want to first evaluate the if,
and then return the numeric
maximum value.
Python is a dynamically typed language,
so it is kind of OK to have mixed
return types, such as str / int as
we see here.
But it's not a best practice.
It tends to make it hard for the
calling function to consume the
return value.
For example, the expression
1 + max_num(a, b, c)
will evaluate nicely on some of your tests, but it will raise an
error on e.g. 1 + max_num(2, 2, 3).
This example also highlights a code
defect in the OP logic.
Note it is quite different
from 1 + max_num(2, 3, 3),
where there truly is a legitimate
tie for maximum.
When designing a public API, consider
how the consumer will use the return
value. In this case, you might want
to return a tuple:
m = max(num1, num2, num3)
is_tie = ( (num1 == num2 == m)
or (num1 == num3 == m)
or (num2 == num3 == m))
return m, is_tie
OTOH if consumer will merely print it,
then the current API is just fine.
At the first return the function exits. Control flow never reaches the conditional. Perhaps you meant the following, checking for a tie, otherwise returning the maximum number.
def max_num(num1, num2, num3):
if num1 == num2 or num1 == num3 or num2 == num3:
return "It's a tie"
else:
return max(num1, num2, num3)
As a sidenote, another way to check for a tie would be to check the length of a set created from the three numbers. A set will not contain duplicates, so if it's less than 3, there must be a tie.
def max_num(num1, num2, num3):
if len(set([num1, num2, num3])) != 3:
return "It's a tie"
else:
return max(num1, num2, num3)
Rather than returning a string from your function in the event of a tie, you may wish to raise an exception so the calling code can handle that situation as it sees fit.
class TieException(Exception): pass
def max_num(num1, num2, num3):
if len(set([num1, num2, num3])) != 3:
raise TieException
return max(num1, num2, num3)
try:
print(max_num(1, 2, 2))
except TieException:
print("It's a tie")
Note that else is not necessary here because raising the exception also forces control flow to leave the function. The return will not be evaluated if the fist condition is true.
You might also use count to check for a tie situation.
def max_nums(num1, num2, num3):
nums = [num1, num2, num3]
if any(nums.count(n) > 1 for n in nums):
raise TieException
return max(nums)
This has the benefit of scaling so that any number of numbers can be passed in. Though you may wish to raise a TypeError exception if no numbers are provided.
def max_nums(*nums):
if len(nums) == 0:
raise TypeError("max_nums requires at least one argument")
if any(nums.count(n) > 1 for n in nums):
raise TieException
return max(nums)
Of course, we also don't need to know the count. This would be very inefficient for a large list. Instead we just need to check if any number is in the rest of the list after it. This will stop as soon as it finds a duplicate, indicating a "tie."
def max_nums(*nums):
if len(nums) == 0:
raise TypeError("max_nums requires at least one argument")
if any(x in nums[i+1:] for i, x in enumerate(nums)):
raise TieException
return max(nums)
The explanation is below:
def displaySortedNumbers(num1, num2, num3):
smallest = num1
if num2 < smallest:
smallest = num2
if num3 < smallest:
smallest = num3
return smallest
def main():
num1, num2, num3 = eval(input("Enter three numbers seperated by commas:"))
print("The numbers are,",displaySortedNumbers(num1, num2, num3))
main()
After the three numbers are entered, the smallest number prints out but the rest of the numbers do not follow. I need the numbers to print out from smallest to largest. I'm not sure what I did wrong.
Your function is only returning the one smallest number of the provided three, you may consider using a list and sorting it instead if that works for you.
def displaySortedNumbers(num1, num2, num3):
s = ""
for c in sorted([num1, num2, num3]):
s += " " + str(c)
return s
The sorted() function takes an iterable argument and returns it sorted by a key, however in this case, if you are just sorting it in increasing order, you do not need to input a key.
In your return statement there is only ´smallest´, not the other variables.
You can store the values in a list, sort it and then return that list, just like this
def displaySortedNumbers(num1, num2, num3):
list = [num1, num2, num3]
list.sort()
return list
In your return statement, you only return one of the three numbers, the one you deem the smallest. But your function is expected to return all three numbers sorted. I'm guessing you can't use the built-in sorted() function and so you need to program the sort manually. You can do a simple bubble sort on 3 numbers by changing your function to be the following:
def displaySortedNumbers(num1, num2, num3):
if num2 < num1:
num1, num2 = num2, num1
if num3 < num2:
num2, num3 = num3, num2
if num2 < num1:
num1, num2 = num2, num1
return num1, num2, num3
This will print all three numbers, properly sorted.
If you CAN use built-in functions, you could simply say:
def displaySortedNumbers(num1, num2, num3):
return sorted((num1, num2, num3))
Try to rewrite like this:
if smallest > num2:
smallest = num2
elif smallest > num3:
smallest = num3
I am trying to solve a question to generate a list of numbers from a given range by making each number passed through a set of rules to get that number added in the list. Also to find the maximum element from the list.
This is the actual question:
Write a python program which finds the maximum number from num1 to num2 (num2 inclusive) based on the following rules.
Always num1 should be less than num2
Consider each number from num1 to num2 (num2 inclusive). Populate the number
into a list, if the below conditions are satisfied
a)Sum of the digits of the number is a multiple of 3
b)Number has only two digits
c)Number is a multiple of 5
Display the maximum element from the list
In case of any invalid data or if the list is empty, display -1.
First of all, I am new to Python and not familiar to solve these type of complex problems. So I think I made a lot of silly mistakes.
def find_max(num1, num2):
max_num=-1
num_list=[] #list declared
if(num1<num2): #to check num1 < num2 as said in the question
for numbers in range(int(num1),int(num2)+1): #for numbers from the range
tot=0
count=0
while(numbers>0):
digit=numbers%10
tot=tot+digit #to generate sum of digits
numbers=numbers//10
count=count+1 #to count the number of digits
if(tot%3==0 and count==2 and numbers%5==0):
num_list.append(numbers) #to generate the list
else:
print(-1)
else:
print(-1)
max_num = max(num_list) #to find the maximum value in the list
return max_num
#Provide different values for num1 and num2 and test your program.
max_num=find_max(10,15)
print(max_num)
Results I am getting :
-1
-1
-1........
The mistake in your code is that in your 'while' loop, you're modifying the value which is being checked for the conditions. (lulian has explained this well.)
Actually, your code can be rewritten more simply. You have these requirements. (a) Sum of the digits of the number is a multiple of 3. (b) Number has only two digits (c) Number is a multiple of 5.
Requirements (a) and (c) can be combined into a single requirement: if you know middle school mathematics, (a) basically means that the number itself is divisible by 3, and (c) means that it is divisible by 5. Together, they mean that the number should be divisible by 3 times 5, i.e. 15. We can exploit this property.
Let us revisit the problem. Observe that each time invalid data is detected, I use a return statement.
def find_max(num1, num2):
# check for invalid data: 'num1' and 'num2' should be integers
if type(num1) != int or type(num2) != int:
return -1
# check if 'num1' is greater than 'num2'
if num1 > num2:
return -1
# initialize empty list
num_list = []
# find the nearest multiple of 15 to 'num1'
if num1 % 15 == 0:
nearest_multiple = num1
else:
nearest_multiple = num1 + 15 - num1 % 15
# scan through possible numbers from 'nearest_multiple' to 'num2'
for numbers in range(nearest_multiple, num2 + 1, 15):
if 10 <= numbers <= 99 or -99 <= numbers <= -10:
num_list.append(numbers)
# if no valid number was detected, the list will remain empty
if num_list == []:
return -1
return max(num_list)
Explanation:
First, locate the nearest multiple of 15 greater than or equal to num1. So, if num1 is 15, then nearest_multiple is also 15. But if num1 were 21, then nearest_multiple would be 30. (The formula used is pure math.)
Then, we iterate from nearest_multiple to num2 in jumps of 15. That way, we encounter only numbers which satisfy both (a) and (c). Then we check the number we encounter for condition (b).
Your function is not working like you want because you are using numbers for checking condition, but you're changing it in your code when you are making computations.
numbers = numbers // 10
So when you'll use it in if block, numbers will have a different value not the initial one.
For example with numbers = 15 at the start it will become:
numbers -> 15 -> 1 -> 0
Thus when you check numbers % 5 == 0 it will never pass and the if conditional will fail. Use a copy of the number and every thing will work fine.
Revisited code:
def function_name(num1,num2):
num_list=[] #list declared
if(num1<num2): #to check num1 < num2 as said in the question
for numbers in range(int(num1),int(num2)+1): #for numbers from the range
tot=0
count=0
copy = numbers
while(copy>0):
digit=copy%10
tot=tot+digit #to generate sum of digits
copy = copy//10
count = count+1 #to count the number of digits
if(tot%3==0 and count==2 and numbers%5==0):
num_list.append(numbers) #to generate the list
else:
print(-1)
else:
print(-1)
if num_list:#if the list is populates with some numbers
return max(num_list)
else: return "what you think is needed in case there aren't numbers" #None is a good choice equivalent to null in other programming languages
print(function_name(10,15))
My idea to implement your function
Not the best, but its shorter and more readable.
def function_name(num1,num2):
num_list=[] #list declared
if(num1<num2): #to check num1 < num2 as said in the question
for number in range(int(num1),int(num2)+1): #for numbers from the range
# for every char return its int and group all in a list
# [int(digit) for digit in str(number)]
tot = sum( [int(digit) for digit in str(number)])
#count how many char are that is like saying how many digits
count= len(str(number))
if(tot%3==0 and count==2 and number%5==0):
num_list.append(number) #to generate the list
else:
print(-1)
else:
print(-1)
if num_list:#if the list is populates with some numbers
return max(num_list)
else:
return "what you think is needed in case there aren't numbers" #None is a good choice equivalent to null in other programming languages
print("Max", function_name(10,15))
def find_max(num1, num2):
if (num1<num2):
max_num=-1
for i in range(num1,num2 + 1,1):
if (10 <= i <= 99 or -99 <= i <= -10):
j = i/10
k= i%10
if ((j+k)%3==0 and i%5 == 0):
max_num = i
# Write your logic here
return max_num
else:
return -1
#Provide different values for num1 and num2 and test your program.
max_num=find_max(-100,500)
print(max_num)
def find_max(num1, num2):
max_num=-1
num_list=[]
if(num1<num2):
for numbers in range(int(num1),int(num2)+1):
tot=0
count=0
while(numbers>0):
digit=numbers%10
tot=tot+digit
numbers=numbers//10
count=count+1
if(tot%3==0 and count==2 and numbers%5==0):
num_list.append(numbers)
else:
print(-1)
else:
print(-1)
max_num = max(num_list)
return max_num
max_num=find_max(10,15)
print(max_num)
So I am trying to teach myself python and I am having some problems accomplishing this task. I am trying to read in two integers from the keyboard, but the problem is that they can either be read in on the same line or on two different lines.
Example Inputs:
23 45
or
23
45
Each number should go to its own variable.
Im pretty sure I should make use of the strip/split functions, but what else am I missing? I just really dont know how to go about this... Thanks.
Here is what Im working with, but obviously this version takes the numbers one on each line.
def main():
num1 = int(input())
num2 = int(input())
numSum = num1 + num2
numProduct = num1 * num2
print("sum = ",numSum)
print("product = ",numProduct)
main()
the input terminates on new line (more percisely, the sys.stdin flushes on new line), so you get the entire line. To split it use:
inputs = input("Enter something").split() # read input and split it
print inputs
applying to your code, it would look like this:
# helper function to keep the code DRY
def get_numbers(message):
try:
# this is called list comprehension
return [int(x) for x in input(message).split()]
except:
# input can produce errors such as casting non-ints
print("Error while reading numbers")
return []
def main():
# 1: create the list - wait for at least two numbers
nums = []
while len(nums) < 2:
nums.extend(get_numbers("Enter numbers please: "))
# only keep two first numbers, this is called slicing
nums = nums[:2]
# summarize using the built-in standard 'sum' function
numSum = sum(nums)
numProduct = nums[0] * nums[1]
print("sum = ",numSum)
print("product = ",numProduct)
main()
Notes on what's used here:
You can use list comprehension to construct lists from iterable objects.
You can use sum from the standard library functions to summarize lists.
You can slice lists if you only want a part of the list.
Here I have modified your code.
def main():
num1 = int(input("Enter first number : "))
num2 = int(input("\nEnter second number : "))
if(num1<=0 or num2<=0):
print("Enter valid number")
else:
numSum = num1 + num2
numProduct = num1 * num2
print("sum of the given numbers is = ",numSum)
print("product of the given numbers is = ",numProduct)
main()
If you enter invalid number it prints message Enter valid number.