20
false primes within a reasonable runtime.is_false_prime
function that uses both is_prime
and is_prime_like
.while
loop to find 20
false primes, since we don't know how high of integers we will need to check before finding 20
.n=20
.primary
that finds primary decompositions (including multiplicity).while
loop here to see how many times a prime factor divides the number.my_list = ['a','b','c','d','e','f','g','h']
my_list[0]
'a'
my_list[-1]
'h'
It is often useful to get a subset of a list. Suppose we want a sublist consisting of the index 3
, 4
, 5
, and 6
elements:
my_sublist = []
for i in range(len(my_list)):
if i >= 3 and i <= 6:
my_sublist.append(my_list[i])
my_sublist
['d', 'e', 'f', 'g']
A more elegant way to accomplish this task is by using list slicing. The syntax is:
my_list[start_index:stopping_index]
, which returns a sublist with indices greater than or equal to start_index
and strictly less than stopping_index
.my_list[3:7]
['d', 'e', 'f', 'g']
my_list[0:5]
['a', 'b', 'c', 'd', 'e']
my_list[3:-1]
['d', 'e', 'f', 'g']
We can also use slicing in the following ways:
my_list[start_index:]
will start the slice at start_index
and go the end of the list.my_list[:stopping_index]
will start the list at the beginning (i.e. 0
) and proceed until one less than stopping_index
.my_list[:]
will return the full listmy_list[start_index:-1]
will start the list at start_index
and end at the last index (excluding it)my_list[:-3]
['a', 'b', 'c', 'd', 'e']
my_list[3:]
['d', 'e', 'f', 'g', 'h']
Just like the range
function, we can use a third input as a step size for slices:
my_list
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
my_list[1:-1:2]
['b', 'd', 'f']
my_list[0:7:3]
['a', 'd', 'g']
my_list[::4]
['a', 'e']
integers = []
for i in range(100):
integers.append(i)
integers[1::2]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]
We can also check whether a list contains a particular element using the in
operator:
vowels = ['a','e','i','o','u']
'a' in vowels
True
'b' in vowels
False
for letter in 'buffalo':
if letter not in vowels:
print(letter)
b f f l
zip
function¶The zip
function gives a way to simultaneously iterate through a pair of lists in parallel.
list1 = [0,1,2,3,4,5]
list2 = ['a','b','c','d','e','f']
A pair of nested for
loops will iterate through every possible combination of elements of each list.
for item1 in list1:
for item2 in list2:
print(item1, item2)
0 a 0 b 0 c 0 d 0 e 0 f 1 a 1 b 1 c 1 d 1 e 1 f 2 a 2 b 2 c 2 d 2 e 2 f 3 a 3 b 3 c 3 d 3 e 3 f 4 a 4 b 4 c 4 d 4 e 4 f 5 a 5 b 5 c 5 d 5 e 5 f
In other situations, the elements of two lists might be in correspondence with one another. This is where we can use the zip
function to glue the two lists together in parallel and iterate through the corresponding pairs:
for item1, item2 in zip(list1, list2):
print(item1, item2)
0 a 1 b 2 c 3 d 4 e 5 f
For example, this may be useful in project 1 if you a list of false primes and a separate list of their corresponding prime factorizations.
Suppose we want to generate a list of square numbers 1**2, 2**2, ..., N**2
.
N = 10
squares = []
for n in range(1,N+1):
square = n**2
squares.append(square)
squares
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
We can accomplish this same task in one line by using list comprehension:
squares = [n**2 for n in range(1,N+1)]
squares
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
We can also use if
statement within a list comprehension:
[n**2 for n in range(1,N+1) if n**2 % 3 == 1]
[1, 4, 16, 25, 49, 64, 100]
[square for square in squares if square % 3 == 1]
[1, 4, 16, 25, 49, 64, 100]
n = 3
m = n
print(n)
print(m)
3 3
n = n + 5
print(n)
print(m)
8 3
list1 = [1,2,3,4]
list2 = list1
print(list1)
print(list2)
[1, 2, 3, 4] [1, 2, 3, 4]
list1[0] = 99
print(list1)
print(list2)
[99, 2, 3, 4] [99, 2, 3, 4]
What's going on here? Setting m = n
did not cause changes in n
to propogate back to m
, but in the list example, settings list2=list1
did cause changes to list1
to propogate to list2
.
The difference is that integers immutable objects while lists are mutable. For mutable objects, variable assigments point to a place in memory that stores the obect (in this case a list). That is, list1
and list2
point to the same location in memory. Changes to one affect the other.
We can use the id
function to check whether two objects share the same space in memory:
list1 = [1,2,3,4]
list2 = list1
id(list1)
2457623177728
id(list2)
2457623177728
list3 = [1,2,3,4]
id(list3)
2457623176512
Note: list1
and list3
contain the same values in their list:
list1 == list3
True
On the other hand, their contents reside in different memory positions. We can use the is
operator to check whether two objects point to the same memory location:
list1 is list3
False
Since they point to different memory locations, changes to one do not affect the other.
list1[0] = 99
print(list1)
print(list2)
print(list3)
[99, 2, 3, 4] [99, 2, 3, 4] [1, 2, 3, 4]
list1 is list2
True
Sometimes, we may want to copy a list to a new variable but sever this link. That is, have the new variable point to a new location in memory. We can use the .copy()
method:
list1 = [1,2,3,4]
list2 = list1.copy()
list1 == list2
True
list1 is list2
False
list1[-1] = 99
print(list1)
print(list2)
[1, 2, 3, 99] [1, 2, 3, 4]
We will the pyplot
submodule from the matplotlib
module for our plotting needs. Typically, we will import this submodule and assign it the name plt
.
import matplotlib.pyplot as plt
The plt.plot
function can be used for plotting:
x_list = [x for x in range(0,11)]
y_list = [x**2 for x in x_list]
plt.plot(x_list,y_list)
[<matplotlib.lines.Line2D at 0x23c38694eb0>]
By default, the plot
function will connect datapoints with a polygonal line. We can change this behavior by supplying a supplying a string that can control markers, color, and linestyle:
plt.plot(x_list,y_list,'c')
[<matplotlib.lines.Line2D at 0x23c388e08b0>]
There are many color characters available:
'r'
: red'g'
: green'b'
: blue'k'
: black'm'
: magenta'c'
: cyan'y'
: yellowWe can also specify a marker type:
plt.plot(x_list,y_list,'o')
[<matplotlib.lines.Line2D at 0x23c38944850>]
plt.plot(x_list,y_list,'.')
[<matplotlib.lines.Line2D at 0x23c389a59d0>]
plt.plot(x_list,y_list,'*')
[<matplotlib.lines.Line2D at 0x23c38a0b9d0>]
plt.plot(x_list,y_list,'+')
[<matplotlib.lines.Line2D at 0x23c38aaf9d0>]
plt.plot(x_list,y_list,'s')
[<matplotlib.lines.Line2D at 0x23c38b118b0>]
plt.plot(x_list,y_list,'mD')
[<matplotlib.lines.Line2D at 0x23c38b777f0>]
We can also choose a linestyle (polygonal lines, dashed lines, etc.)
plt.plot(x_list,y_list,'o-')
[<matplotlib.lines.Line2D at 0x23c39b68850>]
plt.plot(x_list,y_list,'r*-')
[<matplotlib.lines.Line2D at 0x23c39bcb8b0>]
plt.plot(x_list,y_list,'r*--')
[<matplotlib.lines.Line2D at 0x23c39c2a700>]
Instead of supplying this string formatter, we can use keyword arguments to specify a color
, a marker
, linestyle
:
plt.plot(x_list,y_list,color='r', marker='D', linestyle='dashdot')
[<matplotlib.lines.Line2D at 0x23c39e8d130>]
We can use plt.xlabel
and plt.ylabel
to add axis labels. These labels can include LaTeX:
plt.plot(x_list,y_list,color='r', marker='D', linestyle='dashdot')
plt.xlabel('$x$')
plt.ylabel('$y = x^2$')
Text(0, 0.5, '$y = x^2$')
We can use plt.title
to add a title the plot:
plt.plot(x_list,y_list,color='r', marker='D', linestyle='dashdot')
plt.xlabel('$x$')
plt.ylabel('$y = x^2$')
plt.title('My plot')
Text(0.5, 1.0, 'My plot')
x_list = [x for x in range(0,11)]
y_list1 = [x**2 for x in x_list]
y_list2 = [100 - x**2 for x in x_list]
plt.plot(x_list,y_list1,color='r', marker='D', linestyle='dashdot')
plt.plot(x_list,y_list2,color='b', marker='s', linestyle='solid')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.title('My plot')
Text(0.5, 1.0, 'My plot')
We can add labels to plots using the label
keyword argument, and then add a legend using the plt.legend()
function.
x_list = [x for x in range(0,11)]
y_list1 = [x**2 for x in x_list]
y_list2 = [100 - x**2 for x in x_list]
plt.plot(x_list,y_list1,color='r', marker='D', linestyle='dashdot', label='$y = x^2$')
plt.plot(x_list,y_list2,color='b', marker='s', linestyle='solid', label='$y = 100 - x^2$')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.title('My plot')
plt.legend()
<matplotlib.legend.Legend at 0x23c3b42dc70>
We can change the horizontal and vertical limits using the plt.xlim
and plt.ylim
function:
x_list = [x for x in range(0,11)]
y_list1 = [x**2 for x in x_list]
y_list2 = [100 - x**2 for x in x_list]
plt.xlim(4,8)
plt.ylim(20,80)
plt.plot(x_list,y_list1,color='r', marker='D', linestyle='dashdot', label='$y = x^2$')
plt.plot(x_list,y_list2,color='b', marker='s', linestyle='solid', label='$y = 100 - x^2$')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.title('My plot')
plt.legend()
<matplotlib.legend.Legend at 0x23c3b207400>
We can use plt.grid()
to add grid lines to the interior of the plot:
x_list = [x for x in range(0,11)]
y_list1 = [x**2 for x in x_list]
y_list2 = [100 - x**2 for x in x_list]
plt.xlim(4,8)
plt.ylim(20,80)
plt.plot(x_list,y_list1,color='r', marker='D', linestyle='dashdot', label='$y = x^2$')
plt.plot(x_list,y_list2,color='b', marker='s', linestyle='solid', label='$y = 100 - x^2$')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.title('My plot')0
plt.legend()
plt.grid()