-5

I've tried to look for an answer last night and a little this morning, but had no luck. For homework, we have been asked to go through a list, and return the longest run of consecutive numbers. I've been working on this code and it has only been comparing the numbers (if it works correctly) with the first number. I need to know the len(consecutive increases).

    #!/usr/bin/python3


import sys
def fOpen(fname):
        try:
                fd = open(fname,"r")
        except:
                print("Couldn't open file.")
                sys.exit(0)
        all = fd.read().splitlines()
        fd.close()
        return all

words = fOpen(sys.argv[1])



   current = []
   lastc = []


for x in words:
        if len(current) == 0:                                           #Add the first number
                current.append(int(x))
        elif len(current) == 1:                                         #Check first number < next number
                if current[0] < int(x):
                        current.append(int(x))
                else:                                                   #elif current[0] >= int(x):
                        if len(current) >= len(lastc):
                                lastc = current
                        current[:] = []
                        current.append(int(x))
        elif len(current) >= 2:
                if current[-1] < int(x):
                        current.append(int(x))
                else:                                                   #elif current[-1] >= int(x):
                        if len(current) >= len(lastc):
                                lastc = current
                        elif len(current) < len(lastc):
                                current[:] = []
                        current[:] = []
                        current.append(int(x))

print(lastc)

The print statements are just got myself to be able to trace through and will be removed later. Thank you in advance.

Cole Maclean
  • 5,627
  • 25
  • 37
Seth Kania
  • 251
  • 3
  • 15
  • are these words, or are these numbers? – moooeeeep Feb 12 '12 at 19:37
  • SO...where students go to have professionals do their homework for free. Too much of that going around. For this code, broken in so many ways, learn what break does, look at enumerate...start from scratch...try to learn BEFORE asking for help. Sorry Seth, I'll go away now. – Phil Cooper Feb 12 '12 at 19:42
  • 1
    -1 You say "consecutive increases" in your title, but "consecutive numbers" (very ambiguous) in the question body, and "Find the 10 largest integers" in a code comment. Make up your mind what you want, and edit your question accordingly. – John Machin Feb 12 '12 at 20:50
  • Edited. I had just copied the code from the previous problem I finished. Sorry about the ambiguity. – Seth Kania Feb 12 '12 at 22:05
  • All you have edited is the obviously-wrong code comment. You have not explained what you mean by "consecutive numbers". Your not-very-clear and redundancy-replete code appears to mean "sub-sequence that is monotonically increasing". At least one answer has taken it to mean that the increases (differences) are limited to exactly `1.0`. – John Machin Feb 13 '12 at 01:47
  • John, I'm trying to figure out the longest run of numbers that increase consecutively. I guess I don't follow how the code is redundant. And yes, increases are limited to 1.0, there are no decimals in the files. – Seth Kania Feb 13 '12 at 02:28
  • Can the increases be 2 or 3 or ...? As I said, your code allows any positive number as an "increase". – John Machin Feb 13 '12 at 09:55

3 Answers3

2

There are 4 things I'd like to mention. Here's some code and its output:

def srk_func(words):
    current = []
    lastc = []
    for x in words:
        if len(current) == 0: 
                current.append(int(x))
        elif len(current) == 1:
                if current[0] < int(x):
                        current.append(int(x))
                else:          
                        if len(current) >= len(lastc):
                                lastc = current
                        current[:] = []
                        current.append(int(x))
        elif len(current) >= 2:
                if current[-1] < int(x):
                        current.append(int(x))
                else:          
                        if len(current) >= len(lastc):
                                lastc = current
                        elif len(current) < len(lastc):
                                current[:] = []
                        current[:] = []
                        current.append(int(x))
    return lastc

def jm_func(words):
    current = []
    lastc = []
    for w in words:
        x = int(w)
        if not current:
            # this happens only on the first element
            current = [x]
            continue
        if x > current[-1]:
            current.append(x)
        else:
            # no increase, so current is complete
            if len(current) >= len(lastc):
                lastc = current
            current = [x]
    # end of input, so current is complete
    if len(current) >= len(lastc):
        lastc = current
    return lastc

tests = """\
    1
    1 5
    5 1
    1 5 7
    7 5 1
    1 5 7 0
    1 5 7 0 3
    1 5 7 0 2 4 6 8
    1 3 5 7 9 11 0 2
    """

for test in tests.splitlines():
    wds = test.split()
    print wds
    print srk_func(wds)
    print jm_func(wds)
    print

8<--------------------------------------------------

['1']
[]
[1]

['1', '5']
[]
[1, 5]

