0

I'm currently working on a Codeforces problem (I'm not in a middle of a contest so it's not cheating!) and I can't get the string comparison part correctly for some reason.

The gist of the problem is that, given an array of strings, I have to calculate how many columns I have to remove to make the strings lexicographically in order. So for the second test case scenario, we're given

case
care
test
code

And the answer should be 2, with the first and third columns being removed and resulting in

ae
ae
et
oe

Attached below is my code:

#some code to take the input and convert it to a list s
begin = 0
out_list = [[] for i in range(n)]
while begin < m: #m is the length of each string
    out_copy = out_list[:]
    for i in range(n): #n is the number of strings
        out_copy[i].append(s[i][begin])
    fine = True
    for i in range(1,n):
        if ''.join(out_copy[i]) < ''.join(out_copy[i-1]):
            fine = False
    if fine:
        out_list = out_copy
    begin += 1
#some code to output the result

''.join(list) is supposed to give me a string that is a concatenation of all the characters in the list, and the < operator should be enough of a comparator for the computer to return False for the first column since c is less than t... but something must not be quite right here. What's going on?

2012ssohn
  • 159
  • 8

1 Answers1

1

With this line

out_copy = out_list[:]

you make a shallow copy of out_list. Thus, out_list[i] and out_copy[i] refer to the same object.

Notice, that you mutate out_copy[i] on each iteration, so out_list[i] is changed on each iteration regardless of fine value. You can confirm it by adding print out_list inside the loop

begin = 0
out_list = [[] for i in range(n)]
while begin < m: #m is the length of each string
    print out_list
    out_copy = out_list[:]
    .....
    .....

outputs

[[], [], [], []]
[['c'], ['c'], ['t'], ['c']]
[['c', 'a'], ['c', 'a'], ['t', 'e'], ['c', 'o']]
[['c', 'a', 's'], ['c', 'a', 'r'], ['t', 'e', 's'], ['c', 'o', 'd']]

Make a deep copy instead.

import copy
begin = 0
out_list = [[] for i in range(n)]
while begin < m: #m is the length of each string
    out_copy = copy.deepcopy(out_list)
    .....
    .....
print out_list

produces correct result

[['a', 'e'], ['a', 'e'], ['e', 't'], ['o', 'e']]
Konstantin
  • 24,271
  • 5
  • 48
  • 65