printed
, annual_salary
, abc
, sum_of_data
, and b4
.
print("Hello, world!")
Output of statements:
"Quotes"
Slashes \//
How '"confounding' "\" it is!
Output of statements:
name age height
Archie 17 5'9"
Betty 17 5'6"
Jughead 16 6'
Output of statements:
Shaq is 7'1
The string "" is an empty message.
\'""
Output of statements:
a b c"
\\
"
'''
C:
in he downward spiral
Output of statements:
Dear "DoubleSlash" magazine,
Your publication confuses me. Is it
a \\ slash or a //// slash?
Sincerely,
Susan "Suzy" Smith
print
statements to produce desired output:
print("\"Several slashes are sometimes seen,\"")
print("said Sally. \"I've said so.\" See?")
print("\\ / \\\\ // \\\\\\ ///")
print
statements to produce desired output:
print("This is a test of your")
print('knowledge of "quotes" used')
print("in 'string literals.'")
print()
print("You're bound to \"get it right\"")
print("if you read the section on")
print("''quotes.''")
print
statement to produce desired output:
print("/ \\ // \\\\ /// \\\\\\")
Mistakes in the program:
def
is missing.)
is missing.Mistakes in the program:
"
mark is missing.def example():
Output of the program:
This is message1. This is message2. This is message1. Done with message2. Done with main.
Output of the program:
Inside first function Inside third function Inside first function Inside second function Inside first function Inside second function Inside first function Inside third function Inside first function Inside second function Inside first function
Output of the program:
Inside first function Inside first function Inside second function Inside first function Inside third function Inside second function Inside first function Inside first function Inside second function Inside first function Inside third function
Output of the program:
Inside second function Inside first function Inside first function Inside second function Inside first function Inside third function Inside first function Inside second function Inside first function
Mistakes in the program:
:
is missing after the function name and parentheses.)
is missing."
s inside the string need to be escaped.;
.Results of expressions:
8
11
6
4
33
-16
6.4
6
30
1
-1
5.0
2
18
3
4
4
15
8
1
Results of expressions:
9.0
9.6
2.0
6.0
6.0
8.0
1.25
3.0
3.0
3.0
5.0
6.4
37.0
8.5
9.6
4.0
4.8
25.5
grade = 4.0
number % 10
Mistakes in the program:
,
between is"
and x
., x
should be outside the quotes.int
should be omitted.and
should be surrounded by quotes.(number % 100) // 10
or (number // 10) % 10
(number % 1000) // 100
or (number // 100) % 10
Values of a
, b
, and c
after the code:
a: 6 b: 9 c: 16
Values of first
and second
after the code:
first: 19 second: 8The code swaps the values of the variables
first
and second
.
Rewritten shortened version of the code:
first = 8, second = 19 first += second second = first - second first -= second
Values of i
, j
, and k
after the code:
i: 4 j: 2 k: 1
Output of code:
46 36 23 13
Version of the program that uses variables to avoid redundant expressions:
def main(): # Calculate my pay at work, based on how many hours I worked each day total_hours = 4 + 5 + 8 + 4 salary = 8.75 pay = total_hours * salary tax_rate = 0.20 taxes_owed = pay * tax_rate print("My total hours worked:") print(total_hours) print("My hourly salary:") print("$" + str(salary)) print("My total pay:") print(pay) print("My taxes owed:") print(taxes_owed) main()
def main(): for i in range(1, 5): print("2 times", i, "=", (2 * i)) main()
2 * count
15 * count - 11
-10 * count + 40
4 * count - 11
-3 * count + 100
for i in range(1, 7): print(18 * i - 22)
Output of odd_stuff
function:
4 2 1 0
Output of loop:
9 1 7 2 4 3 0 4
Output of loop:
+---+ \ / / \ \ / / \ \ / / \ +---+
Output of loop:
T-minus 5, 4, 3, 2, 1, Blastoff!
Output of loops:
1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50
Output of loops:
****!****!****! ****!****!****!
2 * line + 2 * SIZE
4 * line + (3 * SIZE)
-line + (2 * SIZE + 3)
Table for output:
line | \ | ! | / |
---|---|---|---|
1 | 0 | 22 | 0 |
2 | 2 | 18 | 2 |
3 | 4 | 14 | 4 |
4 | 6 | 10 | 6 |
5 | 8 | 6 | 8 |
6 | 10 | 2 | 10 |
\
and /
: 2 * line - 2
!
: -4 * line + 26
Table for output:
line | \ | ! | / |
---|---|---|---|
1 | 0 | 14 | 0 |
2 | 2 | 10 | 2 |
3 | 4 | 6 | 4 |
4 | 6 | 2 | 6 |
\
and /
: 2 * line - 2
!
: -4 * line + 18
-4 * line + (4 * SIZE + 2)
15 42 10 25
1 3 5 1 3 5 7 9 11 13 15 1 3 5 7 9 11 13 15 17 19 21 23 25
1 2 3 4 5 1 2 3 4 5 6 7 1 2 3 4 number = 8
whom and who like it it and him like whom whom and him like him stu and boo like who her and him like who
touch your eye to your head touch your head to your eye touch your shoulders to your elbow touch your eyes and ears to your eyes and ears touch your toes to your Toes touch your shoulders to your knees toes
say coke not pepsi or pop say soda not soda or pepsi say pepsi not koolaid or pop say say not pepsi or pepsi
def print_strings(s, n): for i in range(1, n + 1): print(s, end=" ") print()
Temperature
program changes the value of its tempc
parameter on line 9, but this doesn't affect the variable tempc
in main
. The (incorrect) output is:
Body temp in C is: 0.0
results of math
expressions:
1.6
2
36.0
64.0
10.0
116.0
7
5
-5
8.0
11.0
102.0
17.0
20.0
13.0
14.0
Output of the program:
3 0 1 2 4 4 3 5 2 4 8 1 5 9 4
grade = 2.7 math.round(grade) # grade = 2.7 grade = math.round(grade) # grade = 3.0 min = math.min(grade, math.floor(2.9)) # min = 2.0 x = math.pow(2, 4) # x = 16.0 x = math.sqrt(64) # x = 8.0 count = 25 math.sqrt(count) # count = 25 count = math.sqrt(count) # count = 5 a = math.abs(math.min(-1, -3)) # a = 3
def count_quarters(cents): return cents % 100 // 25
def main(): age = int(input("How old are you?")) print("You have", (65 - age), "years until retirement.") main()
number = int(input("Type an integer: ")) print(number, "times 2 =", (number * 2))
phrase = input("What is your phrase? ") times = int(input("How many times should I repeat it? ")) for i in range(1, times + 1): print(phrase)
Correct syntax to draw a rectangle:
e.p.draw_rect(10, 20, 50, 30)
Mistakes in the code:
draw_line
should be made on the DrawingPanel
p
, not on nothing.The following is the corrected code:
p = DrawingPanel(200, 200) p.draw_line(50, 86, 20, 35)
The black rectangle is being drawn second, so it's covering up the white inner circle. The following code fixes the problem:
panel = DrawingPanel(200, 100) p.set_color("black") p.fill_rect(10, 10, 50, 50) p.set_color("white") p.fill_oval(10, 10, 50, 50)
The program draws a series of progressively smaller black circles, each with its right and bottom edges touching the right and bottom corners of the window. Its output looks like this:
English statements translated into logical tests:
z % 2 == 1
z <= math.sqrt(y)
y > 0
x % 2 != y % 2
y % z == 0
z != 0
abs(y) > abs(z)
(x >= 0) == (z < 0)
y % 10 == y
z >= 0
x % 2 == 0
abs(x - y) < abs(z - y)
Results of relational expressions:
True
False
True
False
True
False
False
True
True
Mistakes in the program:
=
should be ==
, and line should end with a colonsmaller
is out of scope here (line 4 should be smaller = minimum(a, b)
=>
should be >=
(or better yet, no if
test is needed)
Output of if_else_mystery_1
calls:
Call | Output |
---|---|
a. if_else_mystery_1(3, 20) |
13 21 |
b. if_else_mystery_1(4, 5) |
5 6 |
c. if_else_mystery_1(5, 5) |
6 5 |
d. if_else_mystery_1(6, 10) |
7 11 |
Output of if_else_mystery_2
calls:
Call | Output |
---|---|
a. if_else_mystery_2(10, 2) |
10 6 |
b. if_else_mystery_2(3, 8) |
9 9 |
c. if_else_mystery_1(4, 4)2 |
3 4 |
d. if_else_mystery_2(10, 30) |
29 30 |
Code to read an integer from the user, then print even
if that number is an even number or odd
otherwise:
number = int(input("Type a number: ")) if number % 2 == 0: print("even") else: print("odd")
The code incorrectly prints that even numbers not divisible by 3 are odd.
This is because the else
statement matches the most closely nested if
statement (number % 3 == 0
), not the outer if
statement.
The following change corrects the problem.
if number % 2 == 0: if number % 3 == 0: print("Divisible by 6.") else: print("Odd.")
Refactored code to reduce redundancy:
a = 2 if x < 30: x += 1 print("Python is awesome!", x)
Refactored code to reduce redundancy:
times = int(input("Is your money multiplied 1 or 2 times? ")) donation = int(input("And how much are you contributing? ")) sums += times * donation total += donation if times == 1: count1 += 1 elif times == 2: count2 += 1
If the user could type any number, the code might need additional if
statements to increment the proper count variable.
Code to read red/green/blue color:
choice = input("What color do you want? ") if choice.lower() == "r": print("You have chosen Red.") elif choice.lower() == "g": print("You have chosen Green.") elif choice.lower() == "b": print("You have chosen Blue.") else: print("Unknown color:", choice)
The problem with the given sum_to
function is that the sum
variable needs to be declared outside the for
loop.
The following code fixes the problem:
def sum_to(n): sums = 0 for i in range(1, n + 1): sums += i return sums
The count_factors
function shown will not return the right answer.
It should count the factors using a a cumulative sum; it should not return inside the loop when it finds each factor.
Instead, it should declare a counter outside the loop that is incremented as each factor is seen.
The following code fixes the problem:
def count_factors(n): count = 0 for i in range(1, n + 1): if n % i == 0: count += 1 return count
The expression equals 6.800000000000001
rather than the expected 6.8
because of a roundoff error.
The expression gpa * 3
equals 9.600000000000001
rather than the expected 9.6
because of a roundoff error.
A fix would be to test that the value is close to 9.6
rather than exactly equal to it, as shown in the following code:
gpa = 3.2 diff = abs(gpa * 3 - 9.6) if diff < 0.1: print("You earned enough credits.")
The preconditions of print_triangle_type
function are that the three side lengths constitute a valid triangle. Namely:
The preconditions of the get_grade
function are that the grade parameter's value is between 0 and 100.
The median_of_3
code fails when n3
is the smallest of the three numbers; for example, when the parameters' values are (4, 7, 2), the code should return 4 but instead returns 2.
The method could be correctly written as:
def median_of_3(n1, n2, n3): if n1 < n2 and n1 < n3: if n2 < n3: return n2 else: return n3 elif n2 < n1 and n2 < n3: if n1 < n3: return n1 else: return n3 else: # n3 < n1 and n3 < n2 if n1 < n2: return n1 else: return n2
or the following shorter version:
def median_of_3(n1, n2, n3): return max(max(min(n1, n2), min(n2, n3)), min(n1, n3))
The code fails when more than one number is odd, because it uses elif
rather than if
.
The tests should not be nested because they are not mutually exclusive; more than one number could be odd.
The following code fixes the problem:
def print_num_odd(n1, n2, n3): count = 0 if n1 % 2 != 0: count += 1 if n2 % 2 != 0: count += 1 if n3 % 2 != 0: count += 1 print(count, "of the 3 numbers are odd.")
The following version without if
statements also works:
def print_num_odd(n1, n2, n3): count = n1 % 2 + n2 % 2 + n3 % 2 print(count, "of the 3 numbers are odd.")
Output of the program:
efg nopqrs qr
Statement that tests to see whether a string begins with a capital letter:
if "A" <= the_string[0] <= "Z": ...
The following expression would produce the desired result:
name = "Marla Singer" space = name.find(" ") last_name = name[(space + 1) :] first_initial = name[0] last_name_first_initial = last_name + ", " + first_initial + "." print(last_name_first_initial)
Alternatively, you could use this shorter version:
name = "Marla Singer" print(name[(name.find(" ") + 1):] + ", " + name[0] + ".")
Code to examine a string and determine how many of its letters come from the second half of the alphabet ('n'
or later):
# assuming that the string is stored in the variable s count = 0 for ch in s.lower(): if ch >= 'n': count += 1 print(count, "letters come after n.")
1 11 21 31 41 51 61 71 81 91
250 250 250 ...
2 4 16
bbbbbabbbbb
10 5 2 1 0 0 0
n = 1 while n <= maxs: print(n) n += 1
total = 25 number = 1 while number <= (total // 2): total = total - number print(total, number) number += 1
i = 1 while i <= 2: j = 1 while j <= 3: k = 1 while k <= 4: print("*", end="") k += 1 print("!", end="") j += 1 print() i += 1
mystery
calls:
Call | Output |
---|---|
a. mystery(1) |
1 0 |
b. mystery(6) |
4 2 |
c. mystery(19) |
16 4 |
d. mystery(39) |
32 5 |
e. mystery(74) |
64 6 |
Output of mystery
calls:
Call | Output |
---|---|
a. mystery(19) |
19 0 |
b. mystery(42) |
21 1 |
c. mystery(48) |
3 4 |
d. mystery(40) |
5 3 |
e. mystery(64) |
1 6 |
import random num = random.randint(0, 10)
import random num = random.randint(0, 24) * 2 + 51
print_letters
code has a fencepost problem; it will print a dash after the last letter.
The following code corrects the problem:
def print_letters(text): if len(text) > 0: print(text[0], end="") for i in range(1, len(text)): print("-" + text[i], end="") print() # to end the line of output
-1
is typed, displays the maximum and minimum numbers that the user entered:
SENTINEL = -1 num = int(input("Type a number (or " + str(SENTINEL) + " to stop): ")) mins = num maxs = num while num != SENTINEL: if num < mins: mins = num elif num > maxs: maxs = num num = int(input("Type a number (or " + str(SENTINEL) + " to stop): ")) if mins != SENTINEL: print("Maximum was", maxs) print("Minimum was", mins)
Results of boolean
expressions:
True
True
False
True
True
False
False
True
True
True
True
False
def is_vowel(c): c = c.lower() # case-insensitive return c == "a" or c == "e" or c == "i" or c == "o" or c == "u"or:
def is_vowel(c): return "aeiouAEIOU".find(c) >= 0
is_prime
code the boolean flag isn't being used properly, because if the code finds a factor of the number, prime
will be set to False
, but on the next pass through the loop, if the next number isn't a factor, prime
will be reset to Tue
again.
The following code fixes the problem:
def is_prime(n): prime = True for i in range(2, n): if n % i == 0: prime = False return prime
start_end_same
code using boolean zen:
def start_end_same(string): return string[0] == string[-1]
has_pennies
code using Boolean zen:
def has_pennies(cents): return cents % 5 != 0
Output of mystery
calls:
Call | Value Returned |
---|---|
a. mystery(3, 3) |
3 |
b. mystery(5, 3) |
1 |
c. mystery(2, 6) |
2 |
d. mystery(12, 18) |
6 |
e. mystery(30, 75) |
15 |
days
value will be 366, so code enters the if is_leap_year
statement but does not enter the if days > 366
statement.
So the loop does not subtract any days and never terminates.
It can be fixed by adding a boolean flag to the loop:
days = get_total_days_since_1980() year = 1980 stop = False while days > 365 and not stop: # subtract out years if is_leap_year(year): if days > 366: days -= 366 year += 1 else: # new code here stop = True # new code here else: days -= 365 year += 1
not b
(x <= y) or (y <= z)
(x != y) and (x > z)
(x % 2 == 0) or not b
(x // 2 != 13) and not b and (z * 3 != 96)
(z >= x) or (z <= y and x < y)
success = False while not success: age = input("Type your age: ") try: age = int(age) success = True except ValueError: print("Not an integer; try again.") success = False while not success: gpa = input("Type your GPA: ") try: gpa = float(gpa) success = True except ValueError: print("Not a float; try again.") print("age =", age, " GPA = ", gpa)
prompt = "Please enter a number: " num1 = get_int(prompt) num2 = get_int(prompt) num3 = get_int(prompt) average = (num1 + num2 + num3) / 3.0 print("Average:", average)
Point | y < x |
y == 0 |
count > 0 |
---|---|---|---|
Point A | SOMETIMES | SOMETIMES | NEVER |
ALWAYS | SOMETIMES | SOMETIMES | |
Point C | ALWAYS | ALWAYS | ALWAYS |
Point D | SOMETIMES | SOMETIMES | SOMETIMES |
Point E | NEVER | SOMETIMES | SOMETIMES |
Point | n > b |
a > 1 |
b > a |
---|---|---|---|
Point A | SOMETIMES | SOMETIMES | SOMETIMES |
ALWAYS | SOMETIMES | SOMETIMES | |
Point C | SOMETIMES | ALWAYS | ALWAYS |
Point D | SOMETIMES | ALWAYS | NEVER |
Point E | NEVER | SOMETIMES | SOMETIMES |
Point | next == 0 |
prev == 0 |
next == prev |
---|---|---|---|
Point A | SOMETIMES | ALWAYS | SOMETIMES |
Point B | NEVER | SOMETIMES | SOMETIMES |
Point C | NEVER | NEVER | ALWAYS |
Point D | SOMETIMES | NEVER | SOMETIMES |
Point E | ALWAYS | SOMETIMES | SOMETIMES |
A file is a named collection of information stored on a computer.
We can read a file by opening it and then using the read
or readlines
method:
with open("input.txt") as file: lines = name.readlines()
with open("input.txt") as file: lines = name.readlines()
The call to split
returns:
["welcome...to", "the", "matrix."]
The call to split
returns:
["in", "fourteen-hundred", "92", "columbus", "sailed", "the", "ocean", "blue", ":)"]
"numbers.dat"
or "C:/Users/yana/Documents/programs/numbers.dat"
"data/homework6/input.dat"
or "C:/Users/yana/Documents/programs/data/homework6/input.dat"
"C:/Users/yana/Documents/homework/data.txt"
"names.txt"
or "/home/yana/Documents/hw6/names.txt"
"data/numbers.txt"
or "/home/yana/Documents/hw6/data/numbers.txt"
"/home/yana/download/saved.html"
The following output would be produced:
input: 6.7 This file has input: several input lines. input: input: 10 20 30 40 input: input: test 6 total
Output produced if readlines
and split
are used:
input: 6.7 input: This input: file input: has input: several input: input input: lines. input: input: 10 input: 20 input: 30 input: 40 input: input: test 14 total
Program that prints itself as output:
def main(): with open("input.txt") as file: lines = file.readlines() for line in lines: print(line.strip()) main()
Code that prompts the user for a file name and prints the contents of that file to the console as output:
def print_entire_file(): file_name = input("Type a file name: ") with open(file_name) as file: lines = file.readlines() for line in lines: print(line.strip())
Program that takes as input lines of text and produces as output the same text inside a box:
# precondition: no line in input is longer than width def print_box(lines, width): print_top_bottom(width) for line in lines: spaces = width - len(line.strip()) print("| " + line.strip() + (" " * spaces) + " |") print_top_bottom(width) def print_top_bottom(width): print("+", end="") for i in range(0, width + 2): print("-", end="") print("+")
Code to print the following four lines of text into a file named message.txt
:
with open("message.txt", "w") as my_file: print("Testing,", file=my_file) print("1, 2, 3.", file=my_file) print("", file=my_file) print("This is my output file.", file=my_file)
Code that repeatedly prompts the user for a file name until the user types the name of a file that exists on the system.
import os.path def get_file_name(): file_name = "" while not os.path.isfile(file_name): file_name = input("Type a file name: ") return file_name
Code that uses get_file_name
before calling print_entire_file
:
# reprompts until file name is valid def print_entire_file_2(): file_name = get_file_name() with open(file_name) as file: lines = file.readlines() for line in lines: print(line.strip())
numbers[0]
numbers[9]
or numbers[len(numbers) - 1]
or numbers[-1]
data = [27, 51, 33, -1, 101]
Code that stores all odd numbers between -6 and 38 into an array using a loop:
odds = [0] * 22 for i in range(len(odds)): odds[i] = i * 2 - 5
After the code is executed, the numbers
list contains the following element values:
[0, 4, 11, 0, 44, 0, 0, 2]
After the code is executed, the data
list contains the following element values:
[3, 3, 0, 0, 6, 9, 0, -18]
data = [7, -1, 13, 24, 6]
letters[:2]
letters[3:4]
letters[3:]
letters[:3:-1]
letters[1::2]
def maximum(data): maxs = data[0] for i in range(1, len(data)): if data[i] > maxs: maxs = data[i] return maxs
def average(a): mean = 0.0 for i in range(0, len(a)): mean += a[i] return mean / len(a)
data[3:3] = ["dark", "and"]
data[1] = "IS"
i = 0 while i < len(data): if "a" in data[i]: data.pop(i) else: i += 1
A list traversal is a sequential processing of each of an list's elements. Problems that can be solved in this manner include printing a list, comparing two lists for equality, and searching a list for a given value.
Code that uses a for
loop to print each element of a list named data
:
for i in range(len(data)): print("element [", i, "] is", data[i])
After the code is executed, the list
array contains the following element values:
[3, 24, 8, -6, 6, 1]
[1, 2, 6, 8]
[10, 30, 40, 20, 60, 50]
[-4, 1, 25, 4, 16, 9, 64, 36, 49]
[20, 10, 20, 30, 30, 20]
[8, 7, 8, 2, 9, 7, 4, 4, 2, 8]
[33, 28, 33, -1, 3, 28, 17, 9, 33, 17, -1, 33]
def all_less(list1, list2): if len(list1) != len(list2): return False for i in range(len(list1)): if list1[i] >= list2[i]: return False return True
After the code is executed, the numbers
list contains the following element values:
[20, 30, 40, 50, 60, 70, 80, 90, 100, 100]
After the code is executed, the numbers
list contains the following element values:
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
After the mystery
function is executed, the list a1
contains the following element values:
[26, 19, 14, 11, 10]
After the mystery2
function is executed, the list numbers
contains the following element values:
[7, 3, 1, 0, 25, 4, 18, -1, 5]
Results of calls to mystery3
function:
0
9
6
8
2
def average_length(strings): sums = 0 for i in range(len(strings)): sums += len(strings[i]) return sums / len(strings)
def is_palindrome(lis): for i in range(len(lis) // 2): if lis[i] != lis[len(lis) - 1 - i]: return False return True
[s[0].upper() for s in letters]
[s + s for s in letters]
[(s, s[0]) for s in letters]
Output of the program:
2 [0, 0, 1, 0] 1 [0, 0, 1, 0] 3 [0, 0, 1, 1] 2 [0, 0, 1, 1]
Output of the program:
2 [0, 1] 1 [0, 1] 1 [1, 2] 0 [1, 2]
def swap_pairs(lis): for i in range(0, len(lis) - 1, 2): swap(lis, i, i + 1)
append
on a tuple.
reverse
on a tuple.
clear
on a tuple.
def distance(p1, p2): dx = p2[0] - p1[0] dy = p2[1] - p1[1] return math.sqrt(dx * dx + dy * dy) def nearest_points(points): min_dist = 0 min_p1 = (0, 0) min_p2 = (0, 0) for i in range(len(points)): for j in range(i + 1, len(points)): dist = distance(points[i], points[j]) if min_dist == 0 or dist < min_dist: min_dist = dist min_p1 = points[i] min_p2 = points[j] print(min_p1, "and", min_p2)
After the code is executed, the numbers
list contains the following element values:
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
Loop to initialize the third row of data
to store the numbers 1 through 7:
for i in range(7): data[2][i] = i + 1
Code that constructs a two-dimensional list of integers with 5 rows and 10 columns, filled with a multiplication table:
table = [] for i in range(5): table.append([0] * 10) for i in range(5): for j in range(10): table[i][j] = i * j
Loop to copy the contents of second column into fifth column:
for i in range(6): matrix[i][4] = matrix[i][1]
After the mystery2d
function is executed, the numbers
list contains the following element values:
[[4, 5, 6, 6], [5, 6, 7, 7], [6, 7, 8, 8]]
jagged = [] value = 1 for i in range(5): jagged.append([0] * (i + 1)) for j in range(i + 1): jagged[i][j] = value value += 1
len(pixels)
and its width is stored as len(pixels[0])
.
You can examine every element of a dictionary using a for-each loop.
You can check whether a key is in the dictionary with the in
keyword.
If you try to add a key/value pair to a dictionary and it already has a pair with that same key, the old pair is replaced by the new pair. If it already has a pair with the same value, but not with the same key, the new pair is added without removing the old pair.
You can loop over the keys of a dictionary in sorted order by passing the keys to the sorted
function.
Code to declare a dictionary that associates people's names with their ages:
ages = {} ages["Stuart"] = 85 ages["Marty"] = 12 ages["Allison"] = 25
or:
ages = {"Stuart": 85, "Marty": 12, "Allison": 25}
Keys and values contained in the dictionary after the code executes:
{17: 'Steve', 34: 'Louann', 5: 'Moshe', 27: 'Donald', 2350: 'Orlando', 15: 'Moshe'}
Keys and values contained in the dictionary after the code executes:
{132: 'OneThreeTwo', 8: 'Ocho', 9828: 'Ninety-eight18', 8650: 'Eighty-sixForty-one', 50: 'Fifty', 79: 'Seventy-nine'}
Output produced when the mystery
method is passed each dictionary:
{'one': 'un', 'four': 'quatre', 'deux': 'two', 'cinq': 'five', 'three': 'trois'}
{'computer': 'program', 'car': 'drive', 'board': 'skate'}
{'begin': 'ready', 'boy': 'girl', 'first': 'last', 'ebert': 'siskel', 'H': 'T'}
{'cotton': 'rain', 'light': 'tree', 'tree': 'violin', 'seed': 'tree'}
Result returned when the mystery
function is passed each pair of dictionaries:
{'mumble': 'fire', 'baz': 'wind', 'bar': 'earth', 'foo': 'air'}
{'one': 'dos', 'five': 'quatro', 'three': 'tres'}
{'c': 'seven', 'g': 'seven', 'b': 'years', 'e': 'ago'}
Result returned when the mystery
function is passed each list:
{1: [1], 2: [1, 1], 3: [], 4: [1], 34: [], 14: []}
{1: [1, 1, 1], 2: [1, 1], 4: [1, 1]}
{43: [1], 44: [], 45: [1, 1], 54: [1]}
Result returned when the mystery
function is passed each dictionary:
{3: {'and'}, 4: {'hello', 'world'}}
{1: {'banana', 'kiwi'}, 2: {'peach'}, 3: {'apple', 'nectarine'}}
{'the': {'is', 'has'}, 'and': {'the', 'and'}}
You should use a set rather than a list if you wanted to avoid duplicates or wanted to be able to search the collection quickly.
You can examine every element of a set using a for-each loop.
You can check whether a value is contained in a set with the in
keyword.
After the code executes, the set contains the following elements (in some order):
{32, 18274, 18212, 9, 12, 29999, 9074}
After the code executes, the set contains the following elements (in some order):
{4, 42, 11, 12, 84, 247, 94}
To do a union, use set1 | set2
to create a new set with all items in both sets.
To do an intersection, use set1 & set2
to create a new set with only items in both of the sets.
To find all of the men who are not hungry and are old or poor or both:
(male - hungry) & (old | poor)
mystery
function is passed each list:
{'jessica', 'amanda', 'helene'}
{'riley'}
{'charlie', 'phil', 'alex', 'roy', 'tyler'}
Recursion is a technique where an algorithm is expressed in terms of itself. A recursive function differs from a regular function in that it contains one or more calls to itself within its body.
A base case is a situation where a recursive function does not need to make a recursive call to solve the problem. A recursive case is a situation where the recursive function does call itself. Recursive functions need both cases because the recursive case is called repeatedly until the base case is reached, stopping the chain of recursive calls.
Output produced by the mystery1
function by each call:
1
1, 2
1, 3
1, 2, 4
1, 2, 4, 8, 16
1, 3, 7, 15, 30
1, 3, 6, 12, 25, 50, 100
Output produced by the mystery2
function by each call:
113
140, 70
168, 84, 42
120, 60, 30
160, 80, 40, 20, 10
Output produced by the mystery_x_y
function by each call:
4
8, 4, 8
16, 8, 16
12, 8, 4, 8, 12
12, 9, 6, 3, 6, 9, 12
Recursive version of double_reverse
function:
def double_reverse(s): if len(s) > 0: last = s[-1] print(last, end="") print(last, end="") double_reverse(s[0:-1])
The version of the pow
function shown does not have any base case, so the recursive calls will never stop. It can be fixed by adding a check for y == 0
that does not make a recursive call.
The second version of the pow
function is more efficient than the first because it requires fewer recursive calls.
Both versions are recursive.
Value returned by the mystery4
function for each call:
6
4
7
0
1
Value returned by the mystery5
method for each call:
57
1029
-74
2438
132483
Recursive version of factorial
function:
def factorial(n): if n == 0: return 1 else: return n * factorial(n - 1)
The base case if
statement has a bug: It should test for numbers less than 10, not greater.
The following is the correct line:
if n < 10:
When the parameters needed for recursion don't match those that make sense for the client to pass, use a function with the signature desired by the client and a helper function with the signature needed for the recursion.
The following version of the fibonacci
code has improved efficiency:
def fibonacci(n): if n <= 2: return 1 else: return fibonacci2(n, 3, 1, 1) def fibonacci2(n, i, prev, curr): if n == i: return prev + curr else: return fibonacci2(n, i + 1, curr, prev + curr)
A fractal is an image that is recursively constructed to contain smaller versions of itself. Recursive functions are useful when drawing fractal images because they can elegantly express the recursive nature of the images.
Code to create and draw a regular hexagon:
def draw_hexagon(panel, x, y, size): p1 = (x, y + size // 2) p2 = (x + size // 3, y) p3 = (x + 2 * size // 3, y) p4 = (x + size, y + size // 2) p5 = (x + 2 * size // 3, y + size) p5 = (x + size // 3, y + size) panel.fill_polygon(p1, p2, p3, p4, p5)
Recursion is an effective way to implement a backtracking algorithm because the memory of decisions and points to go back to are represented by the recursive call stack. The pattern of "choose, explore, un-choose is elegantly represented by recursive calls for each individual choice.
A decision tree is a description of the set of choices that can be made by a recursive backtracking function at any point in the algorithm.
Decision tree that would have resulted for Figure for paths to (1, 2) if the backtracking solution had explored NE first instead of last in the recursive explore
function:
start (0, 0) | +--- NE (1, 1) | | | +--- NE NE (2, 2) | | | +--- NE N (1, 2) - output | | | +--- NE E (2, 1) | +--- N (0, 1) | | | +--- N NE (1, 2) - output | | | +--- N N (0, 2) | | | | | +--- N N NE (1, 3) | | | | | +--- N N N (0, 3) | | | | | +--- N N E (1, 2) - output | | | +--- N E (1, 1) | | | +--- N E NE (2, 2) | | | +--- N E N (1, 2) - output | | | +--- N E E (2, 1) | +--- E (1, 0) | +--- E NE (2, 1) | +--- E N (1, 1) | | | +--- E N NE (2, 2) | | | +--- E N N (1, 2) - output | | | +--- E N E (2, 1) | +--- E E (2, 0)
If the solution had explored NE first instead of last, the solutions would have been printed in this order:
moves: NE N moves: N NE moves: N N E moves: N E N moves: E N N
There are 64 entries at the second level of the full tree. There are 512 entries at the third level of the full tree.
If our 8 Queens algorithm tried every possible square on the board for placing each queen, there would be (64*63*62*61*60*59*58*57) = 178,462,987,637,760 entries are there at the 8th and final level of the full tree. Our algorithm avoids such a huge number of choices by only placing one queen in each column of the board.
The 8 Queens explore
function stops once it finds one solution to the problem.
This is because the code has the following lines around its recursive call:
if explore(b, col + 1): return True
The code could be modified so that it would find and output every solution to the problem by changing that code to the following:
explore(b, col + 1)
And changing the base case to the following:
if col > len(b): print("One solution is as follows:") b.print() return True
You can perform a sequential search over the list using a loop, or you can sort the list using sort
and then perform a binary search over it using bisect.bisect_left
.
Closest value to the number of elements that the binary search algorithm will need to examine on a list of one million integers:
e. less than 1% (10,000 or fewer)You should use binary search if the list is sorted. Otherwise you will have to use sequential search.
O(log N)
O(N)
O(N2)
O(N2)
Complexity classes of the given algorithms in terms of N:
Complexity classes of the given statements:
The runtime complexity of both sequential searches is O(N).
Binary search requires a sorted dataset because it uses the ordering to jump to the next index. If the elements are out of order, the search isn't guaranteed to find the target element.
A binary search of 60 elements examines at most 6 elements, because log2 60 (when rounded up) equals 6.
The algorithm will examine indexes 4, 6, and 5 and will return -1. The algorithm doesn't work properly because the input array isn't sorted.
The binary search algorithm will examine the following indexes and return the following values for each search:
After a single pass of the selection sort algorithm (a single swap), the state of the list is:
d.[-4, 17, 3, 94, 46, 8, 29, 12]
All steps of selection sort algorithm:
[29, 17, 3, 94, 46, 8, -4, 12] [-4, 17, 3, 94, 46, 8, 29, 12] [-4, 3, 17, 94, 46, 8, 29, 12] [-4, 3, 8, 94, 46, 17, 29, 12] [-4, 3, 8, 12, 46, 17, 29, 94] [-4, 3, 8, 12, 17, 46, 29, 94] [-4, 3, 8, 12, 17, 29, 46, 94]
[33, 14, 3, 95, 47, 9, -42, 13] [-42, 14, 3, 95, 47, 9, 33, 13] [-42, 3, 14, 95, 47, 9, 33, 13] [-42, 3, 9, 95, 47, 14, 33, 13] [-42, 3, 9, 13, 47, 14, 33, 95] [-42, 3, 9, 13, 14, 47, 33, 95] [-42, 3, 9, 13, 14, 33, 47, 95]
[7, 1, 6, 12, -3, 8, 4, 21, 2, 30, -1, 9] [-3, 1, 6, 12, 7, 8, 4, 21, 2, 30, -1, 9] [-3, -1, 6, 12, 7, 8, 4, 21, 2, 30, 1, 9] [-3, -1, 1, 12, 7, 8, 4, 21, 2, 30, 6, 9] [-3, -1, 1, 2, 7, 8, 4, 21, 12, 30, 6, 9] [-3, -1, 1, 2, 4, 8, 7, 21, 12, 30, 6, 9] [-3, -1, 1, 2, 4, 6, 7, 21, 12, 30, 8, 9] [-3, -1, 1, 2, 4, 6, 7, 21, 12, 30, 8, 9] [-3, -1, 1, 2, 4, 6, 7, 8, 12, 30, 21, 9] [-3, -1, 1, 2, 4, 6, 7, 8, 9, 30, 21, 12] [-3, -1, 1, 2, 4, 6, 7, 8, 9, 12, 21, 30]
[6, 7, 4, 8, 11, 1, 10, 3, 5, 9] [1, 7, 4, 8, 11, 6, 10, 3, 5, 9] [1, 3, 4, 8, 11, 6, 10, 7, 5, 9] [1, 3, 4, 8, 11, 6, 10, 7, 5, 9] [1, 3, 4, 5, 11, 6, 10, 7, 8, 9] [1, 3, 4, 5, 6, 11, 10, 7, 8, 9] [1, 3, 4, 5, 6, 7, 10, 11, 8, 9] [1, 3, 4, 5, 6, 7, 8, 11, 10, 9] [1, 3, 4, 5, 6, 7, 8, 9, 10, 11]
A merge sort of 32 elements will generate 63 total calls to merge_sort
and will perform the merge
operation 31 times.
State of the elements after five passes of the outermost loop of selection sort have occurred:
[1, 2, 3, 4, 5, 11, 9, 7, 8, 10]
Trace of merge sort algorithm:
[7, 2, 8, 4, 1, 11, 9, 5, 3, 10] [7, 2, 8, 4, 1], [11, 9, 5, 3, 10] [7, 2], [8, 4, 1], [11, 9], [5, 3, 10] [7], [2], [8], [4, 1], [11], [9], [5], [3, 10] [4], [1], [3], [10] [8], [1, 4], [5], [3, 10] [2, 7], [1, 4, 8], [9, 11], [3, 5, 10] [1, 2, 4, 7, 8], [3, 5, 9, 10, 11] [1, 2, 3, 4, 5, 7, 8, 9, 10, 11]
State of the elements after five passes of the outermost loop of selection sort have occurred:
[-3, -1, 1, 2, 4, 8, 7, 21, 12, 30, 6, 9]
Trace of merge sort algorithm:
[7, 1, 6, 12, -3, 8, 4, 21, 2, 30, -1, 9] [7, 1, 6, 12, -3, 8], [4, 21, 2, 30, -1, 9] [7, 1, 6], [12, -3, 8], [4, 21, 2], [30, -1, 9] [7], [1, 6], [12], [-3, 8], [4], [21, 2], [30], [-1, 9] [1], [6], [-3], [8], [21], [2], [-1], [9] [7], [1, 6], [12], [-3, 8], [4], [2, 21], [30], [-1, 9] [1, 6, 7], [-3, 8, 12], [2, 4, 21], [-1, 9, 30] [-3, 1, 6, 7, 8, 12], [-1, 2, 4, 9, 21, 30] [-3, -1, 1, 2, 4, 6, 7, 8, 9, 12, 21, 30]
The following statement about sorting and big-Oh is true:
b. Merge sort achieves an O(N log N) runtime by dividing the list in half at each step and then recursively sorting and merging the halves back together.Traces of merge sort algorithm:
[29, 17, 3, 94, 46, 8, -4, 12] [29, 17, 3, 94], [46, 8, -4, 12] [29, 17], [3, 94], [46, 8], [-4, 12] [29], [17], [3], [94], [46], [8], [-4], [12] [17, 29], [3, 94], [8, 46], [-4, 12] [3, 17, 29, 94], [-4, 8, 12, 46] [-4, 3, 8, 12, 17, 29, 46, 94]
[6, 5, 3, 7, 1, 8, 4, 2] [6, 5, 3, 7], [1, 8, 4, 2] [6, 5], [3, 7], [1, 8], [4, 2] [6], [5], [3], [7], [1], [8], [4], [2] [5, 6], [3, 7], [1, 8], [2, 4] [3, 5, 6, 7], [1, 2, 4, 8] [1, 2, 3, 4, 5, 6, 7, 8]
[33, 14, 3, 95, 47, 9, -42, 13] [33, 14, 3, 95], [47, 9, -42, 13] [33, 14], [3, 95], [47, 9], [-42, 13] [33], [14], [3], [95], [47], [9], [-42], [13] [14, 33], [3, 95], [9, 47], [-42, 13] [14, 33], [3, 95], [9, 47], [-42, 13] [3, 14, 33, 95], [-42, 9, 13, 47] [-42, 3, 9, 13, 14, 33, 47, 95]
Procedural programming treats a program as a sequence of actions or commands to perform. Object-oriented programming looks at a program as a group of interacting entities named objects that each keep track of related data and behavior.
An object is an entity that encapsulates data and behavior that operates on the data. A class is the blueprint for a type of object, specifying what data and behavior the object will have and how to construct it.
Output of the program:
14 14 7 9 14 2 18 18 7 9 14 18
The state of a Calculator
object might include the number that has just been computed, as well as another number that is currently being input.
A more complex Calculator
object might also include a memory feature that stores an additional value.
The behavior of a Calculator
object might include methods to add, subtract, multiply, divide, and perhaps carryout other math operations (such as exponentiation, logarithms, and trigonometric functions like sine and cosine).
An attribute is a variable that exists inside of an object. A parameter is a variable inside a method whose value is passed in from outside. Attributes have different syntax because they are declared at the top of a class and not in a method's header. An attribute's scope is throughout the class, while a parameter's scope is limited to the method.
Name
class that represents a person's name:
# A Name object represents a name such as "John Q. Public". # This version contains only data attributes and a constructor. class Name: def __init__(self, first, middle, last): self.first_name = first self.middle_initial = middle self.last_name = last
An accessor provides the client access to some data in the object, while a mutator lets the client change the object's state in some way. Accessors' names often begin with "get" or "is", while mutators' names often begin with "set".
Correct syntax for calling compute_interest
method on a BankAccount
object:
result = acct.compute_interest(42)
Name
class with two methods:
# A Name object represents a name such as "John Q. Public". # This version adds the methods get_normal_order and get_reverse_order. class Name: def __init__(self, first, middle, last): self.first_name = first self.middle_initial = middle self.last_name = last # The name in normal order such as "John Q. Public". def normal_order(self): return self.first_name + " " + self.middle_initial + ". " + self.last_name # The name in reverse order such as "Public, John Q.". def reverse_order(self): return self.last_name + ", " + self.first_name + " " + self.middle_initial + "."
To make the objects of your class printable, define a __str__
method in it.
The print
statement is equivalent to the following:
print(d1.__str__())
__str__
method for Name
class:
# Returns a string representation of this Name, such as "John Q. Public". def __str__(self): return self.first_name + " " + self.middle_initial + ". " + self.last_nameor:
# Returns a string representation of this Name, such as "John Q. Public". def __str__(self): return self.normal_order()
Abstraction is the ability to focus on a problem at a high level without worrying about the minor details. Objects provide abstraction by giving us more powerful pieces of data that have sophisticated behavior without having to manage and manipulate the data directly.
To access private attributes, create properties that return their values.
For example, add a name
property to access the _name
data attribute of an object.
You can also write accessor methods that return data from the object.
Encapsulated version of Name
class:
# A Name object represents a name such as "John Q. Public". # This version is encapsulated with underscored attributes and properties. class Name: # Initializes a new Name with the given values. def __init__(self, first, middle, last): self._first = first self._middle = middle self._last = last # Returns the person's first name. @property def first_name(self): return self._first # Returns the person's middle initial. @property def middle_initial(self): return self._middle # Returns the person's last name. @property def last_name(self): return self._last # The name in normal order such as "John Q. Public" def normal_order(self): return self._first + " " + self._middle + ". " + self._last # The name in reverse order such as "Public, John Q.". def reverse_order(self): return self._last + ", " + self._first + " " + self._middle + "." # The name in normal order such as "John Q. Public" def __str__(self): return self.normal_order()
Property setters for Name
class:
class Name: ... # Sets the first name to the given value. @first_name.setter def first_name(self, value): self._first = value # Sets the middle initial to the given value. @middle_initial.setter def middle_initial(self, value): self._middle = value # Sets the last name to the given value. @last_name.setter def last_name(self, value): self._last = value
Encapsulation allows you to change a class's internal implementation without changing its external view to clients. When a class is encapsulated clients should not directly access its attributes, so changing those fields will not disturb client behavior as long as the external view (method behavior) is consistent.
Cohesion is the concept of how well a class's contents go together. You can tell that a class is cohesive when each of its attributes stores important state related to the object and each method interacts with that state in some way to produce useful behavior.
We did not place console I/O code into our Stock
class because doing so would force clients to use those exact I/O messages.
By keeping I/O code out of Stock
, we kept it independent from its clients.
Property setters for Stock
class:
@symbol.setter def symbol(self, value): self._symbol = value @total_cost.setter def total_cost(self, value): if value >= 0.0: self._total_cost = value @total_shares.setter def total_shares(self, value): if value >= 0: self._total_shares = value
Because functional programming focuses so much on individual functions, the community of programmers who use functional programming regularly have concluded that side effects should be avoided when possible. Functions without side effects are easy to reason about, reuse, combine, and parallelize.
Calling print
is considered a side effect because it produces a noticeable outcome, namely printing output to the console.
So you can detect whether a given function was called or not by looking for output.
This doesn't mean that printing output is a bad thing, merely that it is a side effect.
The function's side effect is that it modifies the list that was passed in. It could be changed to remove side effects by having it return the new list state rather than changing the existing list.
# Returns a new list whose values are twice as large as # the values of all elements in the given list. def double_all(lis): result = [0] * len(lis) for i in range(len(lis)): result[i] = 2 * lis[i] return result
lambda num: num * num
lambda a, b: max(a, b)
lambda first, last: last + ", " + first
[10, 28, 33, 28, 49, 56, 49]
[num for num in numbers if num >= 0]
[w for w in words if 3 <= len(w) <= 4]
[line for line in open("notes.txt").readlines() if len(line) >= 40]
A bound variable is inside the lambda, typically one of its parameters. A free variable is a variable referred to in the lambda's code that is declared outside the lambda and enclosed into its closure.
The free variable is a
, and the bound variables are b
(the second one) and c
.