In-Class#

Coding Practice#

Code 7.1: Framed Sign#

Define a variable and assign it a sting value which is not longer than a line, for example This is my important message!. Write python code to print the message between two border lines as shown below. Your code should work for any string value assigned to the variable.

-----------------------------
This is my important message!
-----------------------------

Modify your code such that it also prints the vertical bars on the left and right side of the message as shown below.

---------------------------------
| This is my important message! |
---------------------------------

Make another modification to your code where you define a variable to store a character, for example *. This character will be used for the horizontal borders, such that the code now print the message below.

*********************************
| This is my important message! |
*********************************

Code 7.2: Framed Sign Function#

Based on the previous code, write a function print_framed_sign(message, border_char) that takes two arguments, a message and a character to be used for the border. The function should print the message between two border lines as shown below. Your function should work for any string value assigned to the variable.

Test your function with several different messages.

Add yet another argument to the function, is_important, which is a boolean value. If is_important is True, the function should print the message in uppercase letters. If is_important is False, the function should print the message as it is.

Now, you function should work as shown below.

>>> print_framed_sign("Harry, did you put your name in the goblet of fire?", "~", True)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| HARRY, DID YOU PUT YOUR NAME IN THE GOBLET OF FIRE? |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Lastly, apart form having a function which prints the framed message, we also want to have a function which return a string instead of printing it. Make another function framed_sign(message, border_char, is_important) which returns the framed message instead of printing it. Start by copying the code from the previous function and modify it to return the framed message instead of printing it. The returned string value should contain the framed message in three lines of text.

Test your function with several different messages. Make sure that framed_sign() function does not print anything when called. It should work as shown below.

>>> sign = framed_sign("Harry, did you put your name in the goblet of fire?", "X", True)
>>> print(sign)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
| HARRY, DID YOU PUT YOUR NAME IN THE GOBLET OF FIRE? |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Code 7.3: Count Vowels#

Define a variable and assign it a string value, for example Hello, what a beautiful day!. Write python code to traverse the string, and print every character in the string.

Now change your code so that it for every character prints whether this character is a vowel or not. We consider the vowels to be a, e, i, o, and u.

Modify your code such that it also counts the number of vowels in the string and prints the total number of vowels at the end.

Code 7.4: Count Vowels Function#

Based on the previous code, write a function vowel_count(message) that takes a message as an argument and returns the number of vowels in the message. This function should not print anything, only return the number of vowels. It should work as shown below.

>>> vowel_count("Hello, what's up?")
4
>>> vowel_count("OMG, I can't believe it!")
8
>>> vowel_count("This is a day when I'm feeling good")
11

Code 7.5: Format Dates#

Define a string variable with your birth date formatted as dd/mm/yyyy for example 13/01/1982. Write a python code to split the string into there strings, the day, the month, and the year. Now define a string variable with the date formatted as yyyy-mm-dd.

Now we want to format the date as dd-Mon-yy, for example 13-Jan-82. To accomplish this make a list of strings with the 3-letter abbreviation for each month. You need to appropriately manipulate the month part of the date to get the abbreviation.

Code 7.6: Format Dates Function#

Based on the previous code, write a function format_date(date) that takes a date string in dd/mm/yyyy format, and returns the date in dd-Mon-yy format. The function should work as shown below.

>>> new_format = format_date("01/08/2020")
>>> print(new_format)
01-Aug-2020

Problem Solving#

Problem 7.7: DNA Complement#

A strand of DNA may be represented as text consisting of letters A, T, C, and G. The complement of a DNA string is formed by replacing each nucleotide with its complement: A with T, T with A, C with G, and G with C. For example, the complement of AATTCG is TTAAGC. The reverse complement of a DNA string is the complement of the string read in reverse. For example, the reverse complement of AATTCG is CGAATT.

Write a function dna_complement which takes two inputs: a string dna representing a DNA strand, and a boolean reverse. The function should return the complement of the DNA strand. If reverse is True, the function should return the reverse complement.

Problem 7.8: Arrival Times#

Given a list of scheduled train arrivals (hours and minutes) and a delay in minutes, we need to determine the expected arrival times. The scheduled times are given as a list of strings. Each time is formatted as hh:mm for a 24-hour display. Here, hh is the number of hours between 00 and 23 written using two digits, while mm is the number of minutes between 00 and 59 written using two digits. Expected arrival times need to be formatted in the same way.

Write a function that takes as input a list of scheduled arrivals and a delay in minutes. The list may contain an arbitrary number of scheduled arrivals, but the delay is the same for all arrivals. The function should return a list of strings with expected arrival times formatted as hh:mm in 24-hour time notation with two digits for both hours and minutes. Remember to handle the case when the delay causes the arrival to be postponed until the next day.

As an example, consider the inputs:

>>> arrival_times(['12:37', '08:10'], 25)
['13:02', '08:35']
>>> arrival_times(['22:00', '23:00'], 102)
['23:42', '00:42']

Problem 7.9: Generalized Palindrome#

A palindrome is a word that reads the same forwards and backwards. For example, racecar is a palindrome. A sentence or phrase can also be a palindrome, were punctuation and spaces are ignored. For example, A man, a plan, a canal: Panama! is a palindrome, and so is Was it a car or a cat I saw?.

Write a function is_palindrome takes as input a string containing a word or a sentence. The function should return True if the string is a palindrome and False otherwise. The function should ignore punctuation, spaces, and capitalization. You can consider punctuation to be any of the following characters: ,.?!:;.

Test your function of the following inputs.

