DoingMathWithPython_Solutions
DoingMathWithPython_Solutions
with Py thon
Solutions to
P r o g r a mm i n g C h a l l e n g e s
Contents
'''
even_odd_vending.py
Print whether the input is even or odd. If even, print the next 9 even numbers
If odd, print the next 9 odd numbers.
'''
def even_odd_vending(num):
u if (num % 2) == 0:
print('Even')
else:
print('Odd')
count = 1
v while count <= 9:
num += 2
print(num)
# increment the count of numbers printed
count += 1
if __name__ == '__main__':
try:
num = float(input('Enter an integer: '))
if num.is_integer():
even_odd_vending(int(num))
else:
print('Please enter an integer')
except ValueError:
print('Please enter a number')
If the user enters an even number when they run the program, it will
print Even and the next nine even numbers:
Enter an integer: 2
Even
4
6
8
10
12
14
16
18
20
For an odd number, Odd will be printed along with the next nine odd
numbers.
'''
enhanced_multi_table.py
if __name__ == '__main__':
try:
a = float(input('Enter a number: '))
n = float(input('Enter the number of multiples: '))
if not n.is_integer() or n < 0:
print('The number of multiples should be a positive integer')
else:
multi_table(a, int(n))
except ValueError:
print('You entered an invalid input')
'''
enhanced_unit_converter.py
Unit converter:
def print_menu():
print('1. Kilometers to Miles')
print('2. Miles to Kilometers')
print('3. Kilograms to Pounds')
print('4. Pounds to Kilograms')
print('5. Celsius to Fahrenheit')
print('6. Fahrenheit to Celsius')
def km_miles():
km = float(input('Enter distance in kilometers: '))
miles = km / 1.609
print('Distance in miles: {0}'.format(miles))
def miles_km():
miles = float(input('Enter distance in miles: '))
km = miles * 1.609
print('Distance in kilometers: {0}'.format(km))
def kg_pounds():
kg = float(input('Enter weight in kilograms: '))
pounds = kg * 2.205
print('Weight in pounds: {0}'.format(pounds))
def pounds_kg():
pounds = float(input('Enter weight in pounds: '))
kg = pounds / 2.205
print('Weight in kilograms: {0}'.format(kg))
def cel_fahren():
celsius = float(input('Enter temperature in Celsius: '))
fahrenheit = celsius*(9 / 5) + 32
print('Temperature in fahrenheit: {0}'.format(fahrenheit))
def fahren_cel():
fahrenheit = float(input('Enter temperature in Fahrenheit: '))
celsius = (fahrenheit - 32)*(5/9)
print('Temperature in celsius: {0}'.format(celsius))
if __name__ == '__main__':
print_menu()
choice = input('Which conversion would you like to do? ')
if choice == '1':
km_miles()
if choice == '2':
miles_km()
if choice == '3':
kg_pounds()
if choice == '4':
pounds_kg()
if choice == '5':
cel_fahren()
if choice == '6':
fahren_cel()
Four new functions have been added to our earlier program. The
kg_pounds() function accepts a mass in kilograms as input and returns the
corresponding mass in pounds. The reverse conversion is performed by the
pounds_kg() function. The cel_fahren() and fahren_cel() functions convert
Celsius to Fahrenheit and Fahrenheit to Celsius, respectively.
When the program is run, it asks the user to enter a number from 1 to
6 to choose which conversion they want to perform. Next it asks them to
input the relevant quantity, and then it outputs the converted result:
1. Kilometers to Miles
2. Miles to Kilometers
3. Kilograms to Pounds
4. Pounds to Kilograms
5. Celsius to Fahrenheit
6. Fahrenheit to Celsius
Which conversion would you like to do? 5
Enter temperature in Celsius: 37
Temperature in Fahrenheit: 98.60000000000001
If the user enters a number that is not one of the numbers recognized
by the program, it silently exits. You may want to print a helpful message to
indicate this in your solution.
'''
fractions_operations.py
Fraction operations
'''
if __name__ == '__main__':
try:
a = Fraction(input('Enter first fraction: '))
b = Fraction(input('Enter second fraction: '))
op = input('Operation to perform - Add, Subtract, Divide, Multiply: ')
if op == 'Add':
add(a, b)
if op == 'Subtract':
subtract(a, b)
if op == 'Divide':
divide(a, b)
if op == 'Multiply':
multiply(a, b)
except ValueError:
print('Invalid fraction entered')
When the program is run, it will ask for two fractions and the operation
to be carried out. Then it will display the result of that operation. Here is
an example with the Subtract operation:
If the user enters an invalid input, such as 1, the program will print an
error message.
'''
fractions_operations_exit_power.py
if __name__ == '__main__':
while True:
try:
a = Fraction(input('Enter first fraction: '))
b = Fraction(input('Enter second fraction: '))
op = input('Operation to perform - Add, Subtract, Divide, Multiply: ')
if op == 'Add':
add(a, b)
if op == 'Subtract':
subtract(a, b)
if op == 'Divide':
divide(a, b)
if op == 'Multiply':
multiply(a, b)
except ValueError:
print('Invalid fraction entered')
answer = input('Do you want to exit? (y) for yes ')
if answer == 'y':
break
You can find another example, the modified unit conversion program,
in the file enhanced_unit_converter_exit_power.py, along with other solutions.
Once you have the plot, make two lists: one to store the time of day,
and the other to store the corresponding temperature forecast at that
time. Then call the plot() function to create a graph. The time of day
is shown as strings. However, if you attempt to pass in a list of strings to
the plot() function, your program will fail and give you an error. After
all, what sense does it make to state that you want a point to be plotted at
(“7 am”, 70)? Instead, assign numbers to each time of day that you want to
plot—that is, 1 for 4 am, 2 for 7 am, and so on. Then, use the xticks() func-
tion to change the labels of these numbers to match the time of day they
correspond to. Here’s the solution to the challenge:
'''
nyc_forecast_basic.py
def plot_forecast():
time_of_day = ['4 AM', '7 AM', '10 AM', '1 PM', '4 PM', '7PM', '10 PM']
forecast_temp = [71, 70, 74, 80, 82, 81, 76]
u time_interval = range(1, len(time_of_day) + 1)
if __name__ == '__main__':
plot_forecast()
'''
quad_function_plot.py
if __name__ == '__main__':
# assume values of x
u x_values = range(-100, 100, 20)
y_values = []
for x in x_values:
# calculate the value of the quadratic
# function
y_values.append(x**2 + 2*x + 1)
draw_graph(x_values, y_values)
When you run the program, the graph of the function will look some-
thing like Figure 2.
2
Figure 2: Graph of the quadratic function x + 2x + 1. Increasing the number
of points between −10 and 10 will make the graph appear smoother.
"""
projectile_comparison_gen.py
Compare the projectile motion of a body thrown with various combinations of initial
velocity and angle of projection
"""
g = 9.8
numbers = []
while start < final:
numbers.append(start)
start = start + interval
return numbers
if __name__ == '__main__':
velocities = []
angles = []
for i in range(1, num_trajectories+1):
v = input('Enter the initial velocity for trajectory {0} (m/s): '.format(i))
theta = input('Enter the angle of projection for trajectory {0} (degrees): '.format(i))
velocities.append(float(v))
angles.append(math.radians(float(theta)))
for i in range(num_trajectories):
# Calculate time of flight, maximum horizontal distance and
# maximum vertical distance
t_flight = 2*velocities[i]*math.sin(angles[i])/g
S_x = velocities[i]*math.cos(angles[i])*t_flight
S_y = velocities[i]*math.sin(angles[i])*(t_flight/2) - (1/2)*g*(t_flight/2)**2
u print('Initial velocity: {0} Angle of Projection: {1}'.format(velocities[i],
math.degrees(angles[i])))
print('T: {0} S_x: {1} S_y: {2}'.format(t_flight, S_x, S_y))
print()
v draw_trajectory(velocities[i], angles[i], t_flight)
When executed, the program first asks for the number of trajectories
that the user wants to compare. Then it asks for the initial velocity and
angle of projection for each trajectory. For each of these trajectories, it
prints the time of flight, range, and maximum vertical height reached u
and calls the draw_trajectory() function v, which creates a plot for each
trajectory.
To identify which trajectory corresponds to which initial velocity and
angle, we add a legend to the graph w. Finally, we call the show() function to
show the graph.
Here’s a sample run:
Figure 3 shows the graph created by the program. You can see the
three different trajectories with a legend showing which trajectory belongs
to which combination of initial velocity and angle of projection.
'''
expenditures_barchart.py
if __name__ == '__main__':
n = int(input('Enter the number of categories: '))
labels = []
expenditures = []
for i in range(n):
category = input('Enter category: ')
expenditure = float(input('Expenditure: '))
w labels.append(category)
x expenditures.append(expenditure)
y create_bar_chart(expenditures, labels)
The input categories are stored in the list labels w, which will also
be used for the labels in the bar chart. The corresponding expenditure
for each category is stored in the list expenditures x. We then call the
create_bar_chart() function y with the expenditures as the first argument
and labels as the second argument. This function then calls the barh() func-
tion u with the appropriate arguments, setting the axes labels and other
details, and finally calls the show() function v, which displays the bar chart
showing the expenditures for each category.
#5: Exploring the Relationship Between the Fibonacci Sequence and the
Golden Ratio
For the solution to this challenge, we’ll calculate the first 100 numbers
of the Fibonacci sequence using the fibo() function mentioned in the
challenge description. Then we will calculate the consecutive difference
between these numbers, store those differences in a list, and use the plot()
function to create a graph that shows these differences. Here’s the solution:
'''
fibonacci_goldenration.py
#5: Exploring the Relationship Between the Fibonacci Sequence and the Golden Ratio 13
Doing Math with Python (Programming Challenge Solutions), © 2015 by Amit Saha
def fibo(n):
if n == 1:
return [1]
if n == 2:
return [1, 1]
# n > 2
a = 1
b = 1
# first two members of the series
series = [a, b]
for i in range(n):
c = a + b
series.append(c)
a = b
b = c
return series
def plot_ratio(series):
ratios = []
u for i in range(len(series)-1):
ratios.append(series[i+1]/series[i])
plt.plot(ratios)
plt.title('Ratio between Fibonacci numbers & golden ratio')
plt.ylabel('Ratio')
plt.xlabel('No.')
plt.show()
if __name__ == '__main__':
# Number of fibonacci numbers
num = 100
series = fibo(num)
plot_ratio(series)
The for loop at u is the key step in the plot_ratio() function. We loop
through the numbers of the Fibonacci sequence and store the difference
between the second term and the first term, the third term and the second
term, and so on, in the list ratios. We then call the plot() function, add a
title and axes labels, and finally call the show() function to show the graph.
'''
linear_correlation_enhanced.py
'''
def find_corr_x_y(x,y):
u if len(x) != len(y):
print('The two sets of numbers are of unequal size')
return None
n = len(x)
# numerator
numerator = n*sum_prod_x_y - sum_x*sum_y
denominator_term1 = n*x_square_sum - squared_sum_x
denominator_term2 = n*y_square_sum - squared_sum_y
denominator = (denominator_term1*denominator_term2)**0.5
Doing Math with Python (Programming Challenge Solutions), © 2015 by Amit Saha
correlation = numerator/denominator
return correlation
Besides adding the check for the length of the two lists right at the
beginning u, you can see that I’ve also used list comprehensions (as
explained in Appendix B) to make some parts of the program more
compact (for example, at v and w).
Now, if you call this function with two sets of data, each containing the
same number of items, it will return the correlation coefficient as it did
before. If the two sets of data have an unequal number of items, it returns
None. When you use this function in your programs, you have to check the
return value and take appropriate action depending on the result.
corr = find_corr_x_y(x,y)
if not corr:
print('Correlation correlation could not be calculated')
else:
print('The correlation coefficient between x and y is {0}'.format(corr))
For example, if the return value is None, we print a message saying that
that the correlation coefficient could not be calculated.
'''
statistics_calculator.py
def read_data(filename):
numbers = []
with open(filename) as f:
for line in f:
numbers.append(float(line))
return numbers
if __name__=='__main__':
v data = read_data('mydata.txt')
m = mean(data)
median = median(data)
mode = mode(data)
variance, sd = variance_sd(data)
print('Mean: {0:.5f}'.format(m))
print('Median: {0:.5f}'.format(median))
print('Mode: {0:.5f}'.format(mode))
print('Variance: {0:.5f}'.format(variance))
print('Standard deviation: {0:.5f}'.format(sd))
'''
us_population_stats.py
Read the US population data from a CSV file, calculate the growth in
population in consecutive years, and compute various statistical measures
Also creates two graphs - one showing the total population over the years and
the other showing the change between consecutive years
'''
def read_csv(filename):
years = []
population = []
with open(filename) as f:
reader = csv.reader(f)
next(reader)
summer = []
highest_correlated = []
def calculate_stats(population):
if __name__ == '__main__':
population, years = read_csv('USA_SP_POP_TOTL.csv')
plot_population(population, years)
growth = calculate_stats(population)
plot_population_diff(growth, years)
plt.show()
The read_csv() function reads the data from the file to create two lists:
years and population, which contain the year and the corresponding popula-
tion of each year, respectively. As described earlier, the file contains a date,
but we want to extract just the year (so that the text fits in our graphs),
which is what we do at u. The split() method returns a list of words from a
string and splits the string at the specified delimiter. For example:
>>> d = '2012-09-10'
>>> d.split('-')
['2012', '09', '10']
Thus, if we wanted the year 2012, we would grab the first item in the
returned list:
Since we read the file from the beginning and the latest dates are listed
first, we reverse both lists before returning them with the reverse() method.
The reverse() method reverses a list in place. For example, say that list =
[1, 2, 3]. Calling list.reverse() would change list to [3, 2, 1]. Once we have
the two lists of the years and the population figures, we create the first graph
that shows the population over the years in the function plot_population().
Since we plan to create two separate graphs, we create a figure explicitly by
calling the figure() function and assigning it a number, 1, at v. We plot the
population and add the years as the x-axis labels using the xticks() func-
tion w. The rotation keyword argument lets us display the labels at an angle
so that the consecutive years do not overlap. Here, we specify that the label be
at a 45-degree angle.
In the calculate_stats() function, we calculate and print the statistical
measures of the population growth using the functions that are now part
of the stats module. This function also returns the list growth, which con-
tains the growth in population over consecutive years.
The plot_population_diff() function creates a second figure and plots
the population growth over the years. We use list comprehension to create
a list of labels for the x-axis of the form 1960–1961, 1961–1962 and so on
to indicate the years x. We also specify that we want the labels to be at an
angle of 45 degrees using of the rotation keyword argument.
When you run the program, you should see two graphs side by side as
shown in Figure 5.
One window will be titled Figure 1 and the other Figure 2, and the statis-
tical measures will be printed as shown here:
You will need to maximize the graph windows to see the x-axis labels
clearly.
'''
percentile_score.py
n = len(data)
v i = ((n*percentile)/100) + 0.5
if i.is_integer():
real_idx = int(i-1)
w return data[real_idx]
else:
x k = int(i)
y f = i - k
real_idx_1 = k - 1
real_idx_2 = k
z return (1-f)*data[real_idx_1] + f*data[real_idx_2]
def read_data(filename):
numbers = []
with open(filename) as f:
for line in f:
numbers.append(float(line))
return numbers
if __name__ == '__main__':
percentile = float(input('Enter the percentile score you want to calculate: '))
data = read_data('marks.txt')
percentile_score = find_percentile_score(data, percentile)
if percentile_score:
print('The score at {0} percentile: {1}'.format(percentile, percentile_score))
else:
print('Could not find the score corresponding to {0} percentile'.format(percentile))
However, this algorithm doesn’t work for percentiles that are greater
than 98 with this set of data. An alternative algorithm is implemented
'''
percentile_score_microsoft_excel.py
'''
real_idx_1 = k-1
real_idx_2 = k
def read_data(filename):
numbers = []
with open(filename) as f:
for line in f:
numbers.append(float(line))
return numbers
if __name__ == '__main__':
percentile = float(input('Enter the percentile score you want to calculate: '))
data = read_data('marks.txt')
percentile_score = find_percentile_score(data, percentile)
if percentile_score:
print('The score at {0} percentile: {1}'.format(percentile, percentile_score))
else:
print('Could not find the score corresponding to {0} percentile'.format(percentile))
The key step in this program is at u, where we calculate the rank. Then
we extract the integer and the fractional part of the rank at v and w and
return the number corresponding to the specified percentile at x.
'''
grouped_frequency.py
def read_data(filename):
numbers = []
with open(filename) as f:
for line in f:
numbers.append(float(line))
return numbers
if __name__ == '__main__':
When the program runs, it asks the user to input the desired number
of classes and reads the data from the marks.txt file into a list, numbers. We
then call the function create_classes(), which returns the specified number
of classes referred to by the label classes and calls the classify() function,
which returns a list containing the count of the numbers in each class. We
finally print the table by going over the two lists using the zip() function.
Here’s a sample execution of the program:
You can see that the size of each class is approximately 2.37.
'''
factorizer.py
def factorize(expr):
return factor(expr)
if __name__ == '__main__':
u expr = input('Enter an expression to factorize: ')
try:
expr_obj = sympify(expr)
except SympifyError:
print('Invalid expression entered as input')
else:
print(factorize(expr_obj))
'''
graphical_eq_solve.py
if __name__=='__main__':
try:
eq1 = sympify(eq1)
eq2 = sympify(eq2)
except SympifyError:
print('Invalid input')
else:
x = Symbol('x')
y = Symbol('y')
# check if the expressions consist of only two variables
u eq1_symbols = eq1.atoms(Symbol)
v eq2_symbols = eq2.atoms(Symbol)
Figure 6 shows a graph of the two input equations that also demon-
strates the solution of the two equations (1, 0).
'''
series_summation.py
if __name__ == '__main__':
n_term = sympify(input('Enter the nth term: '))
num_terms = int(input('Enter the number of terms: '))
find_sum(n_term, num_terms)
We ask the user to input the nth term of the series, and the number of
terms they want to sum. We then call the find_sum() function, which calls
SymPy’s summation() function, passing the nth term as the first argument.
The second argument is a tuple consisting of the symbol, 1, and the number
of terms up to which we want to find the sum. We then pretty print the sum
using the pprint() function. Here is a sample run:
'''
isolve.py
def isolve(ineq_obj):
x = Symbol('x')
expr = ineq_obj.lhs
rel = ineq_obj.rel_op
if expr.is_polynomial():
p = Poly(expr, x)
return solve_poly_inequality(p, rel)
elif expr.is_rational_function():
p1, p2 = expr.as_numer_denom()
num = Poly(p1)
denom = Poly(p2)
return solve_rational_inequalities([[((num, denom), rel)]])
else:
return solve_univariate_inequality(ineq_obj , x, relational=False)
if __name__ == '__main__':
ineq = input('Enter the inequality to solve: ')
try:
ineq_obj = sympify(ineq)
except SympifyError:
print('Invalid inequality')
else:
# We check if the input expression is an inequality here
u if isinstance(ineq_obj, Relational) and not isinstance(ineq_obj, Equality):
print(isolve(ineq_obj))
else:
print('Invalid inequality')
The program asks the user to input an inequality and then converts
it into a SymPy object using the sympify() function. We then check whether
the expression is an inequality and not any arbitrary expression. We do this
by using the isinstance() Python function u to check whether the object
returned by the sympify() function is a Relational object and whether it
is not an Equality object. This check is needed because only a Relational
object has a rel_op attribute that refers to the relational operator (>, >=,
< and <=) that will be used later in the function isolve(). Once we have
checked whether the input is an inequality, we call the isolve() function.
In the isolve() function, we use the functions is_polynomial() and
is_rational_function() to check if the inequality is a polynomial or a rational
function and call the appropriate inequality-solver function. If it is neither,
we call the solve_univariate_inequality() function.
Here is a sample execution for a polynomial inequality:
"""
venn_sports.py
def read_csv(filename):
football = []
others = []
with open(filename) as f:
reader = csv.reader(f)
next(reader)
for row in reader:
if row[1] == '1':
football.append(row[0])
if row[2] == '1':
others.append(row[0])
if __name__ == '__main__':
football, others = read_csv('sports.csv')
u f = FiniteSet(*football)
v o = FiniteSet(*others)
draw_venn(f, o)
The key step is creating the two sets—the set of students who like foot-
ball and the set of students who like another sport—by reading the data
from sports.csv, which is created by compiling the results from the survey.
This file is read by the read_csv() function, which creates two lists made up
of student IDs (football and others), and returns them.
Doing Math with Python (Programming Challenge Solutions), © 2015 by Amit Saha
'''
law_ln.py
Verify the law of large numbers using a six-sided die roll as an example
'''
import random
def roll(num_trials):
rolls = []
for t in range(num_trials):
rolls.append(random.randint(1, 6))
return sum(rolls)/num_trials
if __name__ == '__main__':
expected_value = 3.5
print('Expected value: {0}'.format(expected_value))
for trial in [100, 1000, 10000, 100000, 500000]:
avg = roll(trial)
print('Trials: {0} Trial average {1}'.format(trial, avg))
'''
game_tosses.py
A player wins 1$ for every head and loses 1.5$ for every tail.
def play(start_amount):
win_amount = 1
loss_amount = 1.5
cur_amount = start_amount
tosses = 0
if __name__ == '__main__':
start_amount = float(input('Enter your starting amount: '))
play(start_amount)
When the program runs, it asks the user to enter a starting point and
then calls the play() function to start the game.
Then, using a while loop, it continues tossing a coin until the current
amount (cur_amount) is less than or equal to 0 u. The coin toss is simulated
using the random.randint() function so that either a 0 or 1 is returned v. For
every heads (that is, the number 0), we add 1 to the current amount, and
for every tails (the number 1), we deduct 1.5. We keep a count of the total
number of coin tosses via the label tosses.
'''
shuffle_enhanced.py
class Card:
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
def initialize_deck():
suits = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
ranks = ['Ace', '2', '3','4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King']
cards = []
for suit in suits:
for rank in ranks:
u card = Card(suit, rank)
cards.append(card)
return cards
def shuffle_and_print(cards):
v random.shuffle(cards)
w for card in cards:
print('{0} of {1}'.format(card.rank, card.suit))
if __name__ == '__main__':
cards = initialize_deck()
shuffle_and_print(cards)
'''
estimate_circle_area.py
in_circle = 0
for i in range(total_points):
x = random.uniform(0, 2*radius)
y = random.uniform(0, 2*radius)
p = (x, y)
# distance of the point created from circle's center
d = math.sqrt((p[0]-center[0])**2 + (p[1]-center[1])**2)
if d <= radius:
in_circle += 1
area_of_square = (2*radius)**2
return (in_circle/total_points)*area_of_square
if __name__ == '__main__':
radius = float(input('Radius: '))
area_of_circle = math.pi*radius**2
for points in [10**3, 10**5, 10**6]:
print('Area: {0}, Estimated ({1}): {2}'.
format(area_of_circle, points, estimate(radius, points)))
Radius: 1
Area: 3.141592653589793, Estimated (1000): 3.14
Area: 3.141592653589793, Estimated (100000): 3.14756
Area: 3.141592653589793, Estimated (1000000): 3.143504
The program to estimate the value of π has just a slight change from
the previous program:
'''
estimate_pi.py
def estimate(total_points):
radius = 1
center = (radius, radius)
in_circle = 0
for i in range(total_points):
x = random.uniform(0, 2*radius)
y = random.uniform(0, 2*radius)
p = (x, y)
# distance from circle's center
d = math.sqrt((p[0]-center[0])**2 + (p[1]-center[1])**2)
if d <= radius:
in_circle += 1
return (in_circle/total_points)*4
if __name__ == '__main__':
for points in [10**3, 10**5, 10**6]:
print('Known value: {0}, Estimated ({1}): {2}'.
format(math.pi, points, estimate(points)))
'''
circle_in_square.py
Circles in a square
'''
def draw_square():
square = plt.Polygon([(1, 1), (5, 1), (5, 5), (1, 5)], closed=True)
return square
if __name__ == '__main__':
ax = plt.gca()
s = draw_square()
ax.add_patch(s)
y = 1.5
u while y < 5:
x = 1.5
v while x < 5:
w c = draw_circle(x, y)
x ax.add_patch(c)
x += 1.0
y += 1.0
plt.axis('scaled')
plt.show()
First we add a square (each side of the square has a length of 4) to the
figure by creating a Polygon object with the draw_square() function. Then,
using two while loops at u and v, we add circles, each with a radius of 0.5,
so that they all lie inside the square. At w we draw the circle and at x we
add the circle to the figure.
'''
sierpinski.py
Doing Math with Python (Programming Challenge Solutions), © 2015 by Amit Saha
def transformation_1(p):
x = p[0]
y = p[1]
x1 = 0.5*x
y1 = 0.5*y
return x1, y1
def transformation_2(p):
x = p[0]
y = p[1]
x1 = 0.5*x + 0.5
y1 = 0.5*y + 0.5
return x1, y1
def transformation_3(p):
x = p[0]
y = p[1]
x1 = 0.5*x + 1
y1 = 0.5*y
return x1, y1
def get_index(probability):
r = random.random()
c_probability = 0
sum_probability = []
for p in probability:
c_probability += p
sum_probability.append(c_probability)
for item, sp in enumerate(sum_probability):
if r <= sp:
return item
return len(probability)-1
def transform(p):
# list of transformation functions
transformations = [transformation_1, transformation_2, transformation_3]
probability = [1/3, 1/3, 1/3]
# pick a random transformation function and call it
tindex = get_index(probability)
t = transformations[tindex]
x, y = t(p)
return x, y
def draw_sierpinski(n):
# We start with (0, 0)
x = [0]
y = [0]
x1, y1 = 0, 0
for i in range(n):
x1, y1 = transform((x1, y1))
x.append(x1)
y.append(y1)
return x, y
if __name__ == '__main__':
n = int(input('Enter the desired number of points'
'in the Sierpinski Triangle: '))
x, y = draw_sierpinski(n)
# Plot the points
plt.plot(x, y, 'o')
plt.title('Sierpinski with {0} points'.format(n))
plt.show()
Similar to the program we wrote to draw the Barnsley fern, this pro-
gram has three different functions—transformation_1(), transformation_2(),
and transformation_3()—that correspond to the three possible transfor-
mations, one of which is selected with an equal probability during each
transformation.
When the program is run, it asks the user to enter the desired number
of points in the triangle. This also corresponds to the number of iterations
or transformations our initial point (0, 0) undergoes.
Experiment with the number of points to see different triangles.
'''
henon.py
def transform(p):
x,y = p
x1 = y + 1.0 - 1.4*x**2
y1 = 0.3*x
return x1, y1
if __name__ == '__main__':
p = (0, 0)
x = [p[0]]
y = [p[1]]
for i in range(20000):
p = transform(p)
x.append(p[0])
y.append(p[1])
plt.plot(x, y, 'o')
plt.show()
'''
henon_animation.py
'''
def transform(p):
x,y = p
x1 = y + 1.0 - 1.4*x**2
y1 = 0.3*x
return x1, y1
if __name__ == '__main__':
p = (0, 0)
x = [p[0]]
y = [p[1]]
for i in range(10000):
p = transform(p)
x.append(p[0])
y.append(p[1])
fig = plt.gcf()
ax = plt.axes(xlim = (min(x), max(x)),
ylim = (min(y), max(y)))
u plot = plt.plot([], [], 'o')[0]
anim = animation.FuncAnimation(fig, update_points,
fargs=(x, y, plot),
frames = len(x),
interval = 25)
plt.title('Henon Function Animation')
plt.show()
First we create two lists to store the coordinates of all the points.
Then, we create an empty plot by calling the plot() function with two
empty lists u. Recall that matplotlib’s plot() function returns a list of
objects (Chapter 2), and in this case there is only one object, which we
retrieve using the index 0. We create a label, plot, to refer to that object.
Then, we create the FuncAnimation object with the relevant arguments. The
animation will use the number of points to set the number of frames.
Frame 1 will have only the first point, frame 2 will have the first two points,
and so on. The update_points() function updates the figure each frame. In
the update_points() function, we use matplotlib’s set_data() function to add
points to plot. In frame i we specify that we want the first i points stored in
the x and y lists.
When you run the program, you should see an animation showing all
the points lined along the curves.
'''
mandelbrot.py
'''
import matplotlib.pyplot as plt
import matplotlib.cm as cm
def mandelbrot_set():
# Number of divisions along each axis
n = 400
# Maximum iterations
max_iteration=1000
image = initialize_image(n, n)
for i, x in enumerate(x_coords):
for k, y in enumerate(y_coords):
z1 = complex(0, 0)
iteration = 0
c = complex(x, y)
w while (abs(z1) < 2 and iteration < max_iteration):
z1 = z1**2 + c
iteration += 1
x image[k][i] = iteration
return image
if __name__ == '__main__':
image = mandelbrot_set()
y plt.imshow(image, origin='lower', extent=(x0, x1, y0,y1),
cmap=cm.Greys_r, interpolation='nearest')
plt.show()
Figure 7: Mandelbrot set drawn by plotting 1,600 points in the region bounded by
(−2.5, −1.0) and (1.0, 1.0).
If you change the number of points along each axis and play around
with the number of iterations, you can observe the effect of each change on
the final figures you see.
'''
verify_continuity.py
if __name__ == '__main__':
f = input('Enter a function in one variable: ')
var = input('Enter the variable: ')
a = float(input('Enter the point to check the continuity at: '))
try:
f = sympify(f)
except SympifyError:
print('Invalid function entered')
else:
var = Symbol(var)
d = check_continuity(f, var, a)
'''
grad_descent.py
numbers = []
while start < final:
numbers.append(start)
start = start + interval
return numbers
if __name__ == '__main__':
Figure 8: Graph showing the function 3x 2 + 2x and how gradient descent finds the mini-
mum of the function
'''
area_curves.py
if __name__ == '__main__':
f = input('Enter the upper function in one variable: ')
g = input('Enter the lower function in one variable: ')
var = input('Enter the variable: ')
l = float(input('Enter the lower bound of the enclosed region: '))
u = float(input('Enter the upper bound of the enclosed region: '))
try:
f = sympify(f)
g = sympify(g)
except SympifyError:
print('One of the functions entered is invalid')
else:
var = Symbol(var)
print('Area enclosed by {0} and {1} is: {2} '.
format(f, g, find_area(f, g, var, l, u)))
When the program runs, it asks the user to input two functions (the
lower and upper bounds of the variable) and calls the find_area() function
with these values. The find_area() function then calculates the integral
by creating the Integral object, which is the area enclosed by the two curves
between a and b. An example execution of the program is as follows:
I should note that this challenge describes a specific case of finding the
area between curves. You can learn about other cases at http://tutorial.math
.lamar.edu/Classes/CalcI/AreaBetweenCurves.aspx and write programs to solve
them. This example demonstrates solving an adaptation of this website’s
Example 2 using our program.
'''
length_curve.py
if __name__ == '__main__':
f = input('Enter a function in one variable: ')
var = input('Enter the variable: ')
l = float(input('Enter the lower limit of the variable: '))
u = float(input('Enter the upper limit of the variable: '))
try:
f = sympify(f)
except SympifyError:
print('Invalid function entered')
else:
var = Symbol(var)
print('Length of {0} between {1} and {2} is: {3} '.
format(f, l, u, find_length(f, var, l, u)))
A sample of the program is shown here using the example in the chal-
lenge description as the input: