0

I am doing a coding exercise: Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.

So I wrote this code:

def almostIncreasingSequence(sequence):
    first_list, second_list = sequence, sequence
    for i in range(len(sequence)-1):
        if sequence[i] >= sequence[i+1]:
            first_list.remove(sequence[i])
            second_list.remove(sequence[i+1])
            break

    if first_list == sorted(set(first_list)) or second_list == sorted(set(second_list)):
        return True
    else:
        return False

Now this code seems to work on most sequences but this one in particular raises an error:

print almostIncreasingSequence([1,3,2])

The error is as following:

Traceback (most recent call last):
  file.py3 on line ?, in getUserOutputs
    userOutput = _runsppge(testInputs[i])
  file.py3 on line ?, in _runsppge
    return almostIncreasingSequence(*_fArgs_lujxeukjlbwc)
  file.py3 on line 7, in almostIncreasingSequence
    second_list.remove(sequence[i+1])
IndexError: list index out of range

I just dont understand how the list index could possibly be out of range.. Anyone got a clue?

martineau
  • 119,623
  • 25
  • 170
  • 301
Bartek Spitza
  • 305
  • 2
  • 15
  • 3
    `first_list, second_list = sequence, sequence` doesn't create any new lists. `first_list`, `second_list`, and `sequence` all refer to the exact same list object after this line. – user2357112 Jun 06 '17 at 18:00
  • 1
    Have a [quick guide](https://nedbatchelder.com/text/names.html) to how Python variables and assignment work. – user2357112 Jun 06 '17 at 18:01
  • possible tips https://stackoverflow.com/questions/43017251/solve-almostincreasingsequence-codefights – Papouche Guinslyzinho Jun 06 '17 at 18:23

2 Answers2

0

Since you are removing items from the same list which you are iterating on

for i in range(len(sequence)-1):
    if sequence[i] >= sequence[i+1]:
        first_list.remove(sequence[i])     #  <-- removing item
        second_list.remove(sequence[i+1])  #  <-- removing item
        break

And, as mentioned in the comments, first_list, second_list = sequence, sequence doesn't create any new lists. first_list, second_list, and sequence all refer to the exact same list object after that line.

EDITED

The list after the first removal (first_list.remove(sequence[i])), has one less element, hence if the i+1 in on the edge at that moment, it would get out of bound.

Think of a list like [1, 2, 3, 5, 4]. The if statement is triggered when i is at the element 5 (i is 3), then the first removal (first_list.remove(sequence[i])) takes place, after that statement, list has 4 elements [1, 2, 3, 4], and the next line tries to access the element (element 4) at i+1 (second_list.remove(sequence[i+1])), hence it gets (i is 4) out of bound.

Haris
  • 12,120
  • 6
  • 43
  • 70
0
> c:\users\jeffrey\documents\github\wadi\example.py(4)almostIncreasingSequence()
      3     for i in range(len(sequence)-1):
----> 4         if sequence[i] >= sequence[i+1]:
      5             first_list.remove(sequence[i])

ipdb> next
> c:\users\jeffrey\documents\github\wadi\example.py(5)almostIncreasingSequence()
      4         if sequence[i] >= sequence[i+1]:
----> 5             first_list.remove(sequence[i])
      6             second_list.remove(sequence[i+1])

ipdb> first_list
[1, 3, 2]
ipdb> second_list
[1, 3, 2]
ipdb> next
> c:\users\jeffrey\documents\github\wadi\example.py(6)almostIncreasingSequence()
      5             first_list.remove(sequence[i])
----> 6             second_list.remove(sequence[i+1])
      7             break

ipdb> first_list
[1, 2]
ipdb> second_list
[1, 2]
ipdb>

Even if I didn't execute this line second_list.remove(sequence[i+1]), because first_list and second_list point to the same location. In other words we can say that one is an alias of the other. So that if one can change then second_list get change also.

Papouche Guinslyzinho
  • 5,277
  • 14
  • 58
  • 101