Hide tests
test0 = is_palindrome('racecar')
test1 = is_palindrome('A man, a plan, a canal: Panama!')
test2 = is_palindrome('Was it a car or a cat I saw?')
test3 = is_palindrome('Damejer nis berg greb sin rejemad.')
test4 = is_palindrome('A Santa at NASA.')
test5 = not is_palindrome('Morten')
test6 = not is_palindrome('Not a palindrome')
test7 = is_palindrome('Madam')
test8 = not is_palindrome('Palindromes are cool')
test9 = not is_palindrome('Level and level')
test10 = not is_palindrome('Sequence of letters.')

all_tests_passed = (test0 and test1 and test2 and test3 and test4 and test5 
        and test6 and test7 and test8 and test9 and test10) 
print("All tests passed:", all_tests_passed)

Problem 7.10: Punctuation Check#

In typed text, some punctuation marks should always be followed by a space. These include:

  • Punctuation used for ending an sentence: period (.), question mark (?), and exclamation mark (!).

  • Punctuation indicating a pause: comma (,), colon (:), and semicolon (;).

For an automatic text evaluation, we need to count the number of punctuation errors, where punctuation marks (.),(?),(,),(:), and (;) are not followed by a space. If the last character in the text is a punctuation mark, it should not be counted as an error.

Write a function punctuation_check that takes as input a string representing a typed text and returns a number of punctuation errors.

Consider the string ‘This is:a text, a text with many,many errors! But,who cares?' which has following punctuation errors: :a, ,m, and ,w. So the function should return 3 for this string.

Problem 7.11: Change Case#

Two naming conventions for multi-word variable names are: snake case and camel case. Snake case uses underscores in the place of a space. Camel case indicates the separation of words using a single capitalized letter (here, the first letter is lowercase). An example of snake case is circle_radius, and the corresponding camel case is circleRadius. Single-word variable names are the same in both conventions.

Create a function change_case that takes as input a string with the variable name in either a snake case or a camel case, and returns a string with the variable name in the other case. The variable name may be a single word or a multi-word name.

For example, consider the variable name thisIsIdentifierName. The presence of capital letters reveals that this is a camel case. The individual words are: this is identifier name. Written using snake case, this would be this_is_identifier_name.

The function should have the following specifications:

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[16], line 1
----> 1 print_docstring(change_case)

File /builds/pgcs/programmering/pg_cs/utils/print_docstring.py:88, in print_docstring(func)
     87 def print_docstring(func):
---> 88     display_markdown(autofunction_md(func))

File /builds/pgcs/programmering/pg_cs/utils/print_docstring.py:49, in autofunction_md(func, wrap_div)
     47 def autofunction_md(func, wrap_div=True):
     48     doc = docstring_parser.parse(func.__doc__)
---> 49     perform_checks(func, doc)
     50     signature_args = "(" + ', '.join([f"{p.arg_name}" for p in doc.params]) + ")"
     51     signature = f"{func.__name__}{signature_args}"

File /builds/pgcs/programmering/pg_cs/utils/print_docstring.py:30, in perform_checks(func, doc)
     28 func_args = [arg.arg for arg in tree.body[0].args.args]
     29 if source != source_dedent:
---> 30     assert func_args[0] == 'self', f"First argument of method is not 'self', but {func_args[0]}."
     31     func_args = func_args[1:]
     32 # check if all arguments are in doc and have the same names

AssertionError: First argument of method is not 'self', but name.

You can test your function with the following inputs.

Hide tests
test0 = change_case('thisIsIdentifierName') == 'this_is_identifier_name'
test1 = change_case('this_is_identifier_name') == 'thisIsIdentifierName'
test2 = change_case('justChecking') == 'just_checking'
test3 = change_case('just_checking') == 'justChecking'
test4 = change_case('one_two_three_words') == 'oneTwoThreeWords'
test5 = change_case('oneTwoThreeWords') == 'one_two_three_words'
test6 = change_case('singleword') == 'singleword'
test7 = change_case('this_is_a_valid_name') == 'thisIsAValidName'
test8 = change_case('thisIsAlsoValidName') == 'this_is_also_valid_name'
test9 = change_case('nowWhat') == 'now_what'
test10 = change_case('we_are_done') == 'weAreDone'

all_tests_passed = (test0 and test1 and test2 and test3 and test4 and test5 
                and test6 and test7 and test8 and test9 and test10)
print("All tests passed:", all_tests_passed)

Problem 7.12: Code Shift#

A bike lock has 4 dials each with the digits from 0 to 9. The code is set by turning the dials in discrete steps. Turning a dial for one step will increment the digits from 0 to 9, but digit 9 will be set to 0. The dials can be turned in both directions, and we define the positive direction as the direction where digits smaller than 9 increase. If all dials of the lock are turned at once, all code digits will change.

Write a function code_shift which as an input takes a string representing the 4-digit code, and an integer representing a turn of all dials for a number of steps in a positive or a negative direction. The function should return the string with the new code after the turn.

For example, consider the code '2638' and the shift 3. The code consists of digits 2, 6, 3, and 8. Turning the dials for three steps in a positive direction will change the first digit into 2+3=5, the second digit will become 9, the third digit will become 6. The last digit will become 1, as it changes from 8 over 9 and 0 to 1. So the function should return '5961'.

The function should be saved in a file called code_shift.py and have the following specifications:

code_shift(code, turn)

Shifts the code by a given number of steps.

Parameters:

  • code

str

String representing a 4-digit code.

  • turn

int

A number of steps when turning all lock dials.

Returns:

  • str

Code after turning all lock dials.

You can test your function with the following inputs.

Hide tests
test0 = code_shift('2638', 3) == '5961'
test1 = code_shift('0120', -3) == '7897'
test2 = code_shift('9165', 1) == '0276'

all_tests_passed = test0 and test1 and test2 
print("All tests passed:", all_tests_passed)