0

im new to python taking my first class and im doing very well so far, but this problem is killing me, I would appriciate any help i can get.

Problem:

An inversion in a sequence is a pair of entries that are out of order. For example, the characters F and D form an inversion in string 'ABBFHDL', because F appears earlier in the string but later in the alphabet. Characters H and D also form an inversion. The total number of inversions in a sequence, i.e. the number of pairs that are out of order, is a measure of how unsorted the sequence is. the total number of inversions in 'ABBFHDL' is 2. Implement function inversions() that takes a sequence (string) of upper case characters A through Z and returns the number of inversions in the sequence.

what I got so far is the following:

    def inversions(s):
        count = 0
        for i in range(len(s)):          # for each index i
            for j in range(len(s)):      # for each index J
                if s[j]>=s[i]:           # compare string[i] and string[j]
                    count += 0

                else:
                    count +=1
                    return count

and its not far enough down the rabit hole to get good partial credits :(

and this gives me 1 so this is not correct (should be 2).

what im wondering about, and this is a big hurdle right now, is how to write the code in order to achieve this: # for each index j that is greater than i

i have tried several codes but i dont get it to work, i have tried these:

    for j in range(len(s)>i):        # the result i get is 1
    for j in range(len(s)<i):        # the result i get is 'blank
    for j in range(len(s)>s[i]):    # the result i get is this error message : 

    for j in range(len(s)>s[i]):
    TypeError: unorderable types: int() > str()

What i can't achieve is to get the function iterate over every possible pair in the sequence (string).

(i.e AA, AB, AB, AF, AH, AD, AL, BB, BB, BF, BH, BD, BL, (none of these would render a count - but when the iteration reach F there would be an inversion count for FD and then for HD, hence the answer 2)

I just cant get there with my code.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Snarre
  • 597
  • 5
  • 14
  • 22

3 Answers3

2

Revised code

this should work

def inversions(s):
        count = 0
        for i in range(len(s)-1):
            for j in range(i+1,len(s)):
                if s[i] > s[j]:
                    print(s[i],s[j])
                    count +=  1
                    break
#remove 'break' if you want to count every possible 
#out of order pair for a particular character in the string
        print(count)
ParokshaX
  • 277
  • 5
  • 15
  • my bad, but the answer is 2 since in the sequence F comes before D and H comes befor D - so there are 2 inversions. Sorry I was a bit too quick when writing the first time – Snarre May 17 '13 at 17:42
  • @user2394720 could you please restate your definition for "inversion in a sequence".. you mentioned it as pair of entries, if it is then the above code should work correct. – ParokshaX May 17 '13 at 17:46
  • ok, The total number of inversions in a sequence, i.e. the number of pairs that are out of order. This is not only adjacent pairs but any possible pairings of the items in the sequence. EXE: AA, AB, BB, AF, FH, HD, DL etc so if any of these pairing are out of alpahbetical order then the algorithm should add +1 to the count. My problem is that I cant seem to figure out how to write a loop that iterates overe every possible pair in the sequence(string). I think that every letter in the sequence starting with A, needs to be compared with every next letter. – Snarre May 17 '13 at 17:53
  • @user2394720 I got your problem statement... see the revised code, it should work now... – ParokshaX May 17 '13 at 17:53
  • Thank you sir! there is only one thing. I does work with 'ABBFHDL', but here is the doubble check that i was given. if the string is backwards 'DCBA' then every pair comparison we make is worth 2. [DC] = 2 because D is ahead of C and C is after D [CB] = 2 because C is ahead of B and B is after C [BA] = 2 because B is ahead of A and A is after B so that should render an answer of 6 but our current code gives us 3. – Snarre May 17 '13 at 18:00
  • would it be enough to change the if statement you think? – Snarre May 17 '13 at 18:03
  • @user2394720 if 'DCBA' yield 6 then you meant to get every possible pair of inversions.. just remove the `break` statement in above code.. – ParokshaX May 17 '13 at 18:09
1

Here's a way to get all the letter pairs:

for i in range(len(s)):
    for j in range(i + 1, len(s)):
        print s[i], s[j]

I'll leave the counting part to you!

Tom Offermann
  • 1,391
  • 12
  • 12
0

Now what I'm offering is not nice code, but it might still be educational.

inv = lambda w:sum([sum([w[i]>w[j] for j in range(i+1,len(w))]) for i in range(len(w))])

Does exactly what you specified and is a one-liner. I wrote this for a code-golf challenge once.

You can even nicen it up a bit by using itertools:

from itertools import combinations
inv = lambda w:sum([w[i]>w[j] for i,j in combinations(range(len(w)),2)])

You can use these lambda functions like you would use any other function:

In [32]: inv('ABBFHDL')
Out[32]: 2
Dani Gehtdichnixan
  • 1,265
  • 1
  • 11
  • 21