ozzyna
ozzyna

Reputation: 77

Python divide odd length string and combine

I'm going through the free Python class Google has available (Link if interested) and I'm stuck on one of the exercises.

Goal: Consider dividing a string into two halves. If the length is even, the front and back halves are the same length. If the length is odd, we'll say that the extra char goes in the front half. e.g. 'abcde', the front half is 'abc', the back half 'de'. Given 2 strings, a and b, return a string of the form a-front + b-front + a-back + b-back

This is what I have so far:

def front_back(a, b):
    if len(a)%2 == 0 or len(b)%2 == 0:
        firstpart , secondpart = a[:len(a)/2] , a[len(a)/2:]
        thirdpart , fourthpart = b[:len(b)/2] , b[len(b)/2:]
    else:
        firstpart , secondpart = a[:len(a)+1/2] , a[len(a)+1/2:]
        thirdpart , fourthpart = b[:len(b)+1/2] , b[len(b)+1/2:]
    return firstpart+thirdpart+secondpart+fourthpart

These are the test strings:

 test(front_back('abcd', 'xy'), 'abxcdy')
 test(front_back('abcde', 'xyz'), 'abcxydez')
 test(front_back('Kitten', 'Donut'), 'KitDontenut')

The third string in each is the expected string.

What am I doing wrong? I know that the issue is not being able to account for odd-length strings, but I have been searching for a few days now and I've had no luck finding an answer online. I'm also open to more efficient solutions, but I want to know why my particular setup is not working out, for future reference.

Thanks!

Upvotes: 1

Views: 5026

Answers (4)

dansalmo
dansalmo

Reputation: 11694

Simpler method:

def front_back(a, b):
    hlena, hlenb = (len(a) + 1)/2, (len(b) + 1)/2
    return a[:hlena] + b[:hlenb] + a[hlena:] + b[hlenb:]

No need for if clause to handle empty string case. Order of operations for slice calculation was not correct in your code.

Tip: Defore diving in and coding, play with the problem in the REPL shell until you have a succinct representation of the problem. One of the biggest challenges that beginners have is the code they create is much larger than needed, making it harder to understand and debug. Start with the smallest workable chuck and build from there.

Upvotes: 1

msturdy
msturdy

Reputation: 10794

try to avoid repeating code.. if you're splitting one string once, and then following the same rules to split a second string, just write a small function to do it! I've put a function called splitter() inside the main function front_back()

#!/usr/bin/env python

def front_back(a, b):

  def splitter(s):
    l = len(s)
    if l%2 == 0:
      d = l/2
    else:
      d = (l/2) +1
    return (s[:d], s[d:])

  a1, a2 = splitter(a)
  b1, b2 = splitter(b)

  return a1 + b1 + a2 + b2

try that out...

Upvotes: 1

Thomas Fenzl
Thomas Fenzl

Reputation: 4392

You should split the implementation into a splitting function and a merging. Easier to test that way. Also, the way the split is defined, you can simplify the first function quite a bit:

If the length of the string s is even, len(s)//2 in integer division is the same as (len(s)+1)//2. If it is odd, len(s)//2 is one less than (len(s)+1)//2. Since you need the longer string as first part, the splitting function can be written as:

def splitter(s):
    mid = (len(s)+1)//2
    return s[:mid], s[mid:]

Then for the merging:

def front_back(a,b):
    a_front, a_back = splitter(a)
    b_front, b_back = splitter(b)
    return "".join((a_front, b_front, a_back, b_back))

Upvotes: 2

N_A
N_A

Reputation: 19897

Your problem is that you're not treating a and b as separate cases. Consider the case where a has length 4 and b has length 5. In that case you would always take the first branch, which would treat b incorrectly.

def front_back(a, b):
    if len(a)%2 == 0:
        firstpart , secondpart = a[:len(a)/2] , a[len(a)/2:]
    else:
        firstpart , secondpart = a[:len(a)+1/2] , a[len(a)+1/2:]

    if len(b)%2 == 0:
        thirdpart , fourthpart = b[:len(b)+1/2] , b[len(b)+1/2:]
    else
        thirdpart , fourthpart = b[:len(b)/2] , b[len(b)/2:]

    return firstpart+thirdpart+secondpart+fourthpart

Upvotes: 2

Related Questions