HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Returning largest product of longest subsequence between min and max

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
subsequenceproductlargestminreturningbetweenmaxandlongest

Problem

This function returns the largest product of all elements of a list between the leftmost and rightmost min and max elements. Is there more readable and maybe compact way to rewrite the elif chain in this code:

from operator import mul
from functools import reduce

prod = lambda iterable: reduce(mul, iterable, 1)

def prod_between_min_and_max(arr):
    l_min, r_max = arr.index(min(arr)), len(arr)-1 - arr[::-1].index(max(arr))
    l_max, r_min = arr.index(max(arr)), len(arr)-1 - arr[::-1].index(min(arr))
    if len(range(l_min, r_max+1)) > len(range(l_max, r_min+1)):
        sl = slice(l_min, r_max+1)
    elif len(range(l_min, r_max+1)) = prod(arr[l_max:r_min+1]):
        sl = slice(l_min, r_max+1) 
    else:
        sl = slice(l_max, r_min+1)
    return prod(arr[sl])


than this:

from operator import mul
from functools import reduce

cmp = lambda a, b: (a > b) - (a = prod(arr[l_max:r_min+1])
        ], 
        slice(l_min, r_max+1), 
        slice(l_max, r_min+1)
    ][
        cmp(len(range(l_min, r_max+1)), len(range(l_max, r_min+1)))
    ]
    return prod(arr[sl])


Note: The code works in both Python 2 and Python 3.

Solution

The second example is terrible, don't use it.

You assign sl to either (l_min, r_max) or (l_max, r_min), and so you just need to change your ifs to become one if and an else.

First off len(range(l_min, r_max+1)) is the same as r_max+1 - l_min, and there's no need for the +1 if both sides have it. So your first if could become: r_max - l_min > r_min - l_max.

To merge the first and third, you should check it's the first, or explicitly check it's not the second and is the third. And so you can get:

def prod_between_min_and_max(arr):
    l_min = arr.index(min(arr))
    l_max = arr.index(max(arr))
    r_max = len(arr)-1 - arr[::-1].index(max(arr))
    r_min = len(arr)-1 - arr[::-1].index(min(arr))
    if (r_max - l_min > r_min - l_max
      or (r_max - l_min == r_min - l_max
          and prod(arr[l_min:r_max+1]) >= prod(arr[l_max:r_min+1]))):
        sl = (l_min, r_max)
    else:
        sl = (l_max, r_min)
    return prod(arr[slice(sl[0], sl[1]+1)])


This reminds me of FizzBuzz, as there doesn't seem to be a 'nice' solution.

Code Snippets

def prod_between_min_and_max(arr):
    l_min = arr.index(min(arr))
    l_max = arr.index(max(arr))
    r_max = len(arr)-1 - arr[::-1].index(max(arr))
    r_min = len(arr)-1 - arr[::-1].index(min(arr))
    if (r_max - l_min > r_min - l_max
      or (r_max - l_min == r_min - l_max
          and prod(arr[l_min:r_max+1]) >= prod(arr[l_max:r_min+1]))):
        sl = (l_min, r_max)
    else:
        sl = (l_max, r_min)
    return prod(arr[slice(sl[0], sl[1]+1)])

Context

StackExchange Code Review Q#150242, answer score: 4

Revisions (0)

No revisions yet.