Alex Karpowitsch
Alex Karpowitsch

Reputation: 673

Think Python (How to think like a computer scientist) - Excercise 8.4

I'm having some trouble solving the problem below (My thinking on how I might solve it is directly beneath the problem)

"In Robert McCloskey’s book Make Way for Ducklings, the names of the ducklings are Jack, Kack, Lack, Mack, Nack, Ouack, Pack, and Quack."

This loop outputs these names in order:

prefixes = 'JKLMNOPQ' 
suffix = 'ack'
for letter in prefixes:
    print letter + suffix

The output is:

Jack
Kack
Lack
Mack
Nack
Oack
Pack
Qack

Of course, that’s not quite right because “Ouack” and “Quack” are misspelled.

Exercise 8.2 Modify the program to fix this error."

So prefix + suffix yields 4 characters in its current form. Ouack and Quack are 5 characters. In the prior section, we used 'while' to transverse a string to create a condition where if the index is equal to the length of the string, the condition is false, and the body of the loop is not executed. I'm thinking I need to modify the for loop so that if the output character count is less than the original string value inputted, it adds the letter 'U'. How do I go about relating the length of the string value inputted for each name and the 'prefixes'?

I'm not sure how I'd go about doing this, or if I should persue a different strategy.

I apologize in advance I've butchered any of the terminology, I'm two days into this book, and I have no prior computer science background.

Upvotes: 2

Views: 10477

Answers (12)

brownspecs
brownspecs

Reputation: 13

Same as other answers here, going through the book, solved it then came here to compare answers. My solution is to only change the prefixes to a list and no other changes:

prefixes = ["J", "K", "L", "M", "N", "Ou", "P", "Qu"] #originally "JKLMNOPQ"
suffix = "ack"

for letter in prefixes:
    print(letter + suffix)

Upvotes: 0

Sheikh
Sheikh

Reputation: 71

prefixes = "JKLMNOPQ"
suffix = "ack"

for l in prefixes:
    if l == "Q" or l == "O":
    print(l + "u" + suffix)
else:
    print(l + suffix)

Try this!

Upvotes: 0

Anrico G.
Anrico G.

Reputation: 11

I just came across this question myself, and then checked the web to see how others did. Mine looked like this:

prefixes = "JKLMNOPQ"
prefixes = list(prefixes)
prefixes[5] = "Ou" 
prefixes[7] = "Qu"
suffix = "ack"

for p in prefixes:
    print(p + suffix)

Upvotes: 1

Charles
Charles

Reputation: 1

It works but other code using if looks nicer:

prefixes = 'JKLMNP'
prefixess = 'OQ'
suffix = 'ack'

for letter in prefixes:
    print(letter + suffix)
for letter in prefixess:
    print (letter + 'u' + suffix)

Upvotes: 0

Margaret Scott
Margaret Scott

Reputation: 31

I just did this exercise and came here to see how others did it. In my 2nd edition this was part of a chapter on indexing and the string module, so I used them heavily in my nutso solution. Basically I added the "u"s to the prefix string and wrote an if statement to check for lowercase in the string.

import string
def ducks():
    prefixes = "JKLMNOuPQu"
    suffix = "ack"
    index = 0
    while index < len(prefixes)-1:
        if prefixes[index+1] in string.lowercase:
        prefix = prefixes[index:index+2]
        print prefix + suffix
        index += 1
    elif prefixes[index] in string.lowercase:
        index += 1
    else:
        prefix = prefixes[index]
        print prefix + suffix
        index +=1

Upvotes: 3

Chris Adams
Chris Adams

Reputation: 1097

suffix = 'ack'
prefixes = list('JKLMNP')
prefixes += ['Qu', 'Ou']
prefixes.sort()

for prefix in prefixes:
    print prefix + suffix

Upvotes: 1

vonPetrushev
vonPetrushev

Reputation: 5599

My solution would be:

prefixes = list('JKLMNP')
prefixes.extend(['Ou', 'Qu'])
suffix = 'ack'
for pref in prefixes:
    print pref + suffix

It is compact and contains very few modifications of the original.

Upvotes: 4

Binary Phile
Binary Phile

Reputation: 2668

I prefer the Gordian Knot approach:

print '\n'.join(['Jack', 'Kack', 'Lack', 'Mack', 'Nack', 'Ouack', 'Pack', 'Quack'])

Strictly speaking, that's just a (somewhat radical) modification.

Stuff that, Perl guy.

All kidding aside, you could do it as the others have mentioned by special casing the "O" and "Q". A (very) slightly more general approach is to think of the extra vowels not as a special case but rather as the only "visible" members of a general case:

suffixes = ['ack'] * 8
prefixes = 'JKLMNOPQ'
infixes = ',,,,,u,,u'.split(',')

The split of the infixes string returns empty strings surrounding the consecutive commas, so the 'u's are the only non-empty elements and they fall in the right places for the final result.

This makes three iterables (think lists, but strings count too) where all of the parts are lined up in the correct slots. This is enough of a shift that you can trade the old loop for a zip, which is probably not the intent of the exercise but is still a pythonic technique. Now you just need to run a zipper down the three, which is what the zip function is for, of course.

The only wrinkle is that zip gives you a out a list of string pairs and we want whole strings, which is what a ''.join is for. They are processed by a list comprehension, which you will definitely want to learn if you don't already know:

result = [''.join(pair) for pair in zip(infixes, suffixes)]
result = [''.join(pair) for pair in zip(prefixes, result)]

All that is left is to print:

print '\n'.join(result)

To paraphrase a great man, my disclaimer: In theory, I can prove the correctness of this code, but I have not run it, so there may be bugs.

Upvotes: 1

Philar
Philar

Reputation: 3897

Being a Perl guy I couldn't help but give you a shorter solution than everyone else's :p

prefixes = 'JKLMNOPQ' 
suffix = 'ack'
for letter in prefixes:
 if letter in ('O','Q'):
  letter+="u"
 print letter+suffix

PS: I take it that the exercise was to modify the given code rather than to revamp it, otherwise there are ways of shrinking it further, within the confines of PEP8 that is:)

Upvotes: 1

martineau
martineau

Reputation: 123473

I like data-driven code:

endings = ['ack', 'uack']
specials = ['O','Q']
prefixes = 'JKLMNOPQ'
suffixes = dict(zip(prefixes, [endings[p in specials] for p in prefixes]))
for letter in prefixes:
    print letter + suffixes[letter]

Upvotes: 1

user225312
user225312

Reputation: 131677

>>> for letter in prefixes:
        if letter in ('O', 'Q'):  # if the letter is O or Q
            print letter + 'u' + suffix
        else:
            print letter + suffix


Jack
Kack
Lack
Mack
Nack
Ouack
Pack
Quack

Upvotes: 6

Daniel Roseman
Daniel Roseman

Reputation: 599620

I think you're overthinking this. You just need to check within the loop if the current letter is O or Q, and if so add a U.

Upvotes: 2

Related Questions