[1]:
# Remember to execute this cell with Control+Enter
import jupman;

Functions 3 - exercises with strings

First functions

length

✪ a. Write a function length1(s) in which, given a string, RETURN the length of the string. Use len function. For example, with "ciao" string your function should return 4 while with "hi" it should return 2

>>> x = length1("ciao")
>>> x
4

✪ b. Write a function length2 that like before calculates the string length, this time without using len (instead, use a for cycle)

>>> y = length2("mondo")
>>> y
5
Show solution
[2]:
# write here


contains

✪ Write the function contains(word, character), which RETURN True is the string contains the given character, otherwise RETURN False

  • Use in operator

>>> x = contains('ciao', 'a')
>>> x
True
>>> y = contains('ciao', 'z')
>>> y
False
Show solution
[3]:
# write here


invertlet

✪ Write the function invertlet(first, second) which takes in input two strings of length greater than 3, and RETURN a new string in which the words are concataned and separated by a space, the last two characters in the words are inverted. For example, if you pass in input 'twist' and 'space', the function should RETURN 'twise spact'

  • If the two strings are not of adequate length, the program PRINTS error!

NOTE 1: PRINTing is different from RETURNing !!! Whatever gets printed is shown to the user but Python cannot reuse it for calculations.

NOTE 2: if a function does not explicitly return anything, Python implicitly returns None.

NOTE 3: Resorting to prints on error conditions is actually bad practice: this is an invitation to think about what happens when you print something and do not return anything. You can read a discussion about it in Errors handling and testing page

>>> x = invertlet("twist", "space")
>>> x
'twise spact'
>>> x = invertlet("fear", "me")
'error!'
>>> x
None
>>> x = invertlet("so", "bad")
'error!'
>>> x
None
Show solution
[4]:

# write here


nspace

✪ Write a function nspace that given a string s in input, RETURN a new string in which the n-character is a space.

  • if the number is too big, raise the exception ValueError - in the exception message state clearly what the problem was and the input.

NOTE: This time instead of printing the error we raise the exception, which will prevent the program from continuing further. This is a much better way to react to erroneous conditions.

>>> x = nspace('allegory', 5)
>>> x
'alleg ry'

>>> x = nspace('toy', 9)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
2610223641.py in <module>
---> 12 nspace("toy", 9)
ValueError: index 9 is larger than word toy

>>> x = nspace('rack', 4)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
2610223641.py in <module>
---> 12 nspace("rack", 4)
ValueError: index 4 is larger than word rack
Show solution
[5]:


# write here


startend

✪ Write a function which takes a string s and RETURN the first and last two characters

  • if length is less than 4, raises ValueError - in the exception message state clearly what the problem was and the input

>>> startend('robust pack')
rock

>>> startend('sig')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
230230193.py in <module>
----> 8 startend('sig')

ValueError: I need at least 4 characters, got instead: sig
Show solution
[6]:

# write here


swap

Write a function that given a string, swaps the first and last character and RETURN the result.

  • if the string is empty, raise ValueError - in the exception message state clearly the cause of the problem

>>> swap('dream')
mread
>>> swap('c')
c
>>> swap('')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
2089609385.py in <module>
---> 11 swap('')
ValueError: Empty string!
Show solution
[7]:

# write here


Verify comprehension

ATTENTION

The following exercises contain tests with asserts. To understand how to solve them, read first Error handling and testing

has_char

✪ RETURN True if word contains char, False otherwise

  • USE a while cycle

  • DON’T use in operator nor methods such as .count (too easy!)

Show solution
[8]:
def has_char(word, char):
    raise Exception('TODO IMPLEMENT ME !')


# TEST START - DO NOT TOUCH!
# if you wrote the whole code correct, and execute the cell, Python shouldn't raise `AssertionError`

assert has_char("ciao", 'a')
assert not has_char("ciao", 'A')
assert has_char("ciao", 'c')
assert not has_char("", 'a')
assert not has_char("ciao", 'z')

# TEST END

count

