How to determine the maximum number from a list of numbers?

Almost all the discussion here uses a max() not taught up to this point in the course.
So I went ahead trying to figure it out without it.
I managed, but in a slightly different way than the solution provided in the exercise:

def max_num(num1, num2, num3):
  if num1 == num2 or num1 == num3:
    return "It's a tie!"
  elif num2 == num3:
    return "It's a tie!"
  if num1 > num2 and num1 > num3:
    return num1
  elif num2 > num1 and num2 > num3:
    return num2
  elif num3 > num1 and num3 > num2:
    return num3

While the solution offered by the exercise is:

def max_num(num1, num2, num3):
  if num1 > num2 and num1 > num3:
    return num1
  elif num2 > num1 and num2 > num3:
    return num2
  elif num3 > num1 and num3 > num2:
    return num3
  else:
    return "It's a tie!"

So, what I don’t understand is the thinking, the logic behind concluding that a simple:

else:
    return "It's a tie!"

at the end of the code would provide the answer to

If any of two numbers tie as the largest, you should return "It's a tie!" .

It works, but I just can’t figure out why or more importantly, how one could come up with that?
Why is it so obvious that ANY other result (else) would satisfy the condition to return “it’s a tie!”. Obviously clever but I don’t get it.

Hello, @chumbolito.

Consider an example with one less value. If I have 2 integers, a & b, and a isn’t greater than b, and b isn’t greater than a, what possible relationships between the integers remain? Only one. They must be equal. Same thing here, but with one additional value to consider.

Also, we don’t really need the else.

def max_num(num1, num2, num3):
  if num1 > num2 and num1 > num3:
    return num1
  elif num2 > num1 and num2 > num3:
    return num2
  elif num3 > num1 and num3 > num2:
    return num3

  return "It's a tie!" #this will only be reached if none of the above 'return' statements are executed
2 Likes

thanks! That’s exactly the kind of explanation I was looking for. Clear, concise and logical!
That really helped, I got it :wink:

1 Like
def max_num(num1, num2, num3):
#compare each number and check for instances where two numbers are equal to each other but greater than the third number.
  if (num1 == num2 and num1 > num3) or (num2 == num3 and num2 > num1) or (num1 == num3 and num1 > num2):
    return "It's a tie!"

#if there are no instances of a tie then just return the greatest number
  else: 
    return max(num1, num2, num3)

Edge case: What if all 3 numbers are equal? The prompt requests that if any two numbers tie as the largest return “It’s a tie” but what should the function return when there is no “greatest number”. The code I pasted above passes codeacademy’s test cases and in the case where all three numbers are equal (10,10,10) it returns (10). One could write an exception before the first “if” statement to handle a three way “tie”:

def max_num(num1, num2, num3):
  if (num1 == num2 and num1 == num3):
    return "There is no greatest number here, they're all equal!"

#compare each number and check for instances where two numbers are equal to each other but greater than the third number.
  elif (num1 == num2 and num1 > num3) or (num2 == num3 and num2 > num1) or (num1 == num3 and num1 > num2):
    return "It's a tie!"

#if there are no instances of a tie then just return the greatest number
  else: 
    return max(num1, num2, num3)

I’m almost certain there is a better way to do this.

I did this another variation with checking for repetition and max value. For 3 same numbers this should also work

def max_num(num1,num2,num3):
  c = max(num1,num2,num3)
  if num1==num2==c or num2==num3==c or num1==num3==c:
    return "It's a tie!"
  else:
    return c

Can’t see this one being posted here yet, but this should work

def max_num(num1, num2, num3):
if [num1, num2, num3].count(max(num1, num2, num3)) >= 2:
return “It’s a tie!”
return max(num1, num2, num3)

Two approaches
Before you start this, there are 2 ways to approach this and one is more expensive than the other from a compute transaction perspective.

Approach 1 - 3 comparisons - Not ideal but probably the first you will think of
You can easily compare 1v2, 1v3 and then 2v3 and then decide on the result somehow.

Attention to detail
However the question says that if there is a high number, just show it - notice how it doesn’t ask you to output whether the highest number was num1, num2 or num3?

So what?
This is important as interviewers like Amazon / Google will grill you on why this is the approach you took. You should always be thinking about optimization, compute cost and possibility of parallelization.

Approach 2 - 2 comparisons only
I believe there is a 2nd approach which is less compute cost as it iterates through your 3 numbers, it only remembers the highest number seen so far, and if it sees a higher one, it will remember the previous top number in a different variable and replace the highest number seen with the new winner.
You now only need to run 2 comparisons instead of 3.

To other posters posting solutions
The user at this stage of the course has not been introduced to arrays, max function, for loops, etc, so please try add basic answers to assist them.

I have started learning python today and never done it before. I could improve it further to add data validation and exception handling, but this answers the question. But during QA / unit testing, you should be entering symbols and letters into your function and make sure it handles it all correctly.

Here is my take on the code which seems to pass all the basic tests…

# Write your max_num function here:
def max_num(num1, num2, num3):
  #index 0 check (we have only seen 1 number so far so this is the top number we have seen so far)
  top_number = num1
  medium_number = 0
  
  #index 1 compare  (compare num2 with highest number seen so far, if num2 is MTE, relegate the old top number we saw to medium_number, replace top_number with num2
  if num2 >=top_number:
    medium_number = top_number
    top_number = num2
    
  #index 2 compare  (compare num3 with highest number seen so far, if num3 is MTE, relegate the old top number we saw to medium_number, replace top_number with num3
  if num3 >=top_number:
    medium_number = top_number
    top_number = num3
  
  #time to decide on the result, there are only be 2 results, a tie or a winner.
  if (top_number==medium_number):
    message = "It's a tie!"
  else:
    message = top_number
  
  # return the final message
  return message
  
  

# Uncomment these function calls to test your max_num function:
print(max_num(-10, 0, 10))
# should print 10
print(max_num(-10, 5, -30))
# should print 5
print(max_num(-5, -10, -10))
# should print -5
print(max_num(2, 3, 3))
# should print "It's a tie!"

I did it like this

def max_num (num1, num2, num3):
  num = (num1, num2, num3)
  
  if num1 == num2 or num2 == num3 or num3 == num1:
    return "It's a tie!"
  
  elif num == (num1, num2, num3):
    return max(num)

I used this:

def max_num(num1, num2, num3):
    list1 = [num1, num2, num3]
    sorted_list = sorted(list1)
    if sorted_list[-2] == sorted_list[-1]:
        return "It's a tie!"
    else:
        return max(list1)

Thanks for this one! I see a bunch of people using the max(), but I had no idea it even existed… Had something similar to yours where I compared num3 > num2 > num1 – that unfortunately failed on the negative number test. :frowning_face: Now I see my inefficiencies.