Trường ĐH Công nghệ – Đại học Quốc gia Hà Nội
Tài liệu đọc: Think Python 3rd ed., 5.{8–10}, 6.{6–8}
def blast_off_loop(n):
"""Print a countdown starting at n.
n: a non-negative int"""
for n in range(n, 0, -1):
print(n)
print('BLAST OFF!')
>>> r3 = range(3)
>>> r3.step
1
>>> r10 = range(0, 10, 2)
>>> r10.step
2
>>> list(r10)
[0, 2, 4, 6, 8]
>>> r_down = range(10, 0, -1)
>>> list(r_down)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
step cho biết “bước nhảy” giữa hai giá trị liên tiếp trong range.
def blast_off_no_loop(n):
"""Print a countdown starting at n.
n: a non-negative int"""
if n == 0:
print('BLAST OFF!')
else:
print(n)
blast_off_no_loop(n-1)
def factorial_iter(n):
"""Returns n!.
n: a non-negative integer"""
product = 1
for i in range(1, n+1): # 1..n
product = product * i
return product
Dùng biến tạm product để tích lũy kết quả trong vòng for.
def factorial_rec(n):
"""Returns n!.
n: a non-negative integer"""
if n == 0:
return 1
else:
n_minus_1_fact = factorial_rec(n-1)
return n * n_minus_1_fact
def mystery(n):
if n == 0:
return 0
else:
n_minus_1_result = mystery(n-1)
return n + n_minus_1_result
print(mystery(4))
Câu hỏi: Hàm này in ra gì?
def factorial_rec(n):
"""Returns n!.
n: a non-negative integer"""
if n == 0:
return 1
else:
n_minus_1_fact = factorial_rec(n-1)
return n * n_minus_1_fact
def factorial_rec(n):
"""Returns n!.
n: a non-negative integer"""
if n == 0:
return 1
else:
n_minus_1_fact = factorial_rec(n-1)
return n * n_minus_1_fact
Về toán học:
# recursionerrors.py
def infinite_recursion():
infinite_recursion()
>>> import recursionerrors
>>> recursionerrors.infinite_recursion()
... RecursionError: maximum recursion depth exceeded
Không có base case → hàm tự gọi mãi mãi (cho tới khi Python chặn lại).
# recursionerrors.py
def bad_blast_off_v1(n):
if n == 0:
print('BLAST OFF!')
else:
print(n)
bad_blast_off_v1(n) # BUG: need "n-1"
def bad_blast_off_v2(n):
# BUG: no base case
print(n)
bad_blast_off_v2(n-1)
# A
def recurse(n):
if n == 0:
return
recurse(n-1)
# B
def recurse(n):
if n == 0:
return
recurse(n+1)
Tiền điều kiện chung: n >= 0.
Chuỗi số:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
Có hai base case — rất phổ biến trong đệ quy.
def fibo_rec(n):
"""Returns F(n).
n: a non-negative integer"""
if n == 0 or n == 1:
return n
else:
return fibo_rec(n-1) + fibo_rec(n-2)
fibo_rec(n) tạo ra rất nhiều lời gọi lặp lại.
fibo_rec(n) tạo ra rất nhiều lời gọi lặp lại.
def fibo_iter(n):
if n == 0 or n == 1:
return n
else:
a = 0
b = 1
for i in range(2, n+1):
t = a
a = b
b = a + t
return b
def fibo_iter(n):
if n == 0 or n == 1:
return n
else:
a = 0
b = 1
for i in range(2, n+1): # a = F(???), b = F(???)
t = a
a = b
b = a + t
return b
Book = [
'Preface',
'1 Fundamentals',
['1.1 Basic Programming Model',
'1.2 Data Abstraction',
'1.3 Bags, Queues, and Stacks',
['Bags',
'Queues',
'Stacks'],
'1.4 Analysis of Algorithms',
'1.5 Case Study: Union-Find'],
'2 Sorting',
'3 Searching',
...
]
# outline.py
def print_outline_v1(outline):
for item in outline:
print(item)
Preface
1 Fundamentals
['1.1 Basic Programming Model', '1.2 Data Abstraction',
'1.3 Bags, Queues, and Stacks', ['Bags', 'Queues', 'Stacks'],
'1.4 Analysis of Algorithms', '1.5 Case Study: Union-Find']
2 Sorting
3 Searching
Danh sách lồng bên trong bị in ra nguyên cả list → khó đọc.
def print_outline_v2(outline):
for item in outline:
# handle nested lists
if isinstance(item, list):
for subitem in item:
print(' ' * 4 + str(subitem))
else:
print(item)
Preface
1 Fundamentals
1.1 Basic Programming Model
1.2 Data Abstraction
1.3 Bags, Queues, and Stacks
['Bags', 'Queues', 'Stacks']
1.4 Analysis of Algorithms
1.5 Case Study: Union-Find
2 Sorting
3 Searching
def print_outline_v3(outline):
for item in outline:
# handle nested lists
if isinstance(item, list):
for subitem in item:
# handle nested nested lists
if isinstance(subitem, list):
for subsubitem in subitem:
print(' ' * 8 + str(subsubitem))
else:
print(' ' * 4 + str(subitem))
else:
print(item)
Preface
1 Fundamentals
1.1 Basic Programming Model
1.2 Data Abstraction
1.3 Bags, Queues, and Stacks
Bags
Queues
Stacks
1.4 Analysis of Algorithms
1.5 Case Study: Union-Find
2 Sorting
3 Searching
def indent(level):
return ' ' * level
def print_outline_rec(outline, level):
for item in outline:
if isinstance(item, list):
print_outline_rec(item, level+1)
else:
print(indent(level) + item)
outline = ['Intro',
['Part 1',
['Detail 1.1', 'Detail 1.2'],
'Part 2'],
'Conclusion']
print_outline_rec(outline, 0)
def print_outline_rec(outline, level):
for item in outline:
if isinstance(item, list):
print_outline_rec(item, level+1)
else:
print(indent(level) + item)
Hỏi: tổng cộng bao nhiêu lần hàm print_outline_rec được gọi (kể cả lần đầu)?
Mục tiêu: giải bài toán P trên một dữ liệu đầu vào.
Kỹ thuật này thường được gọi là “chia để trị” (divide and conquer).
Mục tiêu: In mục lục từ list lồng nhau.
Mục tiêu: Tính F(n).
Mục tiêu: Tính n!.
Mỗi bước đều phải đảm bảo: tiến tới base case, không được quay vòng vô hạn.