Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I determine if the numbers in a list initially increase (or stay the same) and then decrease (or stay the same) with Python?

Tags:

python

For example, the digits of 123431 and 4577852 increase and then decrease. I wrote a code that breaks the numbers into a list and is able to tell if all of the digits increase or if all of the digits decrease, but I don't know how to check for digits increasing then decreasing. How do I extend this?

x = int(input("Please enter a number: "))
y = [int(d) for d in str(x)]
def isDecreasing(y):
    for i in range(len(y) - 1):
        if y[i] < y[i + 1]:
            return False
        return True
if isDecreasing(y) == True or sorted(y) == y:
    print("Yes")
like image 513
Matt Avatar asked Apr 24 '18 23:04

Matt


2 Answers

Find the maximum element. Break the list into two pieces at that location. Check that the first piece is increasing, the second decreasing.

  • For your second example, 4577852, you find the largest element, 8.
  • Break the list in two: 4577 and 852 (the 8 can go in either list, both, or neither).
  • Check that 4577 is increasing (okay) and 852 is decreasing (also okay).

Is that enough to get you to a solution?

like image 88
Prune Avatar answered Sep 26 '22 11:09

Prune


Seems like a good opportunity to learn about using itertools and generator pipelines. First we make a few simple, decoupled, and reusable components:

from itertools import tee, groupby

def digits(n):
    """420 -> 4, 2, 0"""
    for char in str(n):
        yield int(char)

def pairwise(iterable):
    """s -> (s0,s1), (s1,s2), (s2, s3), ..."""
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

def deltas(pairs):
    """2 5 3 4 -> 3, -2, 1"""
    for left, right in pairs:
        yield right - left

def directions(deltas):
    """3 2 2 5 6 -> -1, 0, 1, 1"""
    for delta in deltas:
        yield -1 if delta < 0 else +1 if delta > 0 else 0

def deduper(directions):
    """3 2 2 5 6 2 2 2 -> 3, 2, 5, 6, 2"""
    for key, group in groupby(directions):
        yield key

Then we put the pieces together to solve the wider problem of detecting an "increasing then decreasing number":

from itertools import zip_longest

def is_inc_dec(stream, expected=(+1, -1)):
    stream = pairwise(stream)
    stream = deltas(stream)
    stream = directions(stream)
    stream = deduper(stream)
    for actual, expected in zip_longest(stream, expected):
        if actual != expected or actual is None or expected is None:
            return False
    else:
        return True

Usage is like this:

>>> stream = digits(123431)
>>> is_inc_dec(stream)
True

This solution will short-circuit correctly for a number like:

121111111111111111111111111111111111111111111111111...2

I've addressed only the "strictly increasing, and then strictly decreasing" number case. Since this sounds like it might be your homework, I'll leave it as an exercise for you to adapt the code for the "non-decreasing and then non-increasing" case which is mentioned in the question title.

like image 28
wim Avatar answered Sep 26 '22 11:09

wim