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
[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
[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
[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
[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
[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!
[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
cycleDON’T use
in
operator nor methods such as.count
(too easy!)
[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
cycleDON’T use
count
method (too easy!)DON’T PRINT, IT MUST RETURN THE VALUE !
[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
[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
[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 !
[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
nor0039
: 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
andmobile_prefixes
lists.DO USE THE PREVIOUSLY DEFINED FUNCTION
phone_canon(phone)
[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