✪ RETURN the number of occurrences of char in word

  • USE a for in cycle

  • DON’T use count method (too easy!)

  • DON’T PRINT, IT MUST RETURN THE VALUE !

Show solution
[9]:

def count(word, char):
    raise Exception('TODO IMPLEMENT ME !')

# TEST START - DO NOT TOUCH!
# if you wrote the whole code correct, and execute the cell, Python shouldn't raise `AssertionError`

assert count("ciao", "z") == 0
assert count("ciao", "c") == 1
assert count("babbo", "b") == 3
assert count("", "b") == 0
assert count("ciao", "C") == 0
# TEST END

has_lower

✪ RITORNA True if the word contains at least one lowercase character, otherwise return False

  • USE a while cycle

Show solution
[10]:

def has_lower(s):
    raise Exception('TODO IMPLEMENT ME !')


# TEST START - DO NOT TOUCH!
# if you wrote the whole code correct, and execute the cell, Python shouldn't raise `AssertionError`

assert has_lower("David")
assert has_lower("daviD")
assert not has_lower("DAVID")
assert not has_lower("")
assert has_lower("a")
assert not has_lower("A")

dialect

✪✪ There exist a dialect in which all the "a" must be always preceded by a "g". In case a word contains an "a" not preceded by a "g", we can say with certainty that this word does not belong to the dialect. Write a function that given a word, RETURN True if the word respects the rules of the dialect, False otherwise.

