We could use split to make a list, then divide the list in two and rejoin the words.
>>> def split_sentence(line):
words = line.split()
n = len(words) // 2
n += not n % 2 and 1 or 0
return f"{' '.join(words[:n])}\n{' '.join(words[n:])}"
>>> print (split_sentence("A quick brown fox jumps over the lazy dog"))
A quick brown fox jumps
over the lazy dog
>>> print (split_sentence("A quick brown fox jumps over the moping lazy dog"))
A quick brown fox jumps
over the moping lazy dog
>>>
There are likely concepts above that may not be familiar…
-
//
=> floor division
-
+=
=> augmented assignment operator
-
not n % 2 and 1 or 0
=> logic to yield 1 when n is even else 0
-
return f"{..}\n{..}"
=> f-string formatting
-
\n
=> newline escape sequence
-
words[:n]
=> slice of first n - 1 words
-
words[n:]
=> slice of words from n
to end
Using your accumulated knowledge, see if you can interpret this to naive (unrefactored) code that only uses concepts you have already learned.
Let’s work through the code and reduce it to more naive terms as we go. We must at least understand what the int()
constructor does, as it usually precedes introduction of floor division.
>>> def split_sentence(line):
words = line.split()
n = int(len(words) / 2) # expanded form of x // 2
n += 0 if n % 2 else 1 # conditional expression vs. logic
return f"{' '.join(words[:n])}\n{' '.join(words[n:])}"
>>> print (split_sentence("A quick brown fox jumps over the lazy dog"))
A quick brown fox jumps
over the lazy dog
>>> print (split_sentence("A quick brown fox jumps over the moping lazy dog"))
A quick brown fox jumps
over the moping lazy dog
>>>
Notice we’re starting to back away from abstraction on the two commented lines. There’s still more work to be done.
The introduced concept is the conditional expression which is similar to a ternary expression in other languages. Python does not have a ternary operator so this is what we fall back to if that is the logic we are going after. It cannot be left this way since you may have never encountered it in previous lessons. Still, it is a step away from the abstract logic used earlier. As stated, more work to be done.
What if all we have is the sentence, and no int()
constructor? Can we still arrive at a value for n
? Well of course we can. Take out your pencil and paper… Draw a t-grid
,
odd | even
-----------------
|
|
|
|
|
Go through the words and put them alternatively into the grid. One on the left, one on the right until all words are exhausted. We’re not doing anything with this grid so don’t care that it doesn’t make code sense. It’s serving a purpose by helping us split the sentence into two nearly equal lists.
Now cross off every row that has both an odd and an even entry. If there is nothing left at the end, add 1 to n
.
The closer we can bring code to pencil and paper, the closer we are to naive code. Yes, this is a strange exercise, and almost seems like reverse engineering, but it’s not. It is the reduction of abstracts to their basest form. Keep playing with this. For sure I will be.