['5', '1']
[1]
[1]

['1', '5', '7']
[]
[1, 5, 7]

['7', '5', '1']
[1]
[1]

['1', '5', '7', '0']
[0]
[1, 5, 7]

['1', '5', '7', '0', '3']
[0, 3]
[1, 5, 7]

['1', '5', '7', '0', '2', '4', '6', '8']
[0, 2, 4, 6, 8]
[0, 2, 4, 6, 8]

['1', '3', '5', '7', '9', '11', '0', '2']
[0, 2]
[1, 3, 5, 7, 9, 11]

[]
[]
[]

Topic 1: Test your code.

Topic 2: Redundancy: Your code for len(current) == 1 is functionally identical to your code for len >= 2, and the latter is bloated by having the following unnecessary two lines:

  elif len(current) < len(lastc):
        current[:] = []

You can combine the two cases; see my version.

Topic 3: It often happens in this kind of algorithm where you are processing input and keeping some "state" (in this case, current and lastc) that you can't immediately pack up and go home when you reach the end of the input; you need to do something with that state.

Topic 4: This is going to get technical, but it's a common trap for new Python players.

>>> current = [1, 2, 3, 4, 5]
>>> lastc = current # lastc and current refer to THE SAME LIST; no copying!
>>> print current
[1, 2, 3, 4, 5]
>>> print lastc
[1, 2, 3, 4, 5]
>>> current[:] = [] # The list to which current refers is cleared
>>> print current
[]
>>> print lastc # lastc refers to the same list
[]

It's better to just assign the name current to a new list; see my code.

Topic 5 (bonus extra): Consider using 4-space indentation, not 8. Causing both the horizontal and vertical scroll-bars to appear in an SO question or answer == FAIL :-)

John Machin
  • 81,303
  • 11
  • 141
  • 189
  • Thanks for your response John. I didn't realize when I had posted the original code that I copied from PUTTY. Thank you for the tips, however - the `len(current) == 1` was put in because when I would try to reference the last number in the list, with `[-1]` it was giving me an error. Also, comparing `len(current) > len(lastc)` was incorrectly assigning the list of current to last. After inserting multiple print statements, I found that `long_run = max(len(currnet),long_run)` worked much easier. Topic 4 - Wow John, if you hadn't explicitly put that - I would have never known. – Seth Kania Feb 13 '12 at 14:20
0

You compare just to the first number, because you have too many loops nested. Instead, you should need to go through the list only once.

Start with an empty last_best_run and this_run as being a list that you append the next number if the criterion is met, and that you restart when the criterion is not met. Make sure that you convert the numbers to a number-type, i.e. float or int to avoid undesired string comparisons.

Then you simply assign this_run to last_best_run when its length is larger.

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • Thanks for responding. That would work, but I forgot to mention that this program is to run over up 10 million numbers. So running through that many times would be problematic. -Ignore that, I read your answer incorrectly. – Seth Kania Feb 12 '12 at 19:38
  • It might help to try doing this task by hand, using a string of random numbers like this: 1 4 2 8 2 5 7 9 3 4 3 6 8 ... I think you'll find that moooeeep is correct and you can identify runs in a single pass through the list without backtracking. – Russell Zahniser Feb 12 '12 at 19:40
  • Well, with this method, I've got it almost - but how can I empty a list? – Seth Kania Feb 12 '12 at 19:52
  • @SethRainerKania: please see [this post](http://stackoverflow.com/a/1400622/1025391). You might also need to have a look on [this](http://docs.python.org/tutorial/introduction.html), especially section 3.1.4. – moooeeeep Feb 12 '12 at 19:56
-1

Hint #1: Look at what happens to your list of numbers, if you were to subtract an increasing sequence of numbers from it. For example:

If words = [10,11,12,5,6,7,8,9,1,0], imagine subtracting [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] from words:

  10 11 12 5 6 7 8 9  1  0
-  0  1  2 3 4 5 6 7  8  9
  -------------------------
  10 10 10 2 2 2 2 2 -7 -9

Hint #2: itertools.groupby can group sequences of equal items together.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • Thanks for the reponse. Not sure I can follow hint #1 (this is only my second semester as CS), and for hint #2 - while that may work, I'm almost positive the professor wants us to make our own methods. Thanks again! – Seth Kania Feb 12 '12 at 19:47
  • -1 I'm not sure about hint 1 either. This appears to "work" only if increases are limited to being 1. Include 10 12 14 5 6 8 11 15 20 26 in your explanation. – John Machin Feb 12 '12 at 20:56