>>> dialect("ammot")
False
>>> print(dialect("paganog")
False
>>> print(dialect("pgaganog")
True
>>> print(dialect("ciao")
False
>>> dialect("cigao")
True
>>> dialect("zogava")
False
>>> dialect("zogavga")
True
Show solution
[11]:


def dialect(word):
    raise Exception('TODO IMPLEMENT ME !')

# TEST START - DO NOT TOUCH!
# if you wrote the whole code correct, and execute the cell, Python shouldn't raise `AssertionError`

assert dialect("a") == False
assert dialect("ab") == False
assert dialect("ag") == False
assert dialect("ag") == False
assert dialect("ga") == True
assert dialect("gga") == True
assert dialect("gag") == True
assert dialect("gaa") == False
assert dialect("gaga") == True
assert dialect("gabga") == True
assert dialect("gabgac") == True
assert dialect("gabbgac") == True
assert dialect("gabbgagag") == True
# TEST END

countvoc

✪✪ Given a string, write a function that counts the number of vocals. If the vocals number is even, RETURN the number of vocals, otherwise raises exception ValueError

>>> countvoc("arco")
2
>>> count_voc("ciao")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-15-058310342431> in <module>()
     16 countvoc("arco")
---> 19 countvoc("ciao")

ValueError: Odd vocals !
Show solution
[12]:

def countvoc(word):
    raise Exception('TODO IMPLEMENT ME !')

# TEST START - DO NOT TOUCH!
# if you wrote the whole code correct, and execute the cell, Python shouldn't raise `AssertionError`

assert countvoc("arco") == 2
assert countvoc("scaturire") == 4

try:
    countvoc("ciao")    # with this string we expect it raises exception ValueError
    raise Exception("I shouldn't arrive until here !")
except ValueError:      # if it raises the exception ValueError, it is behaving as expected and we do nothing
    pass

try:
    countvoc("aiuola")  # with this string we expect it raises exception ValueError
    raise Exception("I shouldn't arrive until here  !")
except ValueError:      # if it raises the exception ValueError, it is behaving as expected and we do nothing
    pass


extract_email

Show solution
[13]:
def extract_email(s):
    """ Takes a string s formatted like

        "lun 5 nov 2018, 02:09 John Doe <john.doe@some-website.com>"

        and RETURN the email "john.doe@some-website.com"

        NOTE: the string MAY contain spaces before and after, but your function must be able to extract email anyway.

        If the string for some reason is found to be ill formatted, raises ValueError
    """
    raise Exception('TODO IMPLEMENT ME !')

assert extract_email("lun 5 nov 2018, 02:09 John Doe <john.doe@some-website.com>") == "john.doe@some-website.com"
assert extract_email("lun 5 nov 2018, 02:09 Foo Baz <mrfoo.baz@blabla.com>") == "mrfoo.baz@blabla.com"
assert extract_email(" lun 5 nov 2018, 02:09 Foo Baz <mrfoo.baz@blabla.com>  ") == "mrfoo.baz@blabla.com"  # with spaces

canon_phone

✪ Implement a function that canonicalize canonicalize a phone number as a string. It must RETURN the canonical version of phone as a string.

For us, a canonical phone number:

  • contains no spaces

  • contains no international prefix, so no +39 nor 0039: we assume all calls where placed from Italy (even if they have international prefix)

For example, all of these are canonicalized to "0461123456":

+39 0461 123456
+390461123456
0039 0461 123456
00390461123456

These are canonicalized as the following:

328 123 4567        ->  3281234567
0039 328 123 4567   ->  3281234567
0039 3771 1234567   ->  37711234567

REMEMBER: strings are immutable !!!!!

Show solution
[14]:
def phone_canon(phone):
    raise Exception('TODO IMPLEMENT ME !')

assert phone_canon('+39 0461 123456') == '0461123456'
assert phone_canon('+390461123456') == '0461123456'
assert phone_canon('0039 0461 123456') == '0461123456'
assert phone_canon('00390461123456') == '0461123456'
assert phone_canon('003902123456') == '02123456'
assert phone_canon('003902120039') == '02120039'
assert phone_canon('0039021239') == '021239'

phone_prefix

✪✪ We now want to extract the province prefix from phone numbers (see previous exercise) - the ones we consider as valid are in province_prefixes list.

Note some numbers are from mobile operators and you can distinguish them by prefixes like 328 - the ones we consider are in mobile_prefixes list.

Implement a function that RETURN the prefix of the phone as a string. Remember first to make it canonical !!

  • If phone is mobile, RETURN string 'mobile'. If it is not a phone nor a mobile, RETURN the string 'unrecognized'

  • To determine if the phone is mobile or from province, use province_prefixes and mobile_prefixes lists.

  • DO USE THE PREVIOUSLY DEFINED FUNCTION phone_canon(phone)

Show solution
[15]:
province_prefixes = ['0461', '02', '011']
mobile_prefixes = ['330', '340', '328', '390', '3771']


def phone_prefix(phone):
    raise Exception('TODO IMPLEMENT ME !')

assert phone_prefix('0461123') == '0461'
assert phone_prefix('+39 0461  4321') == '0461'
assert phone_prefix('0039011 432434') == '011'
assert phone_prefix('328 432434') == 'mobile'
assert phone_prefix('+39340 432434') == 'mobile'
assert phone_prefix('00666011 432434') == 'unrecognized'
assert phone_prefix('12345') == 'unrecognized'
assert phone_prefix('+39 123 12345') == 'unrecognized'

palindrome

✪✪✪ A word is palindrome if it exactly the same when you read it in reverse

Write a function the RETURN True if the given word is palindrome, False otherwise

  • assume that the empty string is palindrome

Example:

>>> x = palindrome('radar')
>>> x
True
>>> x = palindrome('abstruse')
>>> x
False

There are various ways to solve this problems, some actually easy & elegant. Try to find at least a couple of them (don’t need to bang your head with the recursive one ..).

Show solution
[16]:

def palindrome(word):
    raise Exception('TODO IMPLEMENT ME !')

# TEST START - DO NOT TOUCH!
# if you wrote the whole code correct, and execute the cell, Python shouldn't raise `AssertionError`

assert palindrome('') == True    # we assume the empty string is palindrome
assert palindrome('a') == True
assert palindrome('aa') == True
assert palindrome('ab') == False
assert palindrome('aba') == True
assert palindrome('bab') == True
assert palindrome('bba') == False
assert palindrome('abb') == False
assert palindrome('abba') == True
assert palindrome('baab') == True
assert palindrome('abbb') == False
assert palindrome('bbba') == False
assert palindrome('radar') == True
assert palindrome('abstruse') == False

Continue

Go on with exercises about functions and lists