Download Chapter 4 – Lists - Department of Computer Science

Document related concepts
no text concepts found
Transcript
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