Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Chapter 4 – Lists With this chapter, we begin a detailed discussion of the concepts and techniques of computer programming. We start by looking at issues related to the representation, manipulation, and input/ output of data—fundamental to all computing. OBJECTIVES After reading this chapter and completing the exercises, you will be able to: Explain what a list is in programming Describe the typical operations performed on lists Explain what is meant by list traversal Effectively create and use lists in Python Explain the difference between lists and tuples in Python Explain what a sequence is in Python Describe the sequence operations common to lists, tuples, and strings in Python Effectively use nested lists and tuples in Python Effectively iterate over lists (sequences) in Python Effectively use for statements for iterative control in Python Use the range function in Python Explain how list representation relates to list assignment in Python Effectively use list comprehensions in Python Write Python programs using sequences Chapter Overview The purpose of this chapter is to introduce to students the fundamental notion of a list structure, and to lists (sequences) in Python. Because of the natural use of for loops and lists, the for statement is also introduced here. Section 4.1 – What is a List? Section 4.1.1 describes a list as a linear data structure, in which each element of the list is accessed by a particular index value. It is stated that it is customary that programming language use zero-based indexing. Students are warned here about “off by one” errors. Section 4.1.2 introduces the fundamental list operations of retrieve, update, insert, remove and append. Section 4.1.3 introduces the notion of list traversal. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 1 Section 4.2 – Lists (Sequences) in Python In this section, lists (sequences) in Python are introduced. Section 4.2.1 defines a list in Python as a linear data structure of variable length, allowing for mixed-type elements. The fundamental list operations as perfomed in Python are covered. The empty list is also noted here. Section 4.2.2 defines a tuple in Python as an immutable list, denoted by the use of parentheses rather than square brackets. It is pointed out that, as opposed to lists, tuples of one element must include a comma following the element. The empty tuple is also noted here. Because tuples are immutable, it is stated that the delete, update, insert and append operations are not defined on tuples. PEDAGOGICAL NOTE: The reason that Python requires a trailing comma for tuple containing exactly one element is to distinguish the tuple from an expression. It is likely that students will initially forget this, so it is something worth emphasizing. Section 4.2.3 presents the more general sequence type, in which lists, tuples and strings belong. It is noted that strings, like tuples, as immutable. A table in included that demonstrates the sequence operations as applied to each sequence type: length, select (access), slice, count, index (returns the index value of the first occurrence of a given element), membership, concatenation, minimum/maximum values, and a sum (only applicable to sequences of numeric type). PEDAGOGICAL NOTE: The notion of an overloaded operator is introduced here with the example of the plus sign (+) used for both arithmetic addition and the concatenation of strings. Section 4.2.4 discusses nested lists as a means of creating arbitrarily complex data structures. Section 4.2.5 Let’s Apply It – “A Chinese Zodiac Program” This Let’s Apply It section involves the use of tuples, as well as the datetime module (for determining the current year). The program example displays the characteristics from the Chinese Zodiac associated with a given birth year. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 2 Section 4.3 – Iterating over Lists (Sequences) in Python In this section, the for loop is introdcuced, and list iteration by use of both for loops and while loops is demonstrated. Section 4.3.1 introduces for loops for the construction of definite loops, and the concept of a loop variable. The construction of definite loops by use of the while statement (from Chapter 3) versus the for statement is demonstrated. Example for loops are given showing iteration over a specific sequence (including iteration over strings). Section 4.3.2 introduces the range function for generating a sequence of integers which a for statement can iterate over. Sequential integers are generated within a specified range, with an optional “skip value” provided to generate integers at fixed intervals. PEDAGOGICAL NOTE: The sequence of integers generated by the range function includes the specified initial value, up to but not including the terminating value. This is something that may need to be reiterated with students. Also, the range function is a generator function. Thus, calling this function from the Python shell will only echo back the call, and not evaluate to the sequence as expected. The reason for this should be explained to students. Section 4.3.3 discusses when it is appropriate to directly iterarate over the elements of a list, versus iterating over a list’s index values (in which case the loop variable is called an index variable). Section 4.3.4 discusses the use of while loop for when conditionally iterating over a list (e.g, when searching for a particular value). PEDAGOGICAL NOTE: The break statement is only parenthetically mentioned. It use is avoided in the text in favor of a more structured approach. For those who desire to introduce students to the use of the break statement, supplemental material will need to be used. Section 4.3.5 Let’s Apply It – “Password Encryption/Decryption Program” This Let’s Apply It section involves the use of the for loop, as well as nested sequences (tuples). The program allows the user to encrypt and decrypt user passwords. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 3 Section 4.4 – More on Python Lists In this section, the assignment of lists in Python is discussed, and list comprehensions, a more flexible means of generating lists than the range function procides, is introduced. Section 4.4.1 explains how lists are represented as a reference (without introducing the term reference at this point). The consequences of this for the assignment of lists (as a shallow copy) is described. The need for deep copying at times is mentioned, stating that that is covered in Chapter 6 (with the discussion on objects). Section 4.4.2 introduces list comprehensions in Python. The are described as a mean of providing more varied sequences than the range function can generate. Section 4.5 COMPUTATIONAL PROBLEM SOLVING – Calendar Year Program This Computational Problem Solving section demonstrates the development of a program that displays a complete calendar year. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 4 Section 4.5.1 states the problem as displaying a calendar year for any year between 1800 and 2099 (formatted as shown above). Section 4.5.2 analyzes the problem. The computational issues for this problem are similar to the calendar month program of Chapter 3. An algorithm for computing the day of the week for January 1 of any given year in the range 1800-2099. The remaining issues is the display of all of the months of the given year. Since the calendar should be displayed three months across, a method for properly displaying the year needs to be developed. Section 4.5.3 presents a program design for this problem. The description of data needed for this program is the entered year, whether the year is a leap year or not, the number of days in each month, and which day January 1st of the year falls on. Given that information, the calendar year can be displayed. The algorithmic approach involves determining the day of the week for a specific day of the specified year, January 1st. Thus, a simplified version of the day of the week algorithm (introduced earlier) is developed. To determine the day of the week for January 1 of a given year: 1. Let century_digits be equal to the first two digits of the year. 2. Let year_digits be equal to the last two digits of the year. 3. Let value be equal to year_digits + floor(year_digits / 4) 4. If century_digits equals 18, then add 2 to value, else if century_digits equals 20, then add 6 to value. 5. If year is not a leap year then add 1 to value. 6. Set value equal to (value + 1) mod 7. 7. If value is equal to 1 (Sunday), 2 (Monday), … 0 ( Saturday). Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 5 Overall Program Steps Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 6 Section 4.5.4 demonstrates implementation and testing of the program. The program is developed in three stages. Stage 1 implements and tests the modified day of the week algorithm for determining the day of the week that January 1 st falls on for a given year (between 1800-2099). The code is tested for various years in the 1800s, 1900s, and 2000 including leap years and non-leap years. Stage 2 adds code to construct the complete data structure needed to store a calendar year. It begins as an empty list and incrementally built as a nested structure. An intentional error is contained in the program, resulting in a tuple index out of range error, related to the tuple of month names defined in the program. From the Python shell, it is discovered that the length of the month_names tuple is 11, and not 12. The value of the tuple is displayed as, ('January', 'February', 'March', 'April', 'May', 'September', 'October', 'November', 'December') >>> 'JuneJuly', 'August', Inspecting the assignment of month_names in the program, the problem is found. A comma was omitted for the month of June in the tuple, month_names = ('January', 'February', 'March', 'April', 'May', 'June' 'July', 'August', 'September', 'October', 'November', 'December') Further testing in the shell shows that the program error is fully explained by the omitted comma, >>> 'June' 'July' 'JuneJuly' given that the consecutive strings ‘June’ and ‘July’ are implicitly concatenated into one string. The final stage of the program displays a complete calendar year. The program is tested with the test plan for the calendar month program of Chapter 3. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 7 SOLUTIONS TO CHAPTER EXERCISES Section 4.1 1. (a) Give the index values of all the odd numbers in the following list representation assuming zero-based indexing. 23 16 14 33 19 6 11 ANSWER: 0, 3, 4, 6 (b) How many elements would be looked at when the list is traversed (from top to bottom) until the value 19 was found? ANSWER: five elements Section 4.2 2. Which of the following lists are syntactically correct in Python? (a) [1, 2, 3, 'four'] (b) [1, 2, [3, 4]] (c) [[1, 2, 3]['four']] ANSWER: (a) and (b) 3. For lst = [4, 2, 9, 1], what is the result of each of the following list operations? (a) (b) (c) (d) lst[1] lst.insert(2, 3) del lst[3] lst.append(3) ANSWERS: (a) 2 (b) [4, 2, 3, 9, 1] (c) [4, 2, 9] (d) [4, 2, 9, 1, 3] Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 8 4. For fruit = ['apple', 'banana', 'pear', 'cherry'], use a list operation to produce the list ['apple', 'banana', 'cherry'] from this list. ANSWER: del fruit[2] NOTE: The remove Python list operation, which allows the removal (of the first occurrence) of a given list element by value, is not introduced in this chapter (and in retrospect probably should have been). It is listed in the Programmers’ Reference, however, meant to be a more complete (and convenient ) reference for the Python programming language. Therefore, another possible answer for this question is: fruit.remove('pear'). 5. For list of integers, lst, give the code to retrieve the maximum value of the second half of the list. ANSWER: max(lst[len(lst) // 2:]) NOTE: It was not intended that students be concerned with lists that do not have an even number of elements. 6. For variable product_code containing a string of letters and digits, (a) Give an if statement that outputs “Verified” if product_code contains both a ‘Z’ and a ‘9’, and outputs “Failed” otherwise. if 'Z' in product_code and '9' in product_code: print('Verified') else: print('Failed') (b) Give a Python instruction that prints out just the last three characters in product_code. ANSWER: product_code[len(product_code) - 3:] 7. Which of the following are valid operations on tuples (for tuples t1 and t2)? (a) len(t1) (b) t1 + t2 (c) t1.append(t2) (d) t1.insert(t2) ANSWERS: (a), (b) Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 9 8. For str1 = 'Hello World', answer the following, (a) Give an instruction that prints the fourth character of the string. ANSWER: print(str1[3]) (b) Give an instruction that finds the index location of the first occurrence of the letter 'o' in the string. ANSWER: str1.index('o') 9. For a nested list lst that contains sublists of the form [n1, n2, n3] for integer values n1, n2 and n3, (a) Give a Python instruction that determines the length of the list. ANSWER: len(lst) (b) Give Python code that determines how many total integer values there are in list lst. num_ints = 0 for k in range(0, len(lst)): num_ints = num_ints + len(lst[k]) print(num_ints) or num_ints = 0 for k in lst: num_ints = num_ints + len(k) print(num_ints) (c) Give Python code that totals all the integer values in list lst. total = 0 lst = [[1], [3, 4], [5, 6, 7]] for k in range(0, len(lst)): for n in range(0, len(lst[k])): total = total + lst[k][n] print(total) or total = 0 lst = [[1], [3, 4], [5, 6, 7]] for k in lst: for element in k: total = total + element print(total) (d) Give an assignment statement that assigns the third integer of the fourth element (sublist) of lst to the value 12. ANSWER: lst[3][2] = 12 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 10 Section 4.3 10. For a list of integers named nums, (a) Give a while loop that adds up all the values in nums. total = 0 k = 0 while k <= len(nums): total = total + nums[k] k = k + 1 (b) Write a for loop that adds up all the values in nums in which the loop variable is assigned each value in the list. total = 0 for k in nums: total = total + k (c) Write a for loop that adds up all the elements in nums in which the loop variable is assigned to the index value of each element in the list. total = 0 for k in range(0, len(nums)): total = total + nums[k] (d) Write a for loop that displays the elements in nums backwards. for k in range(len(nums)-1, -1, -1): print('k = ', k) print(nums[k]) (e) Write a for loop that displays every other element in nums. for k in range(0, len(nums), 2): print('k = ', k) print(nums[k]) Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 11 Section 4.4 11. For list1 = [1, 2, 3, 4] and list2 = [5, 6, 7, 8], give the values of list1[0] and list2[0] where indicated. (a) list1[0] = 10 list2[0] = 50 list1[0] ______ list2[0] ______ (b) list2 = list1 list1[0] ______ list2[0] ______ (c) list2[0] = 15 list1[0] ______ list2[0] ______ (d) list1[0] = 0 list1[0] ______ list2[0] ______ ANSWERS: (a) (b) (c) (d) list1[0] equals 10 list1[0] equals 10 list1[0] equals 15 list1[0] equals 0 list2[0] equals 50 list2[0] equals 10 list2[0] equals 15 list2[0] equals 0 12. Give an appropriate list comprehension for each of the following. (a) Producing a list of consonants that appear in string w. ANSWER: vowels = ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U') [ch for ch in w if ch not in vowels] (b) Producing a list of numbers between 1 and 100 that are divisable by 3. ANSWER: [x for x in range(0, 101) if x % 3 == 0] (c) Producing a list of numbers, zero_values from a list of floating-point values, data_values, that are within some distance, epsilon, from 0. ANSWER: zero_values = [x for x in values if abs(x - 0) <= epsilon] Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 12 SOLUTIONS TO PYTHON PROGRAMMING EXERCISES P1. Write a Python program that prompts the user for a list of integers, stores in a list only the values between 1-100, and displays the resulting list. empty_str = '' num_list = [] print('Enter a series of integers,one per line (hit return when done)') entry = input('Enter: ') while entry != empty_str: num = int(entry) if num >= 0 and num <= 100: num_list.append(num) entry = input('Enter: ') print(num_list) P2. Write a Python program that prompts the user for a list of integers, stores in a list only the values that are in tuple valid_values, and displays the resulting list. valid_values = [1, 4, 8, 11, 16, 21] num_list = [] empty_str = '' print('Enter a series of integers,one per line (hit return when done)') entry = input('Enter: ') while entry != empty_str: num = int(entry) if num in valid_values: num_list.append(num) entry = input('Enter: ') print(num_list) P3. Write a Python program that prompts the user for a list of integers and stores them in a list. For all values that are greater than 100, the string 'over' should be stored instead. The program should display the resulting list. num_list = [] empty_str = '' print('Enter a series of integers,one per line (hit return when done)') entry = input('Enter: ') Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 13 while entry != empty_str: num = int(entry) if num <= 100: num_list.append(num) else: num_list.append('over') entry = input('Enter: ') print(num_list) P4. Write a Python program that prompts the user to enter a list of first names and stores in a list. The program should display how many times the letter 'a' appears within the list. num_of_a = 0 names_list = [] empty_str = '' print('Enter a series of first names,one per line (hit return when done)') entry = input('Enter: ') while entry != empty_str: names_list.append(entry) entry = input('Enter: ') for name in names_list: for ch in name: if ch == 'a' or ch == 'A': num_of_a = num_of_a + 1 print('There are', num_of_a, 'occurrences in the names entered') P5. Write a Python program that prompts the user to enter a list of words and stores in a list only those words whose first letter occurs again within the word (for example, 'Baboon'). The program should display the resulting list. word_list = [] empty_str = '' print('Enter a series of words, one per line (hit return when done)') word = input('Enter: ') while word != empty_str: if word[0] in word[1:]: word_list.append(word) word = input('Enter: ') print(word_list) Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 14 P6. Write a Python program that prompts the user to enter types of fruit, and how many pounds of fruit there are for each type. The program should then display the information in the form fruit, weight listed in alphabetical order, one fruit type per line as shown below, Apple, 6 lbs. Banana, 11 lbs. etc. fruit_list = [] empty_str = '' print('Enter type of fruit, and how many pounds of each type there are') print('(hit return when done)\n') entered_fruit = input('Enter fruit: ') while entered_fruit != empty_str: num_pounds = int(input('Enter number of pounds of ' + entered_fruit + ': ')) if len(fruit_list) == 0: fruit_list = [(entered_fruit, num_pounds)] else: insert_index = 0 index = 0 location_found = False while index < len(fruit_list) and not location_found: if fruit_list[index][0] < entered_fruit: index = index + 1 else: fruit_list.insert(index,(entered_fruit, num_pounds)) location_found = True entered_fruit = input('\nEnter fruit: ') print(fruit_list) NOTE: This problem was intended to have students make use of the sort method. However, this method does not provide the abiity to sort complex data (in this case, a list of tuples of the form (fruit_type, num_pounds) ). The built-in function sorted provides such flexibility, However, it is not introduced in the chapter, and involves more advanced concepts. Therefore, this solution relies on the list of fruit to be constructed in alphabetical order, rather than being sorted after the list is built. Thus, the problem is a but more difficult than intended, and would most likely require giving students some help on how this can be done (but searching for the proper index location of each new inserted fruit type, and making use of the insert method for performing the insertion. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 15 P7. Write a Python program that prompts the user to enter integer values for each of two lists. It then should displays whether the lists are of the same length, whether the elements in each list sum to the same value, and whether there are any values that occur in both lists. num_list1 = [] num_list2 = [] empty_str = '' print('Enter a series of integers, one per line') print('(hit return when done)\n') entry = input('Enter: ') while entry != empty_str: num_list1.append(int(entry)) entry = input('Enter: ') print('\nEnter a series of integers of a second list,one per line') print('(hit return when done)\n') entry = input('Enter: ') while entry != empty_str: num_list2.append(int(entry)) entry = input('Enter: ') if len(num_list1) == len(num_list2): print('The two entered lists are the same length') else: print('The two entered lists are NOT the same length') if sum(num_list1) == sum(num_list2): print('The two entered lists sum to the same value') else: print('The two entered lists do NOT sum to the same value') found = False k = 0 while k <= len(num_list1) and not found: if num_list1[k] in num_list2: found = True else: k = k + 1 if found: print('The two lists have common values') else: print('The two lists do not have any values in common') Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 16 SOLUTIONS TO PROGRAM MODIFICATION PROBLEMS M1. Chinese Zodiac Program: Japanese and Vietnamese Variations Modify the Chinese Zodiac program in the chapter to allow the user to select the Chinese Zodiac, the Japanese Zodiac, or the Vietnamese Zodiac. The Japanese Zodiac is the same as the Chinese Zodiac, except that “Pig” is substituted with “Wild Boar.” The Vietnamese Zodiac is also the same except that the “Ox” is substituted with “Water Buffalo” and “Rabbit” is replaced with “Cat.” import datetime # init ox_type = 'Ox' rabbit_type = 'Rabbit' pig_type = 'Pig' rat = 'Forthright, industrious, sensitive, intellectual, sociable' ox = 'Dependable, methodical, modest, born leader, patient' tiger = 'Unpredictable, rebellious, passionate, daring, impulsive' rabbit = 'Good friend, kind, soft-spoken, cautious, artistic' dragon = 'Strong, self-assured, proud, decisive, loyal' snake = 'Deep thinker, creative, responsible, calm, purposeful' horse = 'Cheerful, quick-witted, perceptive, talkative, open-minded' goat = 'Sincere, sympathetic, shy, generous, mothering' monkey = 'Motivator, inquisitive, flexible, innovative, problem solver' rooster = 'Organized, self-assured, decisive, perfectionist, zealous' dog = 'Honest, unpretentious, idealistic, moralistic, easy going' pig = 'Peace-loving, hard-working, trusting, understanding, thoughtful' characteristics = (rat, ox, tiger, rabbit, dragon, snake, horse, goat, monkey, rooster, dog, pig) terminate = False # program greeting print('This program will display your Chinese, Japanese or Vietnamese') print('zodiac sign and associated personal characteristics.\n') # get zodiac type zodiac_type = input('Enter (C)hinese, (J)apanese, or (V)ietnamese: ') while zodiac_type not in ('C', 'J', 'V', 'c', 'j', 'v'): zodiac_type = input('Enter (C)hinese, (J)apanese, or (V)ietnamese: ') # update zodiac animals if zodiac_type in ('J', 'j'): pig_type = 'Wild Boar' elif zodiac_type in ('V', 'v'): ox_type = 'Water Buffalo' rabbit_type = 'Cat' zodiac_animals = ('Rat', ox_type, 'Tiger', rabbit_type, 'Dragon', 'Snake', 'Horse', 'Goat', 'Monkey', 'Rooster', 'Dog', pig_type) # get current year from module datetime current_yr = datetime.date.today().year Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 17 while not terminate: # get year of birth birth_year = int(input('Enter your year of birth (yyyy): ')) while birth_year < 1900 or birth_year > current_yr: print('Invalid year. Please re-enter\n') birth_year = int(input('Enter your year of birth (yyyy): ')) # output results cycle_num = (birth_year - 1900) % 12 print('Your Chinese zodiac sign is the', zodiac_animals[cycle_num],'\n') print('Your personal characteristics ...') print(characteristics[cycle_num]) # continue? response = input('\nWould you like to enter another year? (y/n): ') while response != 'y' and response != 'n': response = input("Please enter 'y' or 'n': ") if response == 'n': terminate = True This program will display your Chinese, Japanese or Vietnamese zodiac sign and associated personal characteristics. Enter (C)hinese, (J)apanese, or (V)ietnamese: C Enter your year of birth (yyyy): 1953 Your Chinese zodiac sign is the Snake Your personal characteristics ... Deep thinker, creative, responsible, calm, purposeful Would you like to enter another year? (y/n): y Enter your year of birth (yyyy): 1954 Your Chinese zodiac sign is the HorseGoat Your personal characteristics ... Cheerful, quick-witted, perceptive, talkative, open-minded Would you like to enter another year? (y/n): n >>> Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 18 This program will display your Chinese, Japanese or Vietnamese zodiac sign and associated personal characteristics. Enter (C)hinese, (J)apanese, or (V)ietnamese: J Enter your year of birth (yyyy): 1959 Your Chinese zodiac sign is the Wild Boar Your personal characteristics ... Peace-loving, hard-working, trusting, understanding, thoughtful Would you like to enter another year? (y/n): n >>> This program will display your Chinese, Japanese or Vietnamese zodiac sign and associated personal characteristics. Enter (C)hinese, (J)apanese, or (V)ietnamese: V Enter your year of birth (yyyy): 1949 Your Chinese zodiac sign is the Water Buffalo Your personal characteristics ... Dependable, methodical, modest, born leader, patient Would you like to enter another year? (y/n): n >>> M2. Chinese Zodiac Program: Improved Accuracy The true Chinese Zodiac does not strictly follow the year that a given person was born. It also depends on the month and date as well, which vary over the years. Following are the correct range of dates for each of the Zodiac symbols for the years 1985 to 2008 (which includes two full cycles of the zodiac). Modify the Chinese Zodiac program in the chapter so that the user is prompted to enter their date of birth, including month and day, and displays the name and characteristics of the corresponding Chinese Zodiac symbol based on the more accurate zodiac provided here. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 19 # Chinese Zodiac Program (Figure 4-8) # MODIFICATION: Determination of zodiac animal for year/month/day of birth import datetime # init zodiac_animals = ('Rat', 'Ox', 'Tiger', 'Rabbit', 'Dragon', 'Snake', 'Horse', 'Goat', 'Monkey', 'Rooster', 'Dog', 'Pig') zodiac_1984_2007 = ((2, (1, (2, (2, 2), (2, 20), (2, 9), (1, 29), (2, 17), (2, 6), 27), (2, 15), (2, 4), (1, 23), (2, 10), (1, 31), 19), (2, 7), (1, 28), (2, 16), (2, 5), (1, 24), 12), (2, 1), (1, 22), (2, 9), (1, 29), (2, 18)) num_days_in_month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) rat = 'Forthright, industrious, sensitive, intellectual, sociable' ox = 'Dependable, methodical, modest, born leader, patient' tiger = 'Unpredictable, rebellious, passionate, daring, impulsive' rabbit = 'Good friend, kind, soft-spoken, cautious, artistic' dragon = 'Strong, self-assured, proud, decisive, loyal' snake = 'Deep thinker, creative, responsible, calm, purposeful' horse = 'Cheerful, quick-witted, perceptive, talkative, open-minded' goat = 'Sincere, sympathetic, shy, generous, mothering' monkey = 'Motivator, inquisitive, flexible, innovative, problem solver' rooster = 'Organized, self-assured, decisive, perfectionist, zealous' dog = 'Honest, unpretentious, idealistic, moralistic, easy going' pig = 'Peace-loving, hard-working, trusting, understanding, thoughtful' characteristics = (rat, ox, tiger, rabbit, dragon, snake, horse, goat, monkey, rooster, dog, pig) terminate = False Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 20 # program greeting print('This program will display your Chinese zodiac sign and associated') print('personal characteristics based on your month/day/year of birth.\n') get current year from module datetime current_yr = datetime.date.today().year while not terminate: # get year of birth birth_year = int(input('Enter your year of birth (1984-2007): ')) while birth_year < 1984 or birth_year > 2007: print('Invalid year. Please re-enter\n') birth_year = int(input('Enter your year of birth (yyyy): ')) birth_month = int(input('Enter the month you were born (1-12): ')) while birth_month < 1 or birth_month > 12: print('Invalid month. Please re-enter\n') birth_month = int(input('Enter the month you were born (1-12): ')) if birth_month == 2 and (birth_year % 4 == 0) and \ (not (birth_year % 100 == 0) or (birth_year % 400 == 0)): last_day_of_month = 29 else: last_day_of_month = num_days_in_month[birth_month - 1] birth_day = int(input('Enter the day of the month you were born: ')) while birth_day < 1 or birth_month > last_day_of_month: print('Invalid date. Please re-enter\n') birth_day = int(input('Enter the day of the month you were born: ')) # determine zodiac symbol cycle_num = (birth_year - 1984) if birth_month < zodiac_1984_2007[cycle_num][0]: cycle_num = (cycle_num - 1) % 12 elif birth_month == zodiac_1984_2007[cycle_num][0]: if birth_day < zodiac_1984_2007[cycle_num][1]: cycle_num = (cycle_num - 1) % 12 # output results print('Your Chinese zodiac sign is the', zodiac_animals[cycle_num % 12],'\n') print('Your personal characteristics ...') print(characteristics[cycle_num % 12]) # continue? response = input('\nWould you like to enter another year? (y/n): ') while response != 'y' and response != 'n': response = input("Please enter 'y' or 'n': ") if response == 'n': terminate = True Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 21 This program will display your Chinese zodiac sign and associated personal characteristics based on your month/day/year of birth. Enter your year of birth (1984-2007): 1983 Invalid year. Please re-enter Enter your year of birth (yyyy): 1984 Enter the month you were born (1-12): 1 Enter the day of the month you were born: 1 Your Chinese zodiac sign is the Pig Your personal characteristics ... Peace-loving, hard-working, trusting, understanding, thoughtful Would you like to enter another year? (y/n): y Enter your year of birth (1984-2007): 1984 Enter the month you were born (1-12): 2 Enter the day of the month you were born: 2 Your Chinese zodiac sign is the Rat Your personal characteristics ... Forthright, industrious, sensitive, intellectual, sociable Would you like to enter another year? (y/n): y Enter your year of birth (1984-2007): 1988 Enter the month you were born (1-12): 2 Enter the day of the month you were born: 17 Your Chinese zodiac sign is the Dragon Your personal characteristics ... Strong, self-assured, proud, decisive, loyal Would you like to enter another year? (y/n): 2007 Please enter 'y' or 'n': y Enter your year of birth (1984-2007): 2007 Enter the month you were born (1-12): 1 Enter the day of the month you were born: 1 Your Chinese zodiac sign is the Dog Your personal characteristics ... Honest, unpretentious, idealistic, moralistic, easy going Would you like to enter another year? (y/n): y Enter your year of birth (1984-2007): 2007 Enter the month you were born (1-12): 2 Enter the day of the month you were born: 18 Your Chinese zodiac sign is the Pig Your personal characteristics ... Peace-loving, hard-working, trusting, understanding, thoughtful Would you like to enter another year? (y/n): n >>> Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 22 NOTE: This problem is a bit challenging in terms of designing an appropriate data structure. In this solution program, only the starting date of each Chinese calendar year is stored. Since the Zodiac cycle of symbols (zodiac_animals) is stored in the program, the task is to determine where in the cycle a given person’s birthday falls. The place in the cycle_num is initialized based on the year of birth: cycle_num = (birth_year - 1984). If the person’s birthday day, however, falls before the start of the Chinese new year for that year, then the cycle_num is set to the previous year: cycle_num = (cycle_num - 1) % 12. When the current value of cycle_num is 0, this relies on the fact that -1 % 12 is 11. Otherwise, cycle_num remains as is. Additionally, this program performs input error checking on the year (between 1984 and 2007), month, and day (for the number of days in a given month. The program accounts for the fact that the number of days in February depends on leap years. Such input error checking could be made optional. M3. Password Encryption/Decryption Program: Multiple Executions Modify the Password Encryption/Decryption program in the chapter so that it allows the user to continue to encrypt and decrypt passwords until they quit. # Password Encryption/Decryption Program (Figure 4-13) # MODIFICATION: Multiple Executions # init password_out = '' case_changer = ord('a') - ord('A') encryption_key = (('a','m'), ('b','h'), ('c','t'), ('d','f'), ('e','g'), ('f','k'), ('g','b'), ('h','p'), ('i','j'), ('j','w'), ('k','e'),('l','r'), ('m','q'), ('n','s'), ('o','l'), ('p','n'), ('q','i'), ('r','u'), ('s','o'), ('t','x'), ('u','z'), ('v','y'), ('w','v'), ('x','d'), ('y','c'), ('z','a')) quit = False # program greeting print('This program will encrypt and decrypt user passwords\n') while not quit: # get selection (encrypt/decrypt) which = input('Enter (e) to encrypt a password, and (d) to decrypt: ') while which != 'e' and which != 'd': which = input("\nINVALID - Enter 'e' to encrypt, 'd' to decrypt: ") encrypting = (which == 'e') # assigns True or False # get password password_in = input('Enter password: ') # perform encryption / decryption if encrypting: from_index = 0 to_index = 1 else: from_index = 1 to_index = 0 case_changer = ord('a') - ord('A') password_out = '' Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 23 for ch in password_in: letter_found = False for t in encryption_key: if ('a' <= ch and ch <= 'z') and ch == t[from_index]: password_out = password_out + t[to_index] letter_found = True elif ('A' <= ch and ch <= 'Z') and \ chr(ord(ch) + 32) == t[from_index]: password_out = password_out + \ chr(ord(t[to_index]) - case_changer) letter_found = True if not letter_found: password_out = password_out + ch # output if encrypting: print('Your encrypted password is:', password_out) else: print('Your decrypted password is:', password_out) # continue? response = input('\nEncrypt/decrypt another password? (y/n): ') while response not in ('Y', 'N', 'y', 'n'): response = input('Encrypt/decrypt another password? (y/n): ') if response in ('N', 'n'): quit = True This program will encrypt and decrypt user passwords Enter (e) to encrypt a password, and (d) to decrypt: e Enter password: Pizza2Day! Your encrypted password is: Njaam2Fmc! Encrypt/decrypt another password? (y/n): y Enter (e) to encrypt a password, and (d) to decrypt: d Enter password: Njaam2Fmc! Your decrypted password is: Pizza2Day! Encrypt/decrypt another password? (y/n): n >>> Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 24 M4. Password Encryption/Decryption Program: Secure Password Check Modify the Password Encryption/Decryption program in the chapter so that the program rejects any entered password for encryption that is not considered “secure” enough. A password is considered secure if it contains at least eight characters, one digit, and one special character (!, #, etc). # Password Encryption/Decryption Program (Figure 4-13) # MODIFICATION: Secure Password Check # init password_out = '' case_changer = ord('a') - ord('A') encryption_key = (('a','m'), ('b','h'), ('c','t'), ('d','f'), ('e','g'), ('f','k'), ('g','b'), ('h','p'), ('i','j'), ('j','w'), ('k','e'),('l','r'), ('m','q'), ('n','s'), ('o','l'), ('p','n'), ('q','i'), ('r','u'), ('s','o'), ('t','x'), ('u','z'), ('v','y'), ('w','v'), ('x','d'), ('y','c'), ('z','a')) digits = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') special_chars = ('!', '@', '#', '$', '%', '^', '&', '*', '?') # program greeting print('This program will encrypt and decrypt user passwords\n') # get selection (encrypt/decrypt) which = input('Enter (e) to encrypt a password, and (d) to decrypt: ') while which != 'e' and which != 'd': which = input("\nINVALID - Enter 'e' to encrypt, 'd' to decrypt: ") encrypting = (which == 'e') # assigns True or False # get password long_enough = False has_digits = False has_special_chars = False while not long_enough or not has_digits or not has_special_chars: password_in = input('Enter password: ') long_enough = False has_digits = False has_special_chars = False if len(password_in) >= 8: long_enough = True if (not has_digits or not has_special_chars): k = 0 while k < len(password_in): if password_in[k] in digits: has_digits = True elif password_in[k] in special_chars: has_special_chars = True k = k + 1 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 25 if not long_enough: print('Password must contain at least 8 characters') if not has_digits: print('Password must contain at least one digit') if not has_special_chars: print('Password must contain at least one special character') print() # perform encryption / decryption if encrypting: from_index = 0 to_index = 1 else: from_index = 1 to_index = 0 case_changer = ord('a') - ord('A') for ch in password_in: letter_found = False for t in encryption_key: if ('a' <= ch and ch <= 'z') and ch == t[from_index]: password_out = password_out + t[to_index] letter_found = True elif ('A' <= ch and ch <= 'Z') and chr(ord(ch) + 32) == t[from_index]: password_out = password_out + chr(ord(t[to_index]) - case_changer) letter_found = True if not letter_found: password_out = password_out + ch # output if encrypting: print('Your encrypted password is:', password_out) else: print('Your decrypted password is:', password_out) This program will encrypt and decrypt user passwords Enter (e) to encrypt a password, and (d) to decrypt: e Enter password: Pizza Password must contain at least 8 characters Password must contain at least one digit Password must contain at least one special character Enter password: Pizza2 Password must contain at least 8 characters Password must contain at least one special character Enter password: Pizza2Day Password must contain at least one special character Enter password: Pizza2Day! Your encrypted password is: Njaam2Fmc! >>> Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 26 M5. Password Encryption/Decryption Program: Random Key Generation Modify the Encryption/Decryption program in the chapter so that a new encryption key is randomly generated each time the program is executed. (See the Python 3 Programmers’ Reference for information on the Random module.) # Password Encryption/Decryption Program (Figure 4-13) # MODIFICATION: Random Key Generation import random # init password_out = '' case_changer = ord('a') - ord('A') alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] # general random key encryption_key = [] for k in range(0, 26): select = random.randint(0, 26 - k - 1) encryption_key.append((chr(ord('a') + k), alphabet[select])) del alphabet[select] # program greeting print('This program will encrypt and decrypt user passwords\n') # get selection (encrypt/decrypt) which = input('Enter (e) to encrypt a password, and (d) to decrypt: ') while which != 'e' and which != 'd': which = input("\nINVALID - Enter 'e' to encrypt, 'd' to decrypt: ") encrypting = (which == 'e') # assigns True or False # get password password_in = input('Enter password: ') # perform encryption / decryption if encrypting: from_index = 0 to_index = 1 else: from_index = 1 to_index = 0 case_changer = ord('a') - ord('A') for ch in password_in: letter_found = False for t in encryption_key: if ('a' <= ch and ch <= 'z') and ch == t[from_index]: password_out = password_out + t[to_index] letter_found = True elif ('A' <= ch and ch <= 'Z') and chr(ord(ch) + 32) == t[from_index]: Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 27 password_out = password_out + chr(ord(t[to_index]) - case_changer) letter_found = True if not letter_found: password_out = password_out + ch # output if encrypting: print('Your encrypted password is:', password_out) else: print('Your decrypted password is:', password_out) This program will encrypt and decrypt user passwords Enter (e) to encrypt a password, and (d) to decrypt: e Enter password: Pizza2Day! Your encrypted password is: Ejppo2Kor! >>> ================================ RESTART ================================ >>> This program will encrypt and decrypt user passwords Enter (e) to encrypt a password, and (d) to decrypt: e Enter password: Pizza2Day! Your encrypted password is: Zpggl2Tla! M6. Calendar Year Program: Multilingual Version Modify the Calendar Year program so that the user can select the language with which the calendar months are labeled. Give the user the choice of at least three different languages from which to select. Find the months names for the other languages online. PROGRAM ERATTA The calendar year program shown in Figure 4-23 in the text has an error. Variable calendar_year is not reset (to an empty list) before each next calendar year is generated. Thus, each next calendar year is appended to the pervious in the calendar_year structure. The same dates are displayed for each subsequent calendar year. The correction is to move the initialization of calendar_year from the start of the program to inside the program’s main loop. This error has been corrected in the provided source code file. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 28 # Calendar Year Program (Figure 4-23) # MODIFICATION: Multilingual Version # initialization terminate = False days_in_month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) month_names_english = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') month_names_dutch = ('janurai', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'october', 'november', 'december') month_names_italian = ('gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'otoobre', 'novembre', 'dicembre') calendar_year = [] month_separator = format(' ', '8') textbook correction blank_week = format(' ', '21') blank_col = format(' ', '3') # prompt for years until quit while not terminate: # program greeting print('This program will display a calendar year in either ', end='') print('English, Dutch or Italian') # get year year = int(input('Enter year (yyyy) (-1 to quit): ')) while (year < 1800 or year > 2099) and year != -1: year = int(input('INVALID - Enter year(1800-2099): ')) if year == -1: terminate = True else: # get language lang = input('Select language - (E)nglish, (D)utch, (I)talian: ') while lang not in ('E', 'D', 'I', 'e', 'd', 'i'): lang = input('Select language - (E)nglish, (D)utch, (I)talian: ') if lang in ('E', 'e'): month_names = month_names_english elif lang in ('D', 'd'): month_names = month_names_dutch elif lang in ('I', 'i'): month_names = month_names_italian # determine if leap year if (year % 4 == 0) and (not (year % 100 == 0) or (year % 400 == 0)): leap_year = True else: leap_year = False # determine day of the week century_digits = year // 100 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 29 year_digits = year % 100 value = year_digits + (year_digits // 4) if century_digits == 18: value = value + 2 elif century_digits == 20: value = value + 6 # leap year check if not leap_year: value = value + 1 # determine first day of month for Jan 1 first_day_of_current_month = (value + 1) % 7 # construct calendar for all 12 months calendar_year = [] for month_num in range(12): month_name = month_names[month_num] textbook correction # init for new month current_day = 1 if first_day_of_current_month == 0: starting_col = 7 else: starting_col = first_day_of_current_month current_col = 1 calendar_week = '' calendar_month = [] # add any needed leading space for first week of month while current_col < starting_col: calendar_week = calendar_week + blank_col current_col = current_col + 1 # store month as separate weeks if (month_name == month_names[1]) and leap_year: num_days_this_month = 29 else: num_days_this_month = days_in_month[month_num] while current_day <= num_days_this_month: # store day of month in field of length 3 calendar_week = calendar_week + \ format(str(current_day),'>3') # check if at last column of displayed week if current_col == 7: calendar_month = calendar_month + [calendar_week] calendar_week = '' current_col = 1 else: current_col = current_col + 1 # increment current day current_day = current_day + 1 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 30 # fill out final row of month with needed blanks calendar_week = calendar_week + \ blank_week[0:(7-current_col+1) * 3] calendar_month = calendar_month + [calendar_week] # reset values for next month first_day_of_current_month = current_col calendar_year = calendar_year + [calendar_month] calendar_month = [] # print calendar year print('\n', year,'\n') # each row starts with January, April, July, or October for month_num in [0,3,6,9]: # displays three months in each row for i in range(month_num, month_num + 3): print(' ' + format(month_names[i],'19'), month_separator, end='') # display each week of months on separate lines week = 0 lines_to_print = True while lines_to_print: # init lines_to_print = False # another week to display for first month in row? for k in range(month_num, month_num + 3): if week < len(calendar_year[k]): print(calendar_year[k][week], end='') lines_to_print = True else: print(blank_week, end='') print(month_separator, end='') # move to next screen line print() # increment week week = week + 1 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 31 This program will display a calendar year in either English, Dutch or Italian Enter year (yyyy) (-1 to quit): 2018 Select language - (E)nglish, (D)utch, (I)talian: D 2018 janurai 1 2 7 8 9 14 15 16 21 22 23 28 29 30 februari 3 4 5 6 10 11 12 13 17 18 19 20 24 25 26 27 31 4 5 6 11 12 13 18 19 20 25 26 27 april 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 29 30 mei juli 1 2 8 9 15 16 22 23 29 30 augustus 3 4 5 6 7 10 11 12 13 14 17 18 19 20 21 24 25 26 27 28 31 6 7 13 14 20 21 27 28 mart 1 2 3 7 8 9 10 14 15 16 17 21 22 23 24 28 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 29 30 31 juni 1 2 3 4 5 8 9 10 11 12 15 16 17 18 19 22 23 24 25 26 29 30 31 5 6 7 12 13 14 19 20 21 26 27 28 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 29 30 september 1 2 3 4 8 9 10 11 15 16 17 18 22 23 24 25 29 30 31 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 29 30 october 1 2 7 8 9 14 15 16 21 22 23 28 29 30 november 3 4 5 6 10 11 12 13 17 18 19 20 24 25 26 27 31 4 5 6 7 11 12 13 14 18 19 20 21 25 26 27 28 december 1 2 3 8 9 10 15 16 17 22 23 24 29 30 2 9 16 23 30 1 3 4 5 6 7 8 10 11 12 13 14 15 17 18 19 20 21 22 24 25 26 27 28 29 31 This program will display a calendar year in either English, Dutch or Italian Enter year (yyyy) (-1 to quit): -1 NOTE: The width of the Python shell window most likely will need to be adjusted to allow all the weeks of each month to line up properly. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 32 M7. Calendar Year Program: Flexible Calendar Format The program as is displays three months per row. Modify .the Calendar Year program so that the user can select how many months are displayed per row. Allow the user to select either two, three or four months per row. # Calendar Year Program (Figure 4-23) # MODIFICATION: Flexible Calendar Format # initialization terminate = False days_in_month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) month_names = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') month_separator = format(' ', '8') blank_week = format(' ', '21') blank_col = format(' ', '3') # prompt for years until quit while not terminate: # program greeting print ('This program will display a calendar year for a given year') # get year year = int(input('Enter year (yyyy) (-1 to quit): ')) while (year < 1800 or year > 2099) and year != -1: year = int(input('INVALID - Enter year(1800-2099): ')) if year == -1: terminate = True else: # get num of months per row months_per_row = int(input('Number of months per row (2,3,4)? ')) while months_per_row not in (2,3,4): months_per_row = input('Number of months per row (2,3,4)? ') if months_per_row == 2: first_month_rows = (0,2,4,6,8,10) elif months_per_row == 3: first_month_rows = (0,3,6,9) elif months_per_row == 4: first_month_rows = (0,4,8) # determine if leap year if (year % 4 == 0) and (not (year % 100 == 0) or (year % 400 == 0)): leap_year = True else: leap_year = False # determine day of the week century_digits = year // 100 year_digits = year % 100 value = year_digits + (year_digits // 4) Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 33 if century_digits == 18: value = value + 2 elif century_digits == 20: value = value + 6 # leap year check if not leap_year: value = value + 1 # determine first day of month for Jan 1 first_day_of_current_month = (value + 1) % 7 # construct calendar for all 12 months calendar_year = [] for month_num in range(12): month_name = month_names[month_num] # init for new month current_day = 1 if first_day_of_current_month == 0: starting_col = 7 else: starting_col = first_day_of_current_month current_col = 1 calendar_week = '' calendar_month = [] # add any needed leading space for first week of month while current_col < starting_col: calendar_week = calendar_week + blank_col current_col = current_col + 1 # store month as separate weeks if (month_name == 'February') and leap_year: num_days_this_month = 29 else: num_days_this_month = days_in_month[month_num] while current_day <= num_days_this_month: # store day of month in field of length 3 calendar_week = calendar_week + \ format(str(current_day),'>3') # check if at last column of displayed week if current_col == 7: calendar_month = calendar_month + [calendar_week] calendar_week = '' current_col = 1 else: current_col = current_col + 1 # increment current day current_day = current_day + 1 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 34 # fill out final row of month with needed blanks calendar_week = calendar_week + \ blank_week[0:(7-current_col+1) * 3] calendar_month = calendar_month + [calendar_week] # reset values for next month first_day_of_current_month = current_col calendar_year = calendar_year + [calendar_month] calendar_month = [] # print calendar year print('\n', year,'\n') # number of months per row determined by months_per_row for month_num in first_month_rows: # displays months_per_row months in each row for i in range(month_num, month_num + months_per_row): print(' ' + format(month_names[i],'19'), month_separator, end='') # display each week of months on separate lines week = 0 lines_to_print = True while lines_to_print: # init lines_to_print = False # another week to display for first month in row? for k in range(month_num, month_num + months_per_row): if week < len(calendar_year[k]): print(calendar_year[k][week], end='') lines_to_print = True else: print(blank_week, end='') print(month_separator, end='') # move to next screen line print() # increment week week = week + 1 NOTE: The width of the Python shell window will need to be readjusted for each new selection of calendar format (months per row) in order for the weeks of each month to line up properly. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 35 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 36 SOLUTIONS TO PROGRAM DEVELOPMENT PROBLEMS D1. Morse Code Encryption/Decryption Program Develop and test a Python program that allows a user to type in a message and have it converted into Morse code, and also enter Morse code and have it converted back to the original message. The encoding of Morse code is given below. Format the original message (containing English words) so that there is one sentence per line. Format the Morse code file (containing dots and dashes) so that there is one letter per line, with a blank line following the last letter of each word, and two blank lines following the end of each sentence (except the last). Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 37 # Morse Code Encryption/Decryption Program # Problem D1 (Chapter 4) # # # # This program will convert between Morse code and English. English messages may only contain (upper/lower case) letters and a period, which must end each sentence. Morse code messages contain one morse-coded letter per line, with one blank line between words, and two blank lines between sentences. # init blank_char = ' ' empty_str = '' message = [] letters = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z') morse_code = ('.-', '-...', '-.-.', '-..', '.', '.._.', '--.', '....', '..', '.---', '-.-', '.-..', '--', '-.', '---', '.--.', '--.-', '.-.', '...', '-', '..-', '...-', '.--', '-..-', '-.--', '--..') # display program welcome print('This program will convert between English and Morse code.') # get which conversion which = input('(E)nglish to Morse code, or (M)orse code to English? ') while which not in ('E', 'M', 'e', 'm'): which = input('(E)nglish to Morse code, or (M)orse code to English? ') # conversion of English to Morse code if which in ('E', 'e'): # display instructions to user print('\nEnter English message, one sentence per line.') print('End each sentence with a period (hit return when done)\n') # get English message line = input('> ') while line != empty_str: message.append(line) line = input('> ') # display Morse-coded results num_lines = len(message) for line in message: for char in line: index = 0 found = False # find Morse code for current char while index < 26 and not found: if char.upper() == letters[index]: print(morse_code[index]) found = True elif char == blank_char or char == '.': print() found = True else: index = index + 1 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 38 # two blank lines after each sentence except the last num_lines = num_lines - 1 if num_lines != 0: print() # conversion of Morse code to English else: # display instruction to user print('\nEnter morse-coded letters one per line.') print('Include one blank line between words,', end='') print('and two blank lines between sentences ') print("(enter 'q' when done)\n") # init sentence = empty_str previous_blankline = False # get first Morse-coded char line = input('> ') # convert chars until 'q' entered while line not in ('Q', 'q'): # end of sentence (two consecutive blank lines)? if line == empty_str and previous_blankline: sentence = sentence + '.' message.append(sentence) sentence = empty_str previous_blankline = False # first blank line elif line == empty_str: previous_blankline = True else: # end of word? if previous_blankline: sentence = sentence + blank_char previous_blankline = False # convert Morse-coded char to letter index = 0 found = False while index < 26 and not found: if line == morse_code[index]: sentence = sentence + letters[index] found = True else: index = index + 1 # get next sentence of English message line = input('> ') # add period for last sentence found message.append(sentence + '.') # display converted message print() for line in message: print(line) Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 39 This program will convert between English and Morse code. (E)nglish to Morse code, or (M)orse code to English? E Enter English message, one sentence per line. End each sentence with a period (hit return when done) > Dawn in breaking. > Sun should rise. > -.. ..--. .. -. -... .-. . .-... -. --. ... ..-. ... .... --...-.. -.. .-. .. ... . Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 40 This program will convert between English and Morse code. (E)nglish to Morse code, or (M)orse code to English? M Enter morse-coded letters one per line. Include one blank line between words,and two blank lines between sentences (enter 'q' when done) > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -.. ..--. .. -. -... .-. . .-... -. --. ... ..-. ... .... --...-.. -.. .-. .. ... . q DAWN IN BREAKING. SUN SHOULD RISE. >>> Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 41 NOTE: The program is not designed to include punctuation in the messages. This might feel limiting to the students. The Morse code for these characters can be given to students to include. The method of conversion relies on the use of “parallel lists” letters and morse_code. Students can be shown a means of conversion in which the corresponding letter for each item in list morse_code is implied by its position in the list, this not requiring the explicit represention of letters of the alphabet. For example, if the letter in variable char is to be converted, the corresponding index in list morse_code can be determined by ord(char) – ord(‘A’). When converting from Morse code to the corresponding letter, the letter can be constructed from the index location in list morse_code by chr(ord(‘A’) + index). Finally, students are likely to have errors that are not due to errors in their program, but from not remembering to add a period at the end of sentences when converting from English to Morse code, or not entering the correcting number of blank lines when converting from Morse code to English. Therefore, students should be reminded of this. D2. Develop and test a Python program that displays the day of the week that the following holidays fall on for a year entered by the user, New Year’s Eve Valentine’s Day St. Patrick’s Day April Fool’s Day Fourth of July Labor Day Halloween User’s Birthday Note that Labor Day, as opposed to the other holidays above, does not fall on the same date each year. It occurs each year on the first Monday of September. # Holidays Calendar Program # Problem D2 (Chapter 4) # This program will display the day of the week that the following holidays fall # on for a specified year: New Year's Eve, Valentine's Day, St. Patrick's Day, # April Fool's Day, Fourth of July, Halloween, User's Birthday, and Labor Day. # initialization terminate = False holiday_dates = [["New Year's Eve", 12, 31], ["Valentine's Day", 2, 14], ["St. Patrick's Day", 3, 17], ["April Fool's Day", 4, 1], ["Fourth of July", 7, 4],["Halloween", 10, 31], ["Your Birthday", None, None]] days_in_month = [31, None, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] month_values = (1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6) day_names = ('Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday') Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 42 # program greeting print('This program will display the day of the week that various holidays') print('fall on for a given year, including a provided birth date.\n') # prompt for years until quit while not terminate: # get year year = int(input('Enter year (yyyy) (-1 to quit): ')) while (year < 1800 or year > 2099) and year != -1: year = int(input('INVALID - Enter year(1800-2099): ')) if year == -1: terminate = True else: # determine if leap year if (year % 4 == 0) and (not (year % 100 == 0) or (year % 400 == 0)): leap_year = True # assign num days for February (leap year) days_in_month[1] = 29 else: leap_year = False # assign num days for February (non-leap year) days_in_month[1] = 28 # get user's birthday birth_month = int(input('\nWhat month were you born? (1,...,12): ')) while birth_month < 1 or birth_month > 12: birth_month = int(input('What month were you born? (1,...,12): ')) birth_day = int(input('What day were you born? (1,...,12): ')) while birth_day < 1 or birth_day > days_in_month[birth_month - 1]: birth_day = int(input('What day were you born? (1,...,12): ')) # update holiday_dates with user's birthday holiday_dates[6][1] = birth_month holiday_dates[6][2] = birth_day # determine century and year digits century_digits = year // 100 year_digits = year % 100 # set initial value value = year_digits + (year_digits // 4) # adjust for centuries if century_digits == 18: value = value + 2 elif century_digits == 20: value = value + 6 # save initial value initial_value = value # display day of the week for each holiday print() Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 43 for holiday in holiday_dates: holiday_name = holiday[0] month = holiday[1] day = holiday[2] # determine day of the week for current holiday if month == 1 and not leap_year: value = value + month_values[month - 1] elif month == 2: if not leap_year: value = value + month_values[month - 1] else: value = value + 3 else: value = value + month_values[month - 1] value = (value + day) % 7 # display result print(holiday_name, 'falls on a', day_names[value]) # reset value value = initial_value # display day of the week for Labor Day (always a Monday) print('Labor Day falls on a Monday\n') This program will display the day of the week that various holidays fall on for a given year, including a provided birth date. Enter year (yyyy) (-1 to quit): 1984 What month were you born? (1,...,12): 2 What day were you born? (1,...,12): 4 New Year's Eve falls on a Monday Valentine's Day falls on a Wednesday St. Patrick's Day falls on a Saturday April Fool's Day falls on a Sunday Fourth of July falls on a Wednesday Halloween falls on a Wednesday Your Birthday falls on a Sunday Labor Day falls on a Monday Enter year (yyyy) (-1 to quit): -1 >>> NOTE: The fact that Labor Day always falls on a Monday means that for that holiday, the day of the week does not need to be computed. Therefore, the inclusion of this holiday in the problem may seem pointless. However, it provides students with the issue of how to handle a special case like this in the most appropriate manner. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 44 D3. The Game of Battleship Battleship is a game involving ships at sea for each of two players. The ships are located in a grid in which each column of the grid is identified by a letter, and each row by a number, as shown below. A B C D E F G H I J 1 2 3 4 5 6 7 8 9 10 The top half of the board contains the ships of player 1, and the bottom half the ships of player 2. The darkened areas indicate the size and location of ships. Each player starts with the same number and types of ships. The location of each player’s ships is determined by the player. Players take turns taking a shot at the opponent’s ships by “calling out” a particular grid location. For example, if player 1 calls out C10,” no ship would be hit in this example. If, however, they were to call out “G10,” then player 2’s ship (on the bottom half of the board) would be hit. Each player calls out “hit” or “miss” when they are shot at by the other player. When all grid locations of a given ship have been hit, the ship is sunk, and the opponent gets the number of points based on the ship’s size (given below). The number of grid locations that a given ship takes up indicates its type and point value. A typical set of ships is given below. Type of Ship aircraft carrier battleship cruiser submarine destroyer Size of Ships 5 4 3 3 2 Develop and test a Python program that can play the game of battleship. The user should be able to select the skill level. The higher the skill level, the larger the grid that is created for play. All games start with exactly one of each type of ship for each player. The locations of the computer’s ships will be randomly placed. The user, however, must be able to enter the location of each of their ships. The computer’s shots into the opponent’s grid area should be randomly generated. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 45 # Battleship Program # Problem D3 (Chapter 4) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This program will allow a person to play a game of Battleship against the computer. The board consists of consecutively numbered rows ('1', '2', ...), and consecutively lettered columns ('A', 'B', ...). The user has the choice of board size from 10 x 10 up to 26 by 26 for nine levels of play. Naming of ships on game board within program: 'a' - aircraft carrier 'b' - battleship 'c' - cruiser 's' 'd' - submarine destroyer ---------------------------------------------------------------------------RULES OF THE GAME (1) Each player starts with five ships, one of each of the following types: aircraft carrier battleship cruiser submarine destroyer 5 4 3 3 2 The number next to each ship corresponds to its size (number of grids) and hence its value. (2) Each player indicates the position their ships by specifing a coordinate range for each, e.g., the position of an aircraft carrier might be specified as (B2, B6). (The computer places its ships randomly.) (3) Each player "calls out" a specific coordinate location (e.g., B7). If the coordinate is occupied by one of the opponent;s ships, then the opponent calls out "Hit". Once all coordinates of an opponent's ship has been hit, the ship is sunk and the other players received points equal to the value of the ship sunk. (4) The game may be played until both players decide to end the game, in which the player with the most number of points wins, or until all of the ships of one of the players have been sunk (in which case the player with ships left unsunk is the winner). ---------------------------------------------------------------------------- import random # --- initialization game_board = [] empty_str = '' ship_names = ('aircraft carrier', 'battleship', 'cruiser', 'submarine', 'destroyer') ship_codings = ('a', 'b', 'c', 's', 'd') ship_hit_codings = ('A', 'B', 'C', 'S', 'D') ship_lengths = (5, 4, 3, 3, 2) # --- program greeting print('This program will play the game of Battleship against an opponent.') print('Nine levels of play are provided.\n') Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 46 # --- prompt for level of play level = input('Enter level of play (1-9): ') while level < '1' or level > '9': level = input('Enter level of play (1-9): ') level = int(level) # --- construct empty board board_size = 10 + (level - 1) * 2 for n in range (1, board_size + 1): row = [] for k in range (1, board_size + 1): row.append(empty_str) game_board.append(row) # ---- display empty board print('\nGame Board ...\n') print(format(' ', '<3'), end='') for k in range(0, board_size): print(format(chr(ord('A') + k), '^3'), end='') print('\n') for row in range(0, board_size): print(format(row + 1, '<3'), end='') for col in range(0, board_size): if row < board_size // 2: print(format('.', '^3'), end='') else: print(format('*', '^3'), end='') # label each side of game board if row == 2: print(format(' ', '<6'), "PLAYER'S SHIPS", end='') elif row == board_size // 2 + 2: print(format(' ', '<6'), "COMPUTER'S SHIPS", end='') # display blank line between player's and computer's sides of board if row == board_size // 2 - 1: print('\n') else: print() print() # --- get player's ship locations print('\nEnter location of each ship of specified size (e.g., A1:A5)') ship_num = 0 for ship in ship_names: ship_placed = False while not ship_placed: # prompt for ship coordinates valid_input = False s = input(ship + '(' + str(ship_lengths[ship_num]) + '): ') Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 47 while not valid_input: # invalid length, missing colon, improper format? if len(s) < 5 or len(s) > 7: print('... invalid number of character entered') s = input(ship + '(' + str(ship_lengths[ship_num]) + '): ') elif ':' not in s or \ s[0] < 'A' or s[0] > 'Z' or \ s[s.index(':') + 1] < 'A' or s[s.index(':') + 1] > 'Z' or \ s[1] < '0' or s[1] > '9' or \ s[s.index(':') - 1] < '0' or s[s.index(':') - 1] > '9' or \ s[s.index(':') + 2] < '0' or s[s.index(':') + 2] > '9' or \ s[len(s) - 1] < '0' or s[len(s) - 1] > '9': print('... must have form <letter><number:><letter><number>') s = input(ship + '(' + str(ship_lengths[ship_num]) + '): ') # valid input found else: valid_input = True # parse rows and column values and convert to row/col of game_board first_row_num = int(s[1:s.index(':')]) - 1 last_row_num = int(s[s.index(':')+2:]) - 1 first_col_num = ord(s[0:s.index(':')][0]) - ord('A') last_col_num = ord(s[s.index(':') + 1:][0]) - ord('A') # check if rows and/or cols are the same rows_same = False cols_same = False if first_row_num == last_row_num: rows_same = True if first_col_num == last_col_num: cols_same = True # init error flag error_found = False # check that valid coordinate range entered if (first_row_num > last_row_num) or (first_col_num > last_col_num) or \ (rows_same and cols_same) or (not rows_same and not cols_same): print('... invalid range specified - please reenter') error_found = True elif last_row_num >= board_size or last_col_num >= board_size: print('... outside limits of board') error_found = True elif rows_same: # horizontially positioned # check for invalid length if (last_col_num - first_col_num) + 1 != ship_lengths[ship_num]: print('... ' + ship + 's are', ship_lengths[ship_num], 'grids long') error_found = True # check if ship positioned within player's area of the board if first_row_num >= len(game_board) // 2: print("... cannot position ship in opponent's area of board") error_found = True Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 48 if not error_found: # generate coordinates of horizontally-placed ship row_num = first_row_num coords = [(row_num, col_num) \ for col_num in range(first_col_num, last_col_num + 1)] # check for collisions collision_found = False k = 0 while k < len(coords) and not collision_found: if game_board[coords[k][0]][coords[k][1]] != empty_str: collision_found = True print('... collision found with existing ship') else: k = k + 1 # position ship if no errors found if not collision_found: for grid_loc in coords: game_board[grid_loc[0]][grid_loc[1]] = \ ship_codings[ship_num] print('* ship positioned *\n') ship_placed = True else: # vertically position # check for invalid length if (last_row_num - first_row_num) + 1 != ship_lengths[ship_num]: print('... ' + ship + 's are', ship_lengths[ship_num], 'grids long') error_found = True # check if ship positioned within player's area of the board if last_row_num >= len(game_board) // 2: print("... cannot position ship in opponent's area of board") error_found = True if not error_found: # generate coordinates of vertically-placed ship col_num = first_col_num coords = [(row_num, col_num) for row_num in \ range(first_row_num, last_row_num + 1)] # check for collisions collision_found = False k = 0 while k < len(coords) and not collision_found: if game_board[coords[k][0]][coords[k][1]] != empty_str: collision_found = True print('... collision found with existing ship') else: k = k + 1 # position ship if no errors found if not collision_found: for grid_loc in coords: game_board[grid_loc[0]][grid_loc[1]] = \ ship_codings[ship_num] print('* ship positioned *\n') ship_placed = True # increment to positioned next ship ship_num = ship_num + 1 Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 49 # --- randomly position computer's ships for current_ship in range(len(ship_names)): # get length of current ship length = ship_lengths[current_ship] # place horizontially or vertically based on even/odd random number if random.randint(1,10) % 2 == 0: # position horizontally placed_without_collision = False while not placed_without_collision: # generate random ship location,(row, col),within bottom half # of board for horizontal placement, accounting for its length loc = (random.randint(len(game_board) // 2, len(game_board) - 1), random.randint(0, len(game_board) - length)) # check for collisions collision_found = False col_incr = 0 while col_incr < ship_lengths[current_ship] and \ not collision_found: if game_board[loc[0]][loc[1] + col_incr] != empty_str: collision_found = True else: col_incr = col_incr + 1 if not collision_found: placed_without_collision = True # place ship on board for col_incr in range(ship_lengths[current_ship]): game_board[loc[0]][loc[1] + col_incr] = ship_codings[current_ship] else: # position vertically placed_without_collision = False while not placed_without_collision: # generate random location, (row, col), within bottom half # of board for vertical placement, accounting for its length loc = (random.randint(len(game_board) // 2, len(game_board) - length), random.randint(0, len(game_board) - 1)) # check for collisions collision_found = False for row_incr in range(ship_lengths[current_ship]): if game_board[loc[0] + row_incr][loc[1]] != empty_str: collision_found = True if not collision_found: placed_without_collision = True # place ship on board for row_incr in range(ship_lengths[current_ship]): game_board[loc[0] + row_incr][loc[1]] = ship_codings[current_ship] Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 50 # --- start game print('\nGAME STARTED . . .\n') game_over = False while not game_over: # -- display current board print(format(' ', '<3'), end='') for k in range(0, board_size): print(format(chr(ord('A') + k), '^3'), end='') print('\n') for row in range(0, board_size): print(format(row + 1, '<3'), end='') for col in range(0, board_size): if game_board[row][col] == empty_str: if row < board_size // 2: print(format('.', '^3'), end='') else: print(format('*', '^3'), end='') # display standing ships (except for computer's) elif game_board[row][col] in ship_codings: if row >= board_size // 2: print(format('*', '^3'), end='') else: print(format(game_board[row][col], '^3'), end='') # display player's ships and computer's hits else: print(format(game_board[row][col], '^3'), end='') # label each side of game board if row == 2: print(format(' ', '<6'), "PLAYER'S SHIPS", end='') elif row == board_size // 2 + 2: print(format(' ', '<6'), "COMPUTER'S SHIPS", end='') # display blank line between player's and computer's sides of board if row == board_size // 2 - 1: print('\n') else: print() print() # -- get player's move valid_input = False while not valid_input: s = input('Enter grid location to bomb (e.g., A4): ') # valid length? if len(s) != 2 and len(s) != 3: print('... invalid input') else: # determine row and col values Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 51 if len(s) == 2: row_value = col_value = else: row_value = col_value = s[1] s[0] s[1:3] s[0] # valid form: <letter><number>? if (ord(col_value) < ord('A') or ord(col_value) > ord('Z')) or \ len(row_value) == 1 and \ (ord(row_value) < ord('0') or ord(row_value) > ord('9')) or \ len(row_value) == 2 and \ (ord(row_value[0]) < ord('0') or ord(row_value[0]) > ord('9') or \ ord(row_value[1]) < ord('0') or ord(row_value[1]) > ord('9')): print('... must be of form <letter><number') # within board size? elif col_value < 'A' or \ col_value > chr(ord('A') + (board_size - 1)) or \ int(row_value) < 1 or int(row_value) > board_size: print('... invalid row/col value (outside limits of board)') # within player's own area of board? elif int(row_value) <= board_size // 2: print("... must be within opponent's area of board") # check if a hit or not else: # flag entered grid location as valid valid_input = True # determine column and row index values col_num = ord(col_value) - ord('A') row_num = int(row_value) - 1 # determine what is in bombed location symbol = game_board[row_num][col_num] if symbol == empty_str: print('-- NO HIT --') elif symbol in ship_codings: game_board[row_num][col_num] = \ '-' + game_board[row_num][col_num] + '-' print('*** DIRECT HIT ***') else: print('-- LOCATION ALREADY SUCESSFULLY STRUCK --') # -- generate computer's move col_num = random.randint(0, board_size - 1) row_num = random.randint(0, board_size // 2 - 1) # display computer's bombing location print('\nIncoming bomb to grid location', chr(ord('A') + col_num) + str(row_num + 1)) # determine what is in bombed location symbol = game_board[row_num][col_num] Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 52 if symbol == empty_str: print('-- NO HIT --') elif symbol in ship_codings: # change board symbol to indicate a hit game_board[row_num][col_num] = \ '-' + game_board[row_num][col_num] + '-' ## game_board[row_num][col_num] = ship_codings.index(symbol) print('*** DIRECT HIT TO YOUR ' + \ ship_names[ship_codings.index(symbol)] + ' ***') elif symbol in ship_hit_codings: print('-- LOCATION ALREADY SUCESSFULLY STRUCK --') print() # -- check if winner standing_ship_player = False standing_ship_computer = False # determine if either or both players have standing ships row_num = 0 while row_num < board_size: col_num = 0 while col_num < board_size: if row_num < board_size // 2 and \ game_board[row_num][col_num] in ship_codings: standing_ship_player = True if row_num >= board_size // 2 and \ game_board[row_num][col_num] in ship_codings: standing_ship_computer = True col_num = col_num + 1 row_num = row_num + 1 if standing_ship_player and not standing_ship_computer: print('\n**** You Won!! ***') game_over = True elif not standing_ship_player and standing_ship_computer: print('\n**** The Computer Won! ****') game_over = True elif not standing_ship_player and not standing_ship_computer: print('\n**** Tie Game ! ****') game_over = True Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 53 NOTE: This is a challenging program for students. One reason is because of all the input error checking that needs to be performed Thus, one way to simplify the assignment is to not require complete error checking. (Because of this, it serves as a good example of how a large part of a program can be concerned with error checking vs. the program logic neede for the problem itself.) The required input error checking is also slightly more involved for students at this point because the string methods that can be useful here are not coverd until Chapter 8 (on Text Files). Thus, for example, the following conditional expression, s[0] < 'A' or s[0] > 'Z', could be instead written as, s.[0].isupper(). Another way to simplify is to required a fixed board size. There are places in the program where a for loop is used (creating a definite loop), and logoically an indefinite loop is called for, e.g., # check for collisions collision_found = False for col_incr in range(ship_lengths[current_ship]): if game_board[loc[0]][loc[1] + col_incr] != empty_str: collision_found = True In this case, the loop could terminate as soon as a collision is found (e.g., collision_found is True). The use of the for loop here, however, can be justified because the list iterating over is very small. Finally, there are expressions in the program solution given that rely on short-circuit (short circuit) evaluation, # invalid length, missing colon, improper format? if len(s) < 5 or len(s) > 7: print('... invalid number of character entered\n') s = input(ship + '(' + str(ship_lengths[ship_num]) + '): ') elif ':' not in s or \ s[0] < 'A' or s[0] > 'Z' or \ s[s.index(':') + 1] < 'A' or s[s.index(':') + 1] > 'Z' or \ s[1] < '0' or s[1] > '9' or \ s[s.index(':') - 1] < '0' or s[s.index(':') - 1] > '9' or \ s[s.index(':') + 2] < '0' or s[s.index(':') + 2] > '9' or \ s[len(s) - 1] < '0' or s[len(s) - 1] > '9': print('... must have form <letter><number:><letter><number>\n') s = input(ship + '(' + str(ship_lengths[ship_num]) + '): ') In this case, if colon were not first looked for in the elif clause, the following calls to the index method, s.index(‘:’) would result in a runtime error. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 54 This program will play the game of Battleship against an opponent. Nine levels of play are provided. Enter level of play (1-9): 4 Game Board ... A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter location of each ship of specified size (e.g., A1:A5) aircraft carrier(5): C4C8 ... invalid number of character entered aircraft carrier(5): C4:C8 * ship positioned * battleship(4): G3:T6 ... invalid range specified - please reenter battleship(4): G3:G7 ... battleships are 4 grids long battleship(4): G3:G6 * ship positioned * cruiser(3): M7:M9 ... cannot position ship in opponent's area of board cruiser(3): M6:M8 * ship positioned * submarine(3): B4:D4 ... collision found with existing ship submarine(3): C4:E4 ... collision found with existing ship submarine(3): K6:M6 ... collision found with existing ship submarine(3): L3:N3 * ship positioned * Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 55 destroyer(2): L12N12 ... must have form <letter><number:><letter><number> destroyer(2): L12:N12 ... destroyers are 2 grids long ... cannot position ship in opponent's area of board destroyer(2): D8:E8 * ship positioned * A . . . . . . . . * * * * * * * * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 B . . . . . . . . * * * * * * * * C . . . a a a a a * * * * s * * * D . . . . . . . d * * * * s * * * E . . . . . . . d * * * * s * * * F . . . . . . . . * * * * * * * * G . . b b b b . . * c c c * * * * H . . . . . . . . * * * * * * * * I . . . . . . . . * * * * * * * * J . . . . . . . . * * * * * * * * K . . . . . . . . d * * * * * * * L . . s . . . . . d * * a * * * * M . . s . . c c c * * * a * * * b N . . s . . . . . * * * a * * * b O . . . . . . . . * * * a * * * b P . . . . . . . . * * * a * * * b GAME STARTED . . . A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s . . . . . . . s . . c c c . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): E10 -- NO HIT -Incoming bomb to grid location I8 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 56 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s . . . . . . . s . . c c c . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): N12 *** DIRECT HIT *** Incoming bomb to grid location L1 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s . . . . . . . s . . c c c . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): D8 ... must be within opponent's area of board Enter grid location to bomb (e.g., A4): D9 -- NO HIT -Incoming bomb to grid location D1 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 57 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s . . . . . . . s . . c c c . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): C13 *** DIRECT HIT *** Incoming bomb to grid location J7 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s . . . . . . . s . . c c c . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * -s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): C14 -- NO HIT -Incoming bomb to grid location D3 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 58 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s . . . . . . . s . . c c c . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * -s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): D13 *** DIRECT HIT *** Incoming bomb to grid location I2 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s . . . . . . . s . . c c c . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * -s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): E13 *** DIRECT HIT *** Incoming bomb to grid location M8 *** DIRECT HIT TO YOUR cruiser *** Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 59 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): N12 -- LOCATION ALREADY SUCESSFULLY STRUCK -Incoming bomb to grid location B5 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): G10 *** DIRECT HIT *** Incoming bomb to grid location K3 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 60 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * * * * * * * * * * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): G11 *** DIRECT HIT *** Incoming bomb to grid location J7 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * * * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): G12 *** DIRECT HIT *** Incoming bomb to grid location O8 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 61 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): L12 *** DIRECT HIT *** Incoming bomb to grid location G7 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a- * -a- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): M12 *** DIRECT HIT *** Incoming bomb to grid location K6 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 62 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a--a--a- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): O12 *** DIRECT HIT *** Incoming bomb to grid location B4 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a--a--a--a- * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): P12 *** DIRECT HIT *** Incoming bomb to grid location J8 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 63 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -a--a--a--a--a* * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): K9 *** DIRECT HIT *** Incoming bomb to grid location K3 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -d- * * * * * * * * * * * * * * * * * * * * * -a--a--a--a--a* * * * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): L9 *** DIRECT HIT *** Incoming bomb to grid location K8 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 64 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -d--d- * * * * * * * * * * * * * * * * * * * * -a--a--a--a--a* * * * * * * * * * * * * * * * * * * * * * * * * * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): M16 *** DIRECT HIT *** Incoming bomb to grid location D1 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -d--d- * * * * * * * * * * * * * * * * * * * * -a--a--a--a--a* * * * * * * * * * * * * * * * * * * * * * * * -b- * * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): N16 *** DIRECT HIT *** Incoming bomb to grid location L1 -- NO HIT -- Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 65 A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -d--d- * * * * * * * * * * * * * * * * * * * * -a--a--a--a--a* * * * * * * * * * * * * * * * * * * * * * * * -b--b- * * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): O16 *** DIRECT HIT *** Incoming bomb to grid location N4 -- NO HIT -A B C D E F G H I J K L M N O P 1 2 3 4 5 6 7 8 . . . . . . . . . . . . . . . . . . . a a a a a . . . . . . . d . . . . . . . d . . . . . . . . . . b b b b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s s . . . . . c . c . -c- . . s . . . . . . . . . . . . . . . . . . . . . 9 10 11 12 13 14 15 16 * * * * * * * * * * * * * * * * * * * * -c- * * * * * * -c- * * * * * * -c- * * -s--s--s- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -d--d- * * * * * * * * * * * * * * * * * * * * -a--a--a--a--a* * * * * * * * * * * * * * * * * * * * * * * * -b--b--b- * PLAYER'S SHIPS COMPUTER'S SHIPS Enter grid location to bomb (e.g., A4): P16 *** DIRECT HIT *** Incoming bomb to grid location F3 -- NO HIT -**** You Won!! *** >>> Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 66 D4. Heuristic Play for the Game of Battleship A heuristic is a general “rule of thumb” for solving a problem. Modify the Game of Battleship program from the previous problem so that the locations of the shots that the computer makes into the opponent’s grid area based on heuristics, rather than being randomly generated. Include an explanation of the heuristics you have developed. NOTE: Because the computer’s ships are placed randomly, there is no heuristic to be used that is based on any strategy of the opponent. Thus, any heuristic would be based on the grid locations known to be occupied by the opponent’s ships. Thus, one heuristic would be to explore adjacent grids with the goal of completely sinking a ship. Another heuristic, for determining where to beginning searching for another of the opponent’s ships, might be to start looking a certain distance from the location of a known ship, in which the distance from the ship is based on the ship’s size. The reasoning here is that a larger ship is less likely to have other ships placed near it than smaller one, given that there is more change of two ships occupying the same grid locations with larger ships. Introduction to Computer Science Using Python – Dierbach Copyright 2013 John Wiley and Sons 67