Posts Homework Solutions 2
Post
Cancel

Homework Solutions 2

1

We first need to figure out how to add letter from the start of a string to the end. For our first case let’s try taking the first letter of 'string' and sticking it to the end.

Slice the string and take the first letter:

1
2
>>> 'string'[:1]
's'

Slice the string and take everything except the first letter:

1
2
>>> 'string'[1:]
'tring'

Snap the first letter to the end of everything-that-is-not-the-first-letter:

1
>>> 'string'[1:]+'string'[:1]

Now that we know how to rotate strings, we can start building our function.

How?

As you know if we rotate a string enough times (len(string) times to be exact) we’ll get our initial string back

0th1st2nd3rd4th
mootootmotmotmoomoot

So we can write a for loop that will rotate one of our strings this many times, and check if any of the rotations are equal to the other string.

Doing it

Defining our function

1
def rotation_test(str1, str2):

To write the loop, we’ll use the range() function. Since we can at most rotate our string len(string) times, that’s what we’ll give to range(). Using range() will also allow us to check for the initial condition since it starts from 0 ('string'[0:]+'string'[:0] == 'string') And arbitrarily I’ve chosen the second string (str2) to rotate.

1
    for i in range(len(str2)):

Now we’ll rotate str2 and check whether it’s the same as str1 at every rotation. If they are the same, we’ll return true.

1
2
        if str2[i:]+str2[:i] == str1:
            return True

So if they are the same somewhere inside the loop, the function will return True and the interpreter won’t read the rest of the function but if it isn’t, the function will return None. We can fix this by returning False after the loop (again, this will only be read if the strings aren’t the rotations of each other).

1
    return False

The problem

Let’s write some tests.

1
2
3
4
5
print(rotation_test("nicole", "icolen"))
print(rotation_test("nicole", "lenico"))
print(rotation_test("aabaaaaabaab", "aabaabaabaaa"))
print(rotation_test("booyah", "yahbah"))
print(rotation_test("", ""))

Now clearly, the first three should give us True, the fourth False and the last one True. But what happens?

1
2
3
4
5
True
True
True
False
False

This is because no matter how you slice '', you get ''. We can fix this by just adding an if statement to check whether both of our strings is '' and return True if so. This is to be added before the final return.

1
2
    if str1+str2 == '':
        return True

Here we shortened our code by using this statement since str1+str2 is only '' when both str1 and str2 is ''. (Alternate way to do it would be str1 == '' and str2 == '')

Code in full

1
2
3
4
5
6
7
def rotation_test(str1, str2):	
    if str1+str2 == '':
		return True
	for i in range(len(str2)):
		if str1 == str2[i:]+str2[:i]:
			return True
	return False

Smarter way

Like always, there is a smarter way. Think about the rotations 'string' and 'trings'. What happens when we double the second string? We get 'tringstrings'. Notice anything peculiar? Yes. Inside the doubled version of our second string, sits our first string. So we can just make our function

1
2
3
4
5
6
def rotation_test(str1, str2):
    double = str2+str2
    if str1 in double:
        return True
    else:
        return False

The problem

The problem is, when we do rotation_test('string', 'stringas'), we’ll get True but we don’t want this, since our strings have to be the same length. We can just add a statement that returns False if these strings aren’t the same length.

1
2
    if len(str1) != len(str2):
        return False

Although this is still a dumb solution because first, we check if str1 in double and return True if it’s True and False if it’s False. Do you see the redundancy? Why don’t we just return str1 in double?

1
    return str2 in double

Code in full

1
2
3
4
5
def rotation_test(str1, str2):
    if len(str1) != len(str2):
        return False
    double = str2+str2
    return str2 in double

Golfed

1
2
def rotation_test(i, j):
  return (len(i) == len(j)) and (j in (i + j))

2

Not much to do in this question. We’ll just make a dictionary that has numbers as keys and add matching stuff to our answer variable. We’ll build on the advanced solution as you’ve learned about splits.

1
2
def time2words(string):
    hour, minute = int(string.split(':')[0]), int(string.split(':')[1])

Defining our dictionary

