SICP Chapter #03 Examples in Python
import math
# Functions defined in previous chapters
def gcd(a, b):
if (b == 0):
return a
else:
return gcd(b, a % b)
def square(x): return x * x
def average(x, y):
return (x + y) / 2.0
def has_no_divisors(n, c):
if c == 1:
return True
elif n % c == 0:
return False
else:
return has_no_divisors(n, c-1)
def isPrime(n):
return has_no_divisors(n, n-1)
def enumerate_interval(low, high):
rt = []
for i in range(low, high+1):
rt.append(i)
return rt
def is_odd(n): return n % 2 == 1
def is_even(n): return not(is_odd(n))
# 3.1.1 - Assignment and State - State Variables
balance = 100
def withdraw(amount):
global balance
if balance >= amount:
balance = balance - amount
return balance
else:
print('InsufficientFunds: ' + str(balance))
return ()
print (withdraw(25))
print (withdraw(25))
print (withdraw(60))
print (withdraw(15))
def new_withdraw():
balance = [100] # use list to overcome scoping intricacies in Python
def withdraw(amount):
if balance[0] >= amount:
balance[0] = balance[0] - amount
return balance[0]
else:
print('InsufficientFunds: ' + str(balance[0]))
return ()
return withdraw
def make_withdraw(init_balance):
balance = [init_balance]
def withdraw(amount):
if balance[0] >= amount:
balance[0] = balance[0] - amount
return balance[0]
else:
print('InsufficientFunds: ' + str(balance[0]))
return ()
return withdraw
w1 = make_withdraw(100)
w2 = make_withdraw(100)
print (w1(50))
print (w2(70))
print (w2(40))
print (w1(40))
class Account:
def __init__(self, init_balance):
self.balance = init_balance
def withdraw(self, amount):
if self.balance >= amount:
self.balance = self.balance - amount
return self.balance
else:
print('InsufficientFunds: ' + str(self.balance))
return ()
def deposit(self, amount):
self.balance = self.balance + amount
return self.balance
def getbalance(self):
return self.balance
acc = Account(100)
acc.withdraw(50)
acc.withdraw(60)
acc.deposit(40)
acc.withdraw(60)
print (acc.getbalance())
Account(100)
# Exercise 3.1
# exercise left to reader to define appropriate functions
# a = make_accumulator(5)
# a.f(10)
# a.f(10)
# Exercise 3.2
# exercise left to reader to define appropriate functions
# s = make_monitored(math.sqrt)
# s.f(100)
# s.how_many_calls()
# Exercise 3.3
# exercise left to reader to define appropriate functions
# acc = Account(100, "secret-password")
# acc.withdraw(40, "secret-password")
# acc.withdraw(50, "some-other-password")
# 3.1.2 - Assignment and State - The Benefits of Introducing Assignment
random_init = 7
def rand_update(x):
a = 27
b = 26
m = 127
return (a*x + b) % m
def rand():
global random_init
x = random_init
random_init = rand_update(random_init)
return x
def cesaro_test():
return gcd(rand(), rand()) == 1
def monte_carlo(trials, experiment):
def iter (trials_remaining, trials_passed):
if trials_remaining == 0:
return trials_passed / trials
elif experiment():
return iter(trials_remaining - 1, trials_passed + 1)
else:
return iter(trials_remaining - 1, trials_passed)
return iter(trials, 0)
def estimate_pi(trials):
return math.sqrt(6.0 / monte_carlo(trials, cesaro_test))
print (estimate_pi(10))
# second version (no assignment)
def random_gcd_test(trials, initial_x):
def iter(trials_remaining, trials_passed, x):
x1 = rand_update(x)
x2 = rand_update(x1)
if trials_remaining == 0:
return trials_passed / trials
elif gcd(x1, x2) == 1:
return iter(trials_remaining - 1, trials_passed + 1, x2)
else:
return iter(trials_remaining - 1, trials_passed, x2)
return iter(trials, 0, initial_x)
def estimate_pi(trials):
return math.sqrt(6.0 / random_gcd_test(trials, random_init))
random_init = 7
print (estimate_pi(10))
# Exercise 3.6
# exercise left to reader to define appropriate functions
# def random_in_range(low, high):
# range = high - low
# return low + random(range)
# 3.1.3 - Assignment and State - The Cost of Introducing Assignment
def make_simplified_withdraw(init_balance):
balance = [init_balance]
def withdraw(amount):
balance[0] = balance[0] - amount
return balance[0]
return withdraw
w = make_simplified_withdraw(25)
print (w(20))
print (w(10))
def make_decrementer(balance):
return lambda amount: balance - amount
d = make_decrementer(25)
print (d(20))
print (d(10))
make_decrementer(25)(20)
(lambda amount: 25 - amount)(20)
25 - 20
make_simplified_withdraw(25)(20)
# Sameness and change
d1 = make_decrementer(25)
d2 = make_decrementer(25)
w1 = make_simplified_withdraw(25)
w2 = make_simplified_withdraw(25)
print (w1(20))
print (w1(20))
print (w2(20))
peter_acc = Account(100)
paul_acc = Account(100)
peter_acc = Account(100)
paul_acc = peter_acc
# Pitfalls of imperative programming
def factorial(n):
def iter(product, counter):
if counter > n:
return product
else:
return iter(counter * product, counter + 1)
return iter(1, 1)
def factorial(n):
product = 1
counter = 1
def iter():
if counter > n:
return product
else:
product = counter * product;
counter = counter + 1;
return iter()
return iter()
# Exercise 3.7
# exercise left to reader to define appropriate functions
# paul_acc = make_joint(peter_acc, "open_sesame", "rosebud")
# 3.2.1 - The Environment Model of Evaluation - The Rules for Evaluation
def square(x): return x * x
square = lambda x: x * x
# 3.2.2 - The Environment Model of Evaluation - Applying Simple Procedures
def square(x): x * x
def sum_of_squares(x, y):
return square(x) + square(y)
def f(a):
return sum_of_squares(a + 1, a * 2)
# Exercise 3.9
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1)
def fact_iter(product, counter, max_count):
if counter > max_count:
return product
else:
return fact_iter(counter * product, counter + 1, max_count)
def factorial(n):
return fact_iter(1, 1, n)
# 3.2.3 - The Environment Model of Evaluation - Frames as Repository of State
def make_withdraw(init_balance):
balance = [init_balance]
def withdraw(amount):
if balance[0] >= amount:
balance[0] = balance[0] - amount
return balance[0]
else:
print('InsufficientFunds: ' + str(balance[0]))
return ()
return withdraw
w1 = make_withdraw(100)
print (w1(50))
w2 = make_withdraw(100)
# Exercise 3.10
def make_withdraw(initial_amount):
balance = [initial_amount]
def withdraw(amount):
if balance[0] >= amount:
balance[0] = balance[0] - amount
return balance[0]
else:
print('InsufficientFunds: ' + str(balance[0]))
return nil
return withdraw
w1 = make_withdraw(100)
print (w1(50))
w2 = make_withdraw(100)
# 3.2.4 - The Environment Model of Evaluation - Internal Definitions
# same as in section 1.1.8
def sqrt(x):
def good_enough(guess):
return abs(square(guess) - x) < 0.001
def improve(guess):
return average(guess, x / guess)
def sqrt_iter(guess):
if good_enough(guess):
return guess
else:
return sqrt_iter(improve(guess))
return sqrt_iter(1.0)
# Exercise 3.11
class Account:
def __init__(self, init_balance):
self.balance = init_balance
def withdraw(self, amount):
if self.balance >= amount:
self.balance = self.balance - amount
return self.balance
else:
print('InsufficientFunds: ' + str(self.balance))
return ()
def deposit(self, amount):
self.balance = self.balance + amount
return self.balance
def getbalance(self):
return self.balance
acc = Account(50)
acc.deposit(40)
acc.withdraw(60)
print (acc.getbalance())
acc2 = Account(100)
|