0

It's a function to count inversion in a list and return the count.

def count_inversion(sequence):
    count = 0

    def merge_count_inversion(L):
        if len(L) > 1:
            # split them.
            mid = len(L) // 2
            leftL = L[:mid]
            rightL = L[mid:]

            merge_count_inversion(leftL)
            merge_count_inversion(rightL)

            # merge them.
            i = j = k = 0
            while i < len(leftL) and j < len(rightL):
                if leftL[i] < rightL[j]:
                    L[k] = leftL[i]
                    i += 1
                else:# no equal situation.
                    L[k] = rightL[j]
                    j += 1
                    count+=j
                k += 1
            while i < len(leftL):#all right is inversion.
                count+=j
                L[k] = leftL[i]
                i += 1
                k += 1
            while j < len(rightL):
                L[k] = rightL[j]
                j += 1
                k += 1

    merge_count_inversion(list(sequence))

    return count

I use a enclosed count and I hope it can save the total number for all merge procession. However, it will be a local variable.

UnboundLocalError: local variable 'count' referenced before assignment

I think I lose some concepts of recursion and the variable scope of python. Please tell me where I am wrong and how to fix it?

Thank you in advance.

ljy
  • 143
  • 1
  • 10
  • 1
    I think you are looking for the `nonlocal` keyword. add `nonlocal count` at the top of `merge_count_inversion`. http://stackoverflow.com/questions/8934772/assigning-to-variable-from-parent-function-local-variable-referenced-before-as – rtemperv May 17 '16 at 09:24

1 Answers1

1

The message means that count isn't a local variable of merge_count_inversion, where you have used count += j. You should move count = 0 in the function merge_count_inversion.

def count_inversion(sequence):

    def merge_count_inversion(L):
        count = 0
        if len(L) > 1:
            # split them.
            mid = len(L) // 2
            leftL = L[:mid]
            rightL = L[mid:]

            merge_count_inversion(leftL)
            merge_count_inversion(rightL)

            # merge them.
            i = j = k = 0
            while i < len(leftL) and j < len(rightL):
                if leftL[i] < rightL[j]:
                    L[k] = leftL[i]
                    i += 1
                else:# no equal situation.
                    L[k] = rightL[j]
                    j += 1
                    count+=j
                k += 1
            while i < len(leftL):#all right is inversion.
                count+=j
                L[k] = leftL[i]
                i += 1
                k += 1
            while j < len(rightL):
                L[k] = rightL[j]
                j += 1
                k += 1

    count = merge_count_inversion(list(sequence))

    return count

With Python 3

def count_inversion(sequence):
    count = 0    
    def merge_count_inversion(L):
        nonlocal count
        if len(L) > 1:
        ......

    merge_count_inversion(list(sequence))

    return count
qvpham
  • 1,896
  • 9
  • 17
  • 1
    Thank you! It seems that I just lose what I learned at the chapter about function in python...Variable can be found, but if we want to change the value, we must use global or nonlocal for situation. – ljy May 17 '16 at 09:39