1
    dictionary = {0:'', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten', 11:'eleven', 12:'twelve', 13:'thirteen', 14:'fourteen', 15:'fifteen', 16:'sixteen', 17:'seventeen', 18:'eighteen', 19:'nineteen', 20:'twenty', 30:'thirty', 40:'forty', 50:'fifty'}

This has all the numbers we need. Let’s try to find a way to convert hour and minute using this dictionary.

Hour part

Let’s get our appendix similarly to how we did last time

1
2
3
4
    if 12 >= hour > 24:
        appendix = 'pm'
    else:
        appendix = 'am'

And let’s translate our 24-hour system to 12-hour like the last time using mod

1
    hour = hour%12

Now there are a few cases we need to consider

  1. hour is 0 in which case we’ll be assigning hour_writing = 'twelve' manually (We do this because we defined 0:'' in our dictionary)
  2. hour is anything else in which case we’ll just look it up on the dictionary
1
2
3
4
    if hour == 0:
        hour_writing = 'twelve'
    else:
        hour_writing = dictionary[hour]

And the hour part is done.

Minute part

We’ll split our minute to 10s and 1s like we did last time.

1
2
    minute_ones = minute%10
    minute_tens = minute-minute_ones

Now we can get the correspondents of these from our dictionary

1
    minute_writing = dictionary[minute_tens]+' '+dictionary[minute_ones]

And we’ll fix it if our minute is something like 12 or 15

1
2
    if 10 < minute < 20:
        minute_writing = dictionary[minute]

Putting it all together

We just need to return what we have and fix the spaces.

1
2
3
4
5
6
7
8
    if (minute_tens == 0) and (minute_ones == 0):
        return hour_writing+' '+appendix
    elif (minute_tens != 0) and (minute_ones == 0):
        return hour_writing+' '+minute_writing+appendix
    elif (minute_tens == 0) and (minute_ones != 0):
        return hour_writing+minute_writing+' '+appendix
    else:
        return hour_writing+' '+minute_writing+' '+appendix

Code in full

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def time2words(string):
    hour, minute = int(string.split(':')[0]), int(string.split(':')[1])
    dictionary = {0:'', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten', 11:'eleven', 12:'twelve', 13:'thirteen', 14:'fourteen', 15:'fifteen', 16:'sixteen', 17:'seventeen', 18:'eighteen', 19:'nineteen', 20:'twenty', 30:'thirty', 40:'forty', 50:'fifty'}
    
    if 12 <= hour < 24:
        appendix = 'pm'
    else:
        appendix = 'am'
        
    hour = hour%12
    if hour == 0:
        hour_writing = 'twelve'
    else:
        hour_writing = dictionary[hour]
        
    minute_ones = minute%10
    minute_tens = minute-minute_ones
    minute_writing = dictionary[minute_tens]+' '+dictionary[minute_ones]
    if 10 < minute < 20:
        minute_writing = dictionary[minute]
    if (minute_tens == 0) and (minute_ones == 0):
        return hour_writing+' '+appendix
    elif (minute_tens != 0) and (minute_ones == 0):
        return hour_writing+' '+minute_writing+appendix
    elif (minute_tens == 0) and (minute_ones != 0):
        return hour_writing+minute_writing+' '+appendix
    else:
        return hour_writing+' '+minute_writing+' '+appendix

Golfing

Golfing is writing code with as little characters as possible.

1
2
3
4
def t(s):
    d = {0:'', 1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten', 11:'eleven', 12:'twelve', 13:'thirteen', 14:'fourteen', 15:'fifteen', 16:'sixteen', 17:'seventeen', 18:'eighteen', 19:'nineteen', 20:'twenty', 30:'thirty', 40:'forty', 50:'fifty'}
    h, m = map(int, s.split(':'))
    return ' '.join(f"{'twelve' if h%12 == 0 else d[h%12]} {d[m] if 10 < m < 20 else d[m-m%10]+' '+d[m%10]} {'pm' if 12 <= h < 24 else 'am'}".split())

3

I’ve modified the question a bit to be more useful. Of course you can do it with pre-defined values.

1
2
3
4
def table(function, values):
    print('x    |  f(x)\n-----------')
    for i in values:
        print(str(i)+'    |    '+str(function(i)))

This is pretty basic. The first print is to set up table titles. Then we loop over each value in values and print value-output pairs. To have a nicer table I’ve also added a separation in between these. Of course, to be able to add it we needed to convert our i and function(i) to str (They could have been integers depending on the function and we certainly don’t want that). For a little test let’s make a simple function

1
2
def func(x):
	return x**2

And try printing a table of our function

1
table(func, [0,1,2,3,4])

Output:

1
2
3
4
5
6
7
x    |  f(x)
-----------
0    |    0
1    |    1
2    |    4
3    |    9
4    |    16

4

We’ll just take a string, and use a split.

1
2
def reverse_string(string):
    return string[::-1]

Our split starts at the beginning of the string (0) and ends at the end (len(string)) but it counts backwards.

This post is licensed under CC BY 4.0 by the author.