--- tags: Python --- # Python Self-Check 6 CS 1358 Introduction to Programming in Python Fall Semester 2022 Prof. Pai H. Chou Self-Check 1 Due Date: -- Answer the following questions to check your understanding of your material. Expect the same kind of questions to show up on your tests. For this course, we use vi and vim interchangeably. ## 1. Definitions and Short Answers 1. Given the following if-statement ``` x = int(input('enter one number: ')) y = int(input('another number: ')) if y == 0: print('sorry, cannot divide by 0!') else: print(f'{x} / {y} = {x/y}') ``` ``` What is the purpose of checking if y == 0? //check if divide by 0 What is the purpose of calling the int() function on the first two lines? //to cast input type(string) to int Will the code still work if you replace lines 1-2 with x = input('enter one number: ') y = input('another number: ') instead? Why or why not? //No,string can't divide ``` 2. The following if-statements are not correct in Python syntax. What is wrong with them and how can they be fixed? Do not change the functionality. ``` if y == 0: # do nothing else: print(f'{x} / {y} = {x/y}') if y != 0: print(f'{x} / {y} = {x/y}') else: # do nothing if x == 0: print('zero, without checking y') else if y == 0: print('sorry, cannot divide by 0!') else: print(f'{x} / {y} = {x/y}') if y == 0: print('sorry, cannot divide by zero') else: print(f'{x}/{y}={x/y}') ``` ``` #do nothing need to be place by pass else if need to be place by elif the last else should be in next line ``` 3. Given the dictionary eng = {'one': 1, 'two': 2, 'three': 3, 'four': 4} what is the value of the following expressions, and which ones cause errors? ``` ## in 代表找dict中的key 4 in eng //False 'three' in eng //True ('two', 2) in eng //False {'one': 1} in eng //error eng['three'] //3 eng[0] //key error eng[1] //key error eng['two':2] //key error ``` 4. Consider the code: ``` english={'one':1,'pan':'鍋子''cabbage':'高麗菜','pie':'派餅'} spanish = {'uno':1, 'pan':'麵包','col':'高麗菜', 'pie':'腳'} french = {'une':1, 'toi':'你', 'col':'衣領', 'pie':'鵲'} word = input('enter word to look up: ') if word in english: print(f'in English: {english[word]}') elif word in spanish: print(f'in Spanish: {spanish[word]}') elif word in french: print(f'in French: {french[word]}') else: print(f'{word} not found in dictionary') ``` When running the program, what happens when you type the following text when prompted? ``` uno //in Spanish: 1 pan //in English: 鍋子 toi //in French: 你 pie //in English: 派餅 col //in Spanish: 高麗菜 cabbage //in English: 高麗菜 1 //1 not found in dictionary ten //ten not found in dictionary ``` 5. In Question #4, if you swap lines 7-8 with lines 9-10, will the code output exactly the same results for all inputs or different for some inputs? Which? ``` uno //same pan //same toi //same pie //same col //in french: 衣領 cabbage //same 1 //same ten //same ``` 6. If the code in Question#4 is modified so all elif clauses get replaced by if, as shown in the following code: ``` if word in english: print(f'in English: {english[word]}') if word in spanish: print(f'in Spanish: {spanish[word]}') if word in french: print(f'in French: {french[word]}') else: print(f'{word} not found in dictionary') ``` ``` Suppose the user enters a word that is in english but not in french, does the print statement on the last line still get executed? Why or why not? ``` ``` yes, because the expression if word in french is false, then executed else ``` 7. Given the following code ``` passing = False if int(input('enter grade: ')) >= 60: passing = True ``` ``` what is the equivalent statement that uses both if and else? // if int(input('enter grade: ')) >= 60: passing = True else: passing = False what is the equivalent (assignment) statement that does not use if at all? // def grade(a): return a >= 60 passing = grade(input('enter grade: ')) ``` 8. Consider the following version of the code ``` word = input('enter word to look up: ') outList = [] if word in english: outList.append(f'in English: {english[word]}') if word in spanish: outList.append(f'in Spanish: {spanish[word]}') if word in french: outList.append(f'in French: {french[word]}') if not outList: print(f'{word} not found in dictionary') else: print('\n'.join(outList)) ``` ``` If line 9 is changed to if outList:, then how should the rest of the code be updated so it behaves exactly the same? //swap line 13 with 15 What does line 12 do? //output all the value of outList Is line 2 really necessary? //Yes What if line 2 is removed and line 4 is replaced by outList = [f'in English: {english[word]}'] will the code still work the same way as before? if not, how can it be fixed by adding more code? //No, if outList find word in english, then the outList will only contain english[word] ``` 9. Convert the if-else statement in the previous question (lines 9-12) into a single print() with a conditional expression as its argument. ``` print(f'{word} not found in dictionary' if not outList\ else '\n'.join(outList)) ``` 10. Convert the if-elif-elif-else statement with four suites in Question#4 (lines 5-12) into a single print() statement whose argument is a conditional expression. ``` print(f'in English: {english[word]}' if word in english \ else f'in Spanish: {spanish[word]}' if word in spanish \ else f'in French: {french[word]}' if word in french \ else f'{word} not found in dictionary') ``` 11. Is there a form of conditional expression that uses the elif keyword? If so, provide an example. ``` NO ``` 12. Given the following nested if-statement ``` if x < 0: if y > 3: print('correct') ``` rewrite it as a single if statement by combining the two conditions ``` if x < 0 and y > 3: print('correct') ``` 13. Given the following function that returns a boolean value: ``` def test(y): if y % 10: return False else: return True ``` rewrite it as a single return statement by eliminating the if-else construct completely. ``` def test(y): return (y % 10 == 0) ``` 14. Given the following function: ``` def fn(z): if z % 10: return True if z > 400: return False return True ``` rewrite it as a single return statement by eliminating all if-constructs completely. ``` def fn(z): return (z % 10 != 0) or not(z > 400) ``` 15. Write a Python function to concatenate a list of strings using a while loop. ``` def concat_str(L): # L is a list of strings # initialize local variables: # - an index into L to select one item at a time # - a result variable initialized to empty string while ____: # fill in your condition # concatenate result with the next string in L # increment the index variable # return the result string ``` ``` def concat_str(L): index = 0 str = "" while index < L.size(): str += L[index] index += 1 return str ``` 16. Write a Python function to concatenate a list of strings using a for loop. ``` def concat_str(L): # L is a list of strings initialize local variables: # - the result variable initialized to empty string for ______ : # get one string at a time from L # concatenate result with string from for loop # return the result string ``` ``` def concat_str(L): str = "" for i in L: str += i return str ``` 17. Given the source code ``` def index(L, val): i = 0 while i < len(L): if L[i] == val: break i += 1 return i if i < len(L) else -1 ``` Rewrite the code so that it does not use a break to exit the loop but still uses the same code as line 7 to return the i value. Hint: you need a separate "flag" variable that can take a True or False value; it should be initialized before the loop and is tested as part of the while-condition. The flag should be set to cause a break out of the loop. Be sure the i value is correct after exiting the loop. ``` def index(L, val): i = 0 flag = False while i < len(L): if L[i] == val: flag = True i += 1 return i if flag else -1 ``` 18. Convert the code from Problem #17 into a while-else construct (where the else clause is associated with the while construct rather than with an if clause) ``` def index(L, val): while i < len(L): if L[i] == val: break i += 1 else: return -1 return i ``` 19. Convert the code from Problem #17 into a while True: on line 3 and convert the while condition into an if condition inside the loop. ``` def index(L, val): i = 0 while True: if L[i] == val or i >= len(L): break i += 1 return i if i < len(L) else -1 ``` 20. Referring to the same code as in Problem #17, what happens if you replace break on line 5 with continue? For example, ``` >>> L = "abaca" >>> index(L, 'a') Does the function return a value or go into an infinite loop? Why? Yes,go into an infinite loop, when execute L[i] == val then continue >>> L = "abcde" >>> index(L, 'z') Does the function return a value or go into an infinite loop and why? Yes,will return -1, because the i will exceed len(L) Try to predict the behavior of the code before you try running it to verify your answer. ``` 21. In the code ``` def index(L, val): i = 0 while i < len(L): if L[i] == val: break i = i + 1 else: return -1 return i ``` What causes the else suite (lines 7-8) to be executed? If line 5 is executed, will line 8 be executed? ``` when i >= len(L) No ``` 22. Given the code ``` ESdict = { 'one': 'uno', 'dos': 'two', 'three': 'tres'} word = input('enter an English word:') while word != '': if word in ESdict: print(f'{word} in Spanish is {ESdict[word]}') else: print(f'{word} not in dictionary') word = input('enter an English word:') ``` However, there is redundancy because line 2 and line 8 are exactly the same (except for indentation). How can this code be rewritten to eliminate this redundancy? ``` ESdict = { 'one': 'uno', 'dos': 'two', 'three': 'tres'} while True: word = input('enter an English word:') if(word == ''): break if word in ESdict: print(f'{word} in Spanish is {ESdict[word]}') else: print(f'{word} not in dictionary') ``` 23. Given the following code ``` def StackInterpreter(): L = [] while True: line = input('command? ') words = line.split() if len(words) == 0: pass elif words[0] == 'show': print(L) elif words[0] == 'push': L.extend(words[1:]) elif words[0] == 'pop': print(L.pop()) elif words[0] == 'quit': break else: print('unknown command') ``` If the elif keywords on lines 8, 10, 12, 14 are replaced by if, will the code still behave the same way as far as the user is concerned? Why? ``` No, it will always print unknown command ``` 24. Using the same code from the previous problem, line 7 can be replaced by a single-keyword statement and the code still behaves the same way to the user. What is the keyword? Explain. ``` continue, because continue statement will execute next loop ``` 25. Using the same code from the previous problem, line 15 can be replaced by a single-keyword statement and the code still behave the same way. What is it? ``` return ``` 26. Given the code ``` def StackInterpreter(): L = [] while True: line = input('command? ') words = line.split() if len(words) == 0: continue if words[0] == 'show': print(L) continue if words[0] == 'push': L.extend(words[1:]) continue if words[0] == 'pop': print(L.pop()) continue if words[0] == 'quit': break print('unknown command') ``` Why doesn't line 19 need to be inside an else-clause but can be an unconditional statement at the same level as all preceding if-statements? ``` because every command will goes into if and execute continue ``` 27. Given the Python code ``` def product(L): p = 1 for i in range(len(L)): p = p * L[i] return t ``` ``` Rewrite it as a while-loop // def product(L): p = 1 i = 0 while i < len(L): p = p * L[i] i += 1 return p Rewrite it as a Pythonic for-loop // def product(L): p = 1 for i in L: p = p * i return p ``` 28. What is the value of the expression ``` list(enumerate("abcde")) //[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')] list(enumerate(range(5, 10))) //[(0, 5), (1, 6), (3, 7), (4, 8), (5, 9)] list(enumerate(['Sun', 'Mon', 'Tue', 'Wed'])) //[(0, 'Sun'), (1, 'Mon'), (2, 'Tue'), (3, 'Wed')] list(enumerate(['Jan', 'Feb', 'Mar'], start=1)) //[(1, 'Jan'), (2, 'Feb'), (3, 'Mar')] ``` 29. Rewrite the following code using a Pythonic for-loop: ``` def find(L, val): i = 0 while i < len(L): if L[i] == val: return i i = i + 1 return -1 ``` ``` def find(L, val): i = 0 for i, ele in enumerate(L): if(ele == val): return i return -1 ``` ## 2. Programming 1. Write a Python program named dateconv.py to prompt the user for date in US format of mm/dd/yyyy (e.g., '02/15/2019' and outputs it in the full format of 'February 15, 2019'. You may assume the dates are given as decimal literals separated by '/', but you should also check if the dates are in range. If the dates are out of range, then you should inform the user what is wrong. For instance $ python3 dateconv.py enter date in mm/dd/yyyy: 02/15/2019 February 15, 2019 enter date in mm/dd/yyyy: 02/29/2019 Invalidate day 29 for February: not a leap year enter date in mm/dd/yyyy: 01/01/2001 January 1, 2001 enter date in mm/dd/yyyy: 13/10/2038 Invalid month 13: should be between 01 and 12 enter date in mm/dd/yyyy: 10/32/2019 Invalid day for October: should be between 01..31 enter date in mm/dd/yyyy: 04/31/2019 Invalid day for April: should be between 01..30 enter date in mm/dd/yyyy: quit bye $ _ Hint: Build up your program one piece at a time. First, simply use a loop to prompt for input and check for 'quit'. If not quit then first use a print statement to check if the input is as you expect. Once confirmed, you can use str's split() method to split a string by its separator ('/' in this case). Then, you can check the array of strings, assuming you can convert them to int, and check if each one is within range. Month can be checked easily. Day depends on the month, and for the month of February, day also depends on whether the year is a leap year (28 or 29 days). If any field is invalid, then report the error and loop again. If all fields are correct then display the full month string. You may store the names of the months all in a list indexed by the month number or in a dictionary keyed by the month. You may use the leap year function from a previous lecture. ## 3. Small Programming Project [somewhat challenging] Write a Python program named long_multiply(a, b) to return a string that shows the steps in a long multiplication. (note: a is called the multiplier, and b is the multiplicand) For example ``` >>> print(long_multiply(12, 34)) 12 x)34 ---- 48 36 ---- 408 ``` Hint: You should construct the return value of the function by concatenating different strings together. It is probably easier if you just append the strings into a list and join them by '\n'.join(listOfStrings). Before you join the strings, you need to determine the width to format each line. This is the maximum number of characters needed to represent the multiplier, multiplicand + 2 (because 'x)' takes two positions), and the product. Create the following strings and append each one into a list: string for the multiplier with the width (right aligned), 'x)' concatenated the multiplicand formatted with width-2 (also right-aligned), string of '-' repeated for width times loop over the partial products of multiplier * each digit of the multiplicand, but each time shifted one position to the left. anotherr string of '-' repeated for width times finally, the product as a string, formatted to the same width, right aligned. finally, return '\n'.join( list of strings created in above steps ) Note: you may assume a and b are both nonnegative integers. Your code should work with integers of any number of digits.