1

Is there something I'm missing here? Kind of stumped on this problem. Hints are greatly appreciated!

Here is what my code is supposed to do:

You are given a string of letters and an array of numbers. The numbers indicate positions of letters that must be removed, in order, starting from the beginning of the array. After each removal the size of the string decreases (there is no empty space). Return the only letter left.

Example:

let str = "zbk", arr = [0, 1]
    str = "bk", arr = [1]
    str = "b", arr = []
    return 'b'

Notes

  • The given string will never be empty.
  • The length of the array is always one less than the length of the string.
  • All numbers are valid.
  • There can be duplicate letters and numbers.

Here is my code:

def last_survivor(letters, coords): 
    list1 = list(letters)
    for x in coords:
        for i in list1:
            if list1.index(i) == x:
                list1.remove(i)
    return print("".join(list1))
        

These function inputs work just fine and return expected output

last_survivor('abc', [1, 1])
last_survivor('kbc', [0, 1])    
last_survivor('zbk', [2, 1])
last_survivor('c', [])
last_survivor("abcdef", [1,2,1,1])

This very long function input does not return the desired output, 'b'

last_survivor('foiflxtpicahhkqjswjuyhmypkrdbwnmwbrrvdycqespfvdviucjoyvskltqaqirtjqulprjjoaiagobpftywabqjdmiofpsr', [8, 59, 52, 93, 21, 40, 88, 85, 59, 10, 82, 18, 74, 59, 51, 47, 75, 49, 23, 56, 1, 33, 39, 33, 34, 44, 25, 0, 51, 25, 36, 32, 57, 10, 57, 12, 51, 55, 24, 55, 31, 49, 6, 15, 10, 48, 27, 29, 38, 30, 35, 42, 23, 32, 9, 39, 39, 36, 8, 29, 2, 33, 14, 3, 13, 25, 9, 25, 18, 10, 1, 2, 20, 8, 2, 11, 5, 7, 0, 10, 10, 8, 12, 3, 5, 1, 7, 7, 5, 1, 4, 0, 4, 0, 0, 1])
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Nik
  • 11
  • 1
  • 1
    `list1.index(i)` returns the index of the first occurrence of `i`. It won't do what you want if there are duplicate values in the list. – Barmar May 21 '21 at 00:29
  • The problem has nothing to do with the length of the input. Your code doesn't work when there are duplicate letters. – Barmar May 21 '21 at 00:30
  • And the instructions made it very clear about this: **There can be duplicate letters and numbers.** – Barmar May 21 '21 at 00:31
  • See also: https://stackoverflow.com/questions/6260089/strange-result-when-removing-item-from-a-list-while-iterating-over-it – Silvio Mayolo May 21 '21 at 00:37

3 Answers3

1

list1.index(i) and list1.remove(i) find and remove the first occurrence of i in the list. This may not be the same index as x if there are duplicate letters in the string.

There's no need to use index() or remove(). You can remove an element by indext using the pop() method.

def last_survivor(letters, coords): 
    list1 = list(letters)
    for x in coords:
        list1.pop(x)
    return list1[0]

Also, your function is supposed to return the result, not print it. return print(...) makes the function return None, because print() doesn't return what it prints.

And since the conditions say that there will always be just one element left, you don't need to use join(), you can just return that element.

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

I think what you want is something like this, I just added a check to show you if you've given a wrong indeed in that long array. However it's better to do it with try and except method

def last_survivor(letters, coords): 
    list1 = list(letters)
    for x in coords:
        if (x < Len(list1)):
            list1.pop(x)
        else:
            print('provided index does not exist')
    return list1[0]
Sina Meftah
  • 133
  • 9
0

You can use slicing and string concatenation to save all the string other than the single character at the edge of the two slices:

def last_survivor(s, cord):
    for e in cord:
        s=s[:e]+s[(e+1):]
    return s

Since it is slicing vs pop, there is no error if the coordinate is out of range or there are too many elements in the list of coordinates.

dawg
  • 98,345
  • 23
  • 131
  • 206