0

I am trying to make a program that finds the maximum integer of a list, and the margin between the highest number and the second highest number. I want it to return these tuple values:

    >>>max_margin([5,6,4,3])
    (6, 1)

    >>>max_margin([8, -2, 8, -3])
    (8, 0)

    >>>maxmargin([2])
    (2, None)

    >>>maxmargin([])
    (None, None)

I have made code which accomplishes this, but It's not the best way to go about it. Here it is:

    def max_margin(int_list):

        if not int_list:
            return None, None

        else:
            maxnum = nextval = int_list[0]
            bymargin = None

            for i in intlist:

                if i > nextval:
                    nextval = i

                if i > maxnum:
                    tmp = nextval
                    nextval = maxnum
                    maxnum = tmp

                    bymargin = maxnum - nextval

                if maxnum == i and nextval == i:
                    maxnum = i
                    nextval = i
                    bymargin = maxnum - nextval

                if len(int_list) <= 1:
                    maxnum = maxnum
                    bymargin = None

        return maxnum, bymargin

Is there a better way to write this?

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • 1
    I'm voting to close this question as off-topic because it belongs on CodeReview.stackexchange.com – Vincent Savard Apr 07 '16 at 15:02
  • You can remove the first `else` and thus save an indentation level – ForceBru Apr 07 '16 at 15:03
  • @VincentSavard any ideas how to actually mark the question as off-topic? It seems to only allow the 5 most common sites for migration, so I wasn't sure what best to do (I agree, this should be on codereview). – dwanderson Apr 07 '16 at 15:38
  • @dwanderson: As far as I know, it's not possible to migrate it ourselves and we need a moderator to do it. – Vincent Savard Apr 07 '16 at 15:39
  • Yeah, but we can't even appropriately mark *where* it should be migrated, because it only allows 5 pre-determined sites. So, marking as off-topic now feels confusing. Probably a quesiton for (or already on) meta). – dwanderson Apr 07 '16 at 15:40

3 Answers3

1

You can sort the list first to make it easy.

In [1]: def max_margin(int_list):
   ...:     args = sorted(int_list)
   ...:     try:
   ...:         return (args[-1], args[-1] - args[-2])
   ...:     except IndexError:
   ...:         try:
   ...:             return (args[-1], None)
   ...:         except IndexError:
   ...:             return (None, None)
   ...:         

In [2]: maxmargin([5,6,4,3])
Out[2]: (6, 1)

In [3]: maxmargin([8, -2, 8, -3])
Out[3]: (8, 0)

In [5]: maxmargin([2])
Out[5]: (2, None)

In [6]: maxmargin([])
Out[6]: (None, None)
Muhammad Tahir
  • 5,006
  • 1
  • 19
  • 36
1

A rather straightforward O(Nlog(N)) solution could involve just sorting the list.

def maxmargin(my_list):
    largest, secondlargest = sorted(my_list,reverse=True)[:2]
    return largest, largest - secondlargest

Else if runtime is of great importance you could have an O(N) solution by iterating only once, like so (credit to this solution for inspiration for second largest)

def max_margin(my_list):
    count = 0
    largest = second_largest = float('-inf')
    for x in my_list:
        count += 1
        if x > second_largest:
            if x >= largest:
                largest, second_largest = x, largest
            else:
                second_largest = x
    return largest, largest - second_largest if count >= 2 else None
Community
  • 1
  • 1
miradulo
  • 28,857
  • 6
  • 80
  • 93
0

You can do like this, int_list2 is not needed if you don't care about what happens to int_list.

def max_margin(int_list):
    if len(int_list)==0:
        return None,None
    if len(int_list)==1:  
        return int_list[0],None  
    max_val = max(int_list)
    int_list2 = list(int_list)
    int_list2.remove(max_val)
    max_val2 = max(int_list2)
    return max_val,max_val-max_val2
Vince
  • 336
  • 1
  • 11