Monday, January 27th¶

Last time, we had just started discussing defining variables in Python.

In [1]:
a = 5
b = 7
c = -2
In [2]:
a
Out[2]:
5
In [3]:
a + b * c
Out[3]:
-9

Variable names must:

  • Start with a letter or underscore (_)
  • Can contain any letter, number, or underscore.
In [4]:
this_is_a_variable_name = 10
In [5]:
_this_is_another_variable_name = -4
In [6]:
variable3 = 100
In [7]:
3rd_variable = 10
  File "C:\Users\Luke\AppData\Local\Temp\ipykernel_32096\1144555293.py", line 1
    3rd_variable = 10
     ^
SyntaxError: invalid syntax

Very often, we'll use underscores as spaces to separate words in our variable names. Another style (known as camelcase) uses capital letters to denote the start of a new word.

In [8]:
thisIsAnotherVariableName = -4

In general, we want to choose variable names that helps the reader understand what they represent.

We can define several variables simultaneously by separating them by commas:

In [9]:
a, b, c = 1, 2, 3
In [10]:
a
Out[10]:
1
In [11]:
b
Out[11]:
2
In [12]:
c
Out[12]:
3

This can be very useful if we ever want to swap the meaning of two variables. As an example, suppose we define a = 1 and b = 2, but then want to swap their values.

In [13]:
a = 1
b = 2

a = b
b = a
In [14]:
a
Out[14]:
2
In [15]:
b
Out[15]:
2
In [16]:
a = 1
b = 2

old_a = a
a = b
b = old_a
In [17]:
a
Out[17]:
2
In [18]:
b
Out[18]:
1

We can use comma separated variable definition to perform this swap:

In [19]:
a = 1
b = 2

a,b = b,a
In [20]:
a
Out[20]:
2
In [21]:
b
Out[21]:
1

Working with strings¶

In Python, strings are used to hold text data. We can define strings by surrounding some text by double quotes " or single quotes ':

In [23]:
this_is_a_string = 'Hello, welcome to MTH 337'
In [24]:
this_is_a_string
Out[24]:
'Hello, welcome to MTH 337'

There are many operations that can be performed on strings. For example:

In [25]:
'this is a string' + 'this is a second string'
Out[25]:
'this is a stringthis is a second string'

Addition strings together concatenates them.

In [26]:
'this is a string' * 5
Out[26]:
'this is a stringthis is a stringthis is a stringthis is a stringthis is a string'

Multiplying a string by an integer concatenates it by the integer number of times.

In [27]:
'this is a string' * 2.5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_32096\3984047980.py in <module>
----> 1 'this is a string' * 2.5

TypeError: can't multiply sequence by non-int of type 'float'
In [28]:
'123' * 5
Out[28]:
'123123123123123'
In [30]:
123 * 5 
Out[30]:
615
In [31]:
123 * '5'
Out[31]:
'555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555'
In [32]:
'123' * '456'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_32096\114232278.py in <module>
----> 1 '123' * '456'

TypeError: can't multiply sequence by non-int of type 'str'

We can also define multi-line strings using triple-single-quotes ''':

In [33]:
'this
will not work correctly
as a multi-line string'
  File "C:\Users\Luke\AppData\Local\Temp\ipykernel_32096\2643678918.py", line 1
    'this
         ^
SyntaxError: EOL while scanning string literal
In [34]:
'''this
will work correctly
as a multi-line string'''
Out[34]:
'this\nwill work correctly\nas a multi-line string'

Notice that our multi-line string does not display the way we might hope. If a want to correctly render a multi-line string, we can use the print function.

In [36]:
my_string = '''this
will work correctly
as a multi-line string'''

print(my_string)
this
will work correctly
as a multi-line string

The print function can be used anytime we want to display some information.

In [38]:
a = 1
b = 2

'The value of a is'
a
'The value of b is'
b
Out[38]:
2
In [37]:
a = 1
b = 2

print('The value of a is')
print(a)
print('The value of b is')
print(b)
The value of a is
1
The value of b is
2

So far, we've talked about integers, floats, and strings. There are often times where we might want to convert between these datatypes.

  • The int function will try to convert an input to an integer type
  • The float function will try to convert an input to a float type
  • The str function will try to convert an input to a string type
In [39]:
float(2)
Out[39]:
2.0
In [40]:
float('1.2345')
Out[40]:
1.2345
In [41]:
float('1.234ab')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_32096\2563777790.py in <module>
----> 1 float('1.234ab')

ValueError: could not convert string to float: '1.234ab'
In [43]:
str(2) * 5
Out[43]:
'22222'
In [45]:
str(1.2345) + 'hi'
Out[45]:
'1.2345hi'
In [46]:
1.2345 + 'hi'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_32096\2157588859.py in <module>
----> 1 1.2345 + 'hi'

TypeError: unsupported operand type(s) for +: 'float' and 'str'
In [47]:
int('4321')
Out[47]:
4321
In [48]:
int(5.0)
Out[48]:
5
In [49]:
int(4.9)
Out[49]:
4
In [50]:
int(-2.3)
Out[50]:
-2

The int function will truncate a float and drop any decimal part.

Sometimes we might want to round to the nearest integer.

In [52]:
round(4.9)
Out[52]:
5
In [53]:
round(-2.3)
Out[53]:
-2

String formatting¶

Very often, we have some string template that we want to fill in with calculated data.

In [55]:
a = 123
b = 567

print('This product of')
print(a)
print('and')
print(b)
print('is')
print(a*b)
This product of
123
and
567
is
69741

We can print all of this using a single print statement by separating our inputs by commas:

In [57]:
print('The product of', a, 'and', b, 'is', a*b, '.')
The product of 123 and 567 is 69741 .

There are several ways that we can accomplish this in a sleeker fashion. One way is by using the .format method:

In [60]:
a = 1.23
b = 5.713

my_string_template = 'The product of {} and {} is {}.'

print(my_string_template.format(a, b, a*b))
The product of 1.23 and 5.713 is 7.02699.

Working with lists in Python¶

Another datatype in Python are lists, which contain ordered collections of objects. To define a list, we surround a comma-separated collection with square brackets.

In [64]:
my_list = [1, 4, 6, 'hello', -2.4]
In [65]:
print(my_list)
[1, 4, 6, 'hello', -2.4]

To access elements of a list, we use square brackets again along with an index. Python is a 0-based indexing language, which means the index of each list starts at 0. That is, 0 indicates the first item in the list.

In [66]:
my_list[0]
Out[66]:
1
In [67]:
my_list[1]
Out[67]:
4
In [68]:
my_list[4]
Out[68]:
-2.4
In [69]:
my_list[5]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_32096\303719451.py in <module>
----> 1 my_list[5]

IndexError: list index out of range

We can also elements of a list by counting backward from the end using negative indices.

  • The -1st index gives the last element.
  • The -2nd index gives the second to last element.
In [70]:
my_list[-1]
Out[70]:
-2.4
In [71]:
my_list[-2]
Out[71]:
'hello'
In [72]:
my_list[-3]
Out[72]:
6
In [73]:
my_list[-5]
Out[73]:
1
In [74]:
my_list[-6]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_32096\3123414668.py in <module>
----> 1 my_list[-6]

IndexError: list index out of range

Arithmetic on lists:

In [76]:
[1,2,3] + ['a','b','c','d']
Out[76]:
[1, 2, 3, 'a', 'b', 'c', 'd']
In [77]:
[1,2,3] * 3
Out[77]:
[1, 2, 3, 1, 2, 3, 1, 2, 3]

In many ways, lists and strings work in the same way.

In [78]:
my_string = 'Hello this is MTH 337'

my_string[0]
Out[78]:
'H'
In [79]:
my_string[-1]
Out[79]:
'7'

We can convert between lists and strings using the list and str functions:

In [81]:
print(list(my_string))
['H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'M', 'T', 'H', ' ', '3', '3', '7']
In [82]:
str(['a','e','i','o','u'])
Out[82]:
"['a', 'e', 'i', 'o', 'u']"

It does not look like this is doing quite what we want, since the resulting includes the list delimitors and element separators.

We can fix this by using the .join method on a string:

In [83]:
my_list = ['a','e','i','o','u']

''.join(my_list)
Out[83]:
'aeiou'

We can do much more with the .join method. In particular, we can any string a separator between the elements of the list that we want to concatenate:

In [84]:
' - '.join(my_list)
Out[84]:
'a - e - i - o - u'
In [85]:
'This is a separator'.join(my_list)
Out[85]:
'aThis is a separatoreThis is a separatoriThis is a separatoroThis is a separatoru'
In [88]:
print('The prime factorization of {} is {}'.format(12, 
                                                   '*'.join(['2','2','3'])))
The prime factorization of 12 is 2*2*3

Working with loops in Python¶

We can perform iterative operations using a for loop. For example, we can iterate through the items in a list:

The syntax is:

for (some variable name) in (some iterable object): (do something)

In [89]:
my_list = [1,2,3,'hello','goodbye']

for element in my_list:
    print(2*element)
2
4
6
hellohello
goodbyegoodbye

Key info: The spacing in Python is critical!!!. In particular, the tabbing decides what operations are part of a for loop and what operations are not.

In [91]:
for a in my_list:
    print(a)
    print('This is inside the for loop')
print('This is outside the for loop')
1
This is inside the for loop
2
This is inside the for loop
3
This is inside the for loop
hello
This is inside the for loop
goodbye
This is inside the for loop
This is outside the for loop

We can also use for loops inside other for loops:

In [92]:
for a in [1,2,3]:
    for b in [4,5,6]:
        print("{} + {} = {}".format(a,b,a+b))
1 + 4 = 5
1 + 5 = 6
1 + 6 = 7
2 + 4 = 6
2 + 5 = 7
2 + 6 = 8
3 + 4 = 7
3 + 5 = 8
3 + 6 = 9

In the example above, we're iterating through all combinations of the two lists [1,2,3] and [4,5,6].

We can use other types of iterables to setup for loops. In the examples above, we've been iterating through a pre-defined list. Suppose we want to perform some operation on the first 10,000 positive integers.

In [ ]:
for n in [1,2,3,4,5,6,7,8,..]

The range function is means for iterating through sequences of integers:

In [93]:
help(range)
Help on class range in module builtins:

class range(object)
 |  range(stop) -> range object
 |  range(start, stop[, step]) -> range object
 |  
 |  Return an object that produces a sequence of integers from start (inclusive)
 |  to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
 |  start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
 |  These are exactly the valid indices for a list of 4 elements.
 |  When step is given, it specifies the increment (or decrement).
 |  
 |  Methods defined here:
 |  
 |  __bool__(self, /)
 |      True if self else False
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(self, key, /)
 |      Return self[key].
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __reduce__(...)
 |      Helper for pickle.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(...)
 |      Return a reverse iterator.
 |  
 |  count(...)
 |      rangeobject.count(value) -> integer -- return number of occurrences of value
 |  
 |  index(...)
 |      rangeobject.index(value) -> integer -- return index of value.
 |      Raise ValueError if the value is not present.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  start
 |  
 |  step
 |  
 |  stop

In [94]:
for n in range(5):
    print(n)
0
1
2
3
4
  • range(n) will give a sequence of integers starting at 0 and going up to n-1.
  • range(m,n) will give a sequence of integers starting at m and going up to n-1.
  • range(m,n,k) will give a sequence of integers starting m, stepping by k, and stopping before n.
In [96]:
for n in range(6,15):
    print(n)
6
7
8
9
10
11
12
13
14
In [97]:
for n in range(6,15,4):
    print(n)
6
10
14

Exercise: Write Python code to print the cubes of the first 50 positive integers.

In [98]:
for n in range(1,51):
    print(n**3)
1
8
27
64
125
216
343
512
729
1000
1331
1728
2197
2744
3375
4096
4913
5832
6859
8000
9261
10648
12167
13824
15625
17576
19683
21952
24389
27000
29791
32768
35937
39304
42875
46656
50653
54872
59319
64000
68921
74088
79507
85184
91125
97336
103823
110592
117649
125000

So far, we've explicitly generated lists using square brackets and comma-separated inputs. Suppose we want to generate a list containing the cubes of the first 50 positive integers.

We can start with an empty list [], and then iteratively use the .append method to add elements to that list.

In [99]:
my_list = []

my_list.append(5)
my_list.append(10)

print(my_list)
[5, 10]
In [100]:
cubes = []

for n in range(1,51):
    cubes.append(n**3)

Suppose we want to count how many of the first 50 cubes end in a digit of 1. That means we want iterate through each of our cubes, and then somehow decide whether or not it ends in a 1.

This leads us to Boolean expressions and if statements:

Boolean expressions¶

There are two Boolean values, namely True and False.

We can write statements that evalute to either True or False called Boolean expressions.

In [107]:
5 < 7
Out[107]:
True
In [108]:
10 < 8
Out[108]:
False
In [109]:
6 > 1
Out[109]:
True

We can use <= or >= for lessn than/greater than or equal to:

In [110]:
5 <= 6
Out[110]:
True
In [111]:
5 < 5
Out[111]:
False
In [112]:
5 <= 5
Out[112]:
True

We can use a double equality to check whether two objects are equal to one another:

In [115]:
5 == 5
Out[115]:
True

We can also check whether two lists are equal to one another:

In [116]:
[1,2,3] == [1,2,7]
Out[116]:
False
In [117]:
[1,2,3] == [1,2,3]
Out[117]:
True

We can use an if statement to perform some operations only when a Boolean expression is True.

In [127]:
a = 5
b = 7

if a * b < 100:
    print("The product of {} and {} is small.".format(a,b))
if 100 <= a * b < 1000:
    print("The product of {} and {} is medium.".format(a,b))
    
print('Done')
The product of 5 and 7 is small.
Done

We can also an elif statement (which is short for "else if") to perform operations only in the case that the first if expression was False:

In [129]:
a = 45
b = 7

if a * b < 100:
    print("The product of {} and {} is small.".format(a,b))
elif a * b < 1000:
    print("The product of {} and {} is medium.".format(a,b))
    
print('Done')
The product of 45 and 7 is medium.
Done

We can also use an else statement to perform some operations if none of the if or elif expressions were True.

In [132]:
a = 45
b = 7500

if a * b < 100:
    print("The product of {} and {} is small.".format(a,b))
elif a * b < 1000:
    print("The product of {} and {} is medium.".format(a,b))
elif a * b < 10000:
    print("The product of {} and {} is big.".format(a,b))
else: 
    print("The product of {} and {} is huge".format(a,b))
    
    
print('Done')
The product of 45 and 7500 is huge
Done

Exercise: Count how many cubes of the first 50 positive integers end in a digit of 1.

Wednesday, January 29th¶

In [1]:
cubes = []

for n in range(1,51):
    cubes.append(n**3)
In [3]:
print(cubes)
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832, 6859, 8000, 9261, 10648, 12167, 13824, 15625, 17576, 19683, 21952, 24389, 27000, 29791, 32768, 35937, 39304, 42875, 46656, 50653, 54872, 59319, 64000, 68921, 74088, 79507, 85184, 91125, 97336, 103823, 110592, 117649, 125000]
In [4]:
cubes_that_end_in_1 = []

for n in range(1,51):
    if n**3 % 10 == 1:
        cubes_that_end_in_1.append(n**3)
In [5]:
cubes_that_end_in_1
Out[5]:
[1, 1331, 9261, 29791, 68921]

Some thoughts about efficiency:

  • In the previous calculation, we compute n**3 twice. It would be better to compute it once and store it, then reuse the stored result.
  • We are also reconstructing the first 50 cubes, even though we've already computed all of them.
In [6]:
cubes_that_end_in_1 = []

for n in range(1,51):
    cube = n**3
    if cube % 10 == 1:
        cubes_that_end_in_1.append(cube)
In [9]:
cubes_that_end_in_1 = []

for cube in cubes:
    if cube % 10 == 1:
        cubes_that_end_in_1.append(cube)
In [10]:
cubes_that_end_in_1
Out[10]:
[1, 1331, 9261, 29791, 68921]

Let's explore how the number of cubes that end in 1 grows as we look at larger cubes:

In [36]:
N = 100000
last_digit = 9

cubes = []
cubes_that_end_in_last_digit = []

for n in range(1,N+1):
    cubes.append(n**3)

for cube in cubes:
    if cube % 10 == last_digit:
        cubes_that_end_in_last_digit.append(cube)

We can use the len function to get the length of a list.

In [37]:
len(cubes_that_end_in_last_digit)
Out[37]:
10000

Exercise: Modify the previous code cell to iterate through all digits 0, 1, 2, ..., 9 and print the number cubes that end in each digit.

In [50]:
N = 100000

for last_digit in range(10):
    cubes = []
    cubes_that_end_in_last_digit = []

    for n in range(1,N+1):
        cubes.append(n**3)

    for cube in cubes:
        if cube % 10 == last_digit:
            cubes_that_end_in_last_digit.append(cube)
            
    print('There are',len(cubes_that_end_in_last_digit),'cubes that end in',last_digit)
There are 10000 cubes that end in 0
There are 10000 cubes that end in 1
There are 10000 cubes that end in 2
There are 10000 cubes that end in 3
There are 10000 cubes that end in 4
There are 10000 cubes that end in 5
There are 10000 cubes that end in 6
There are 10000 cubes that end in 7
There are 10000 cubes that end in 8
There are 10000 cubes that end in 9
In [52]:
N = 100000

cubes = []
for n in range(1,N+1):
    cubes.append(n**3)

for last_digit in range(10): 
    cubes_that_end_in_last_digit = []
    
    for cube in cubes:
        if cube % 10 == last_digit:
            cubes_that_end_in_last_digit.append(cube)
            
    print('There are',len(cubes_that_end_in_last_digit),'cubes that end in',last_digit)
There are 10000 cubes that end in 0
There are 10000 cubes that end in 1
There are 10000 cubes that end in 2
There are 10000 cubes that end in 3
There are 10000 cubes that end in 4
There are 10000 cubes that end in 5
There are 10000 cubes that end in 6
There are 10000 cubes that end in 7
There are 10000 cubes that end in 8
There are 10000 cubes that end in 9

Exercise: Modify the previous cell to count the number of cubes whose remainder after dividing by 4 is 0, 1, 2, or 3.

In [54]:
N = 100000

print('For the first',N,'cubes:')
divisor = 4

cubes = []
for n in range(1,N+1):
    cubes.append(n**3)

for last_digit in range(divisor): 
    cubes_that_end_in_last_digit = []
    
    for cube in cubes:
        if cube % divisor == last_digit:
            cubes_that_end_in_last_digit.append(cube)
            
    print('There are',len(cubes_that_end_in_last_digit),'cubes that have remainder',
          last_digit,'after division by',divisor)
For the first 100000 cubes:
There are 50000 cubes that have remainder 0 after division by 4
There are 25000 cubes that have remainder 1 after division by 4
There are 0 cubes that have remainder 2 after division by 4
There are 25000 cubes that have remainder 3 after division by 4

Suppose that we want to find the first 100 cubes that have remainder 1 after division by 4.

Problem: We don't know ahead of time how many numbers we'd have to check before we find 100 such cubes.

For these types of problems, it makes sense to use a while loop. With while loops, we will iteratiavely perform some operations as long as some Boolean expression is True.

In [55]:
n = 0

while n < 100:
    n = n + 10
    print(n)
10
20
30
40
50
60
70
80
90
100
In [56]:
found_cubes = []

n = 1
while len(found_cubes) < 100:
    cube = n**3
    if cube % 4 == 1:
        found_cubes.append(cube)
    n = n + 1
In [58]:
print(found_cubes)
[1, 125, 729, 2197, 4913, 9261, 15625, 24389, 35937, 50653, 68921, 91125, 117649, 148877, 185193, 226981, 274625, 328509, 389017, 456533, 531441, 614125, 704969, 804357, 912673, 1030301, 1157625, 1295029, 1442897, 1601613, 1771561, 1953125, 2146689, 2352637, 2571353, 2803221, 3048625, 3307949, 3581577, 3869893, 4173281, 4492125, 4826809, 5177717, 5545233, 5929741, 6331625, 6751269, 7189057, 7645373, 8120601, 8615125, 9129329, 9663597, 10218313, 10793861, 11390625, 12008989, 12649337, 13312053, 13997521, 14706125, 15438249, 16194277, 16974593, 17779581, 18609625, 19465109, 20346417, 21253933, 22188041, 23149125, 24137569, 25153757, 26198073, 27270901, 28372625, 29503629, 30664297, 31855013, 33076161, 34328125, 35611289, 36926037, 38272753, 39651821, 41063625, 42508549, 43986977, 45499293, 47045881, 48627125, 50243409, 51895117, 53582633, 55306341, 57066625, 58863869, 60698457, 62570773]

Warnings:

  • Unlike with for loops, it is very easy to end up with a while loop that runs forever.
  • Always make sure that your Boolean expression will eventually be False so that the while loop can terminate
  • Check that you are incrementing any necessary variables with each iteration

There are some shortcuts for incrementing variables. In particular:

  • n += 1 is equivalent to n = n + 1
  • n -= 3 is equivalent to n = n - 3
  • n *= 7 is equivalent to n = n * 7
In [61]:
found_cubes = []

n = 1
while len(found_cubes) < 100:
    cube = n**3
    if cube % 4 == 1:
        found_cubes.append(cube)
    n += 1

Project 1¶

This project deals with prime numbers and numbers that share some properties with primes. It will be useful if we can develop some code to decide whether a given integer is prime or not.

To check for primality, we can check all positive integers between 2 and our number (excluding the number) to see if any divide the number.

In [67]:
n = 15

for d in range(2,n):
    if n / d == n // d:
        print('{} is not prime, it is divisible by {}'.format(n,d))
15 is not prime, it is divisible by 3
15 is not prime, it is divisible by 5

Instead of printing out these statements, can we define a Boolean variable that will True is n is prime and False if n is not prime?

In [72]:
n = 127

n_is_prime = True

for d in range(2,n):
    if n % d == 0:
        n_is_prime = False
        
if n_is_prime:
    print('{} is a prime number'.format(n))
else:
    print('{} is not a prime number'.format(n))
127 is a prime number

Another way to deal with this problem is to use a break command. The break will immediately terminate a loop.

In [73]:
n = 128

n_is_prime = True

for d in range(2,n):
    print('Checking if {} divides {}'.format(d,n))
    if n % d == 0:
        n_is_prime = False
        
if n_is_prime:
    print('{} is a prime number'.format(n))
else:
    print('{} is not a prime number'.format(n))
Checking if 2 divides 128
Checking if 3 divides 128
Checking if 4 divides 128
Checking if 5 divides 128
Checking if 6 divides 128
Checking if 7 divides 128
Checking if 8 divides 128
Checking if 9 divides 128
Checking if 10 divides 128
Checking if 11 divides 128
Checking if 12 divides 128
Checking if 13 divides 128
Checking if 14 divides 128
Checking if 15 divides 128
Checking if 16 divides 128
Checking if 17 divides 128
Checking if 18 divides 128
Checking if 19 divides 128
Checking if 20 divides 128
Checking if 21 divides 128
Checking if 22 divides 128
Checking if 23 divides 128
Checking if 24 divides 128
Checking if 25 divides 128
Checking if 26 divides 128
Checking if 27 divides 128
Checking if 28 divides 128
Checking if 29 divides 128
Checking if 30 divides 128
Checking if 31 divides 128
Checking if 32 divides 128
Checking if 33 divides 128
Checking if 34 divides 128
Checking if 35 divides 128
Checking if 36 divides 128
Checking if 37 divides 128
Checking if 38 divides 128
Checking if 39 divides 128
Checking if 40 divides 128
Checking if 41 divides 128
Checking if 42 divides 128
Checking if 43 divides 128
Checking if 44 divides 128
Checking if 45 divides 128
Checking if 46 divides 128
Checking if 47 divides 128
Checking if 48 divides 128
Checking if 49 divides 128
Checking if 50 divides 128
Checking if 51 divides 128
Checking if 52 divides 128
Checking if 53 divides 128
Checking if 54 divides 128
Checking if 55 divides 128
Checking if 56 divides 128
Checking if 57 divides 128
Checking if 58 divides 128
Checking if 59 divides 128
Checking if 60 divides 128
Checking if 61 divides 128
Checking if 62 divides 128
Checking if 63 divides 128
Checking if 64 divides 128
Checking if 65 divides 128
Checking if 66 divides 128
Checking if 67 divides 128
Checking if 68 divides 128
Checking if 69 divides 128
Checking if 70 divides 128
Checking if 71 divides 128
Checking if 72 divides 128
Checking if 73 divides 128
Checking if 74 divides 128
Checking if 75 divides 128
Checking if 76 divides 128
Checking if 77 divides 128
Checking if 78 divides 128
Checking if 79 divides 128
Checking if 80 divides 128
Checking if 81 divides 128
Checking if 82 divides 128
Checking if 83 divides 128
Checking if 84 divides 128
Checking if 85 divides 128
Checking if 86 divides 128
Checking if 87 divides 128
Checking if 88 divides 128
Checking if 89 divides 128
Checking if 90 divides 128
Checking if 91 divides 128
Checking if 92 divides 128
Checking if 93 divides 128
Checking if 94 divides 128
Checking if 95 divides 128
Checking if 96 divides 128
Checking if 97 divides 128
Checking if 98 divides 128
Checking if 99 divides 128
Checking if 100 divides 128
Checking if 101 divides 128
Checking if 102 divides 128
Checking if 103 divides 128
Checking if 104 divides 128
Checking if 105 divides 128
Checking if 106 divides 128
Checking if 107 divides 128
Checking if 108 divides 128
Checking if 109 divides 128
Checking if 110 divides 128
Checking if 111 divides 128
Checking if 112 divides 128
Checking if 113 divides 128
Checking if 114 divides 128
Checking if 115 divides 128
Checking if 116 divides 128
Checking if 117 divides 128
Checking if 118 divides 128
Checking if 119 divides 128
Checking if 120 divides 128
Checking if 121 divides 128
Checking if 122 divides 128
Checking if 123 divides 128
Checking if 124 divides 128
Checking if 125 divides 128
Checking if 126 divides 128
Checking if 127 divides 128
128 is not a prime number

In the above cell, we immediately realize that 128 is not prime when we check d=2, so there's no need to run the rest of the checks. We can use a break to terminate the loop early.

In [74]:
n = 128

n_is_prime = True

for d in range(2,n):
    print('Checking if {} divides {}'.format(d,n))
    if n % d == 0:
        n_is_prime = False
        break
        
if n_is_prime:
    print('{} is a prime number'.format(n))
else:
    print('{} is not a prime number'.format(n))
Checking if 2 divides 128
128 is not a prime number

More about Markdown: LaTeX¶

LaTeX is a tool for writing math expressions. To enter LaTeX mode in a markdown cell, we use dollar signs $.

  • Plain-text:
    • 123456
    • 123^456
    • 123_456
  • LaTeX:
    • $123456$
    • $123^{456}$
    • $123_{456}$

Some common LaTeX commands:

  • Exponents: $x^2 + y^$ renders as $x^2 + y^2$
  • Fractions: \frac{numerator}{denominator}$ renders as $\frac{numerator}{denominator}$
  • Integrals and trig functions: \int_0^x \cos(t) dt$ renders as $\int_0^x \cos(t) dt$

Using a single dollar sign writes LaTeX in in-line mode. We can use two dollar signs ($$) to write in display mode, which gives a centered equation. For example, $$\int_0^x \cos(t) dt$$ renders as:

$$\int_0^x \cos(t) dt$$
  • Subscripts and superscripts: $a_n$, $2^n$ renders as $a_n$, $2^n$
  • Square roots and other roots: $\sqrt{7}$, $\sqrt[10]{x^2-5}$ renders as $\sqrt{7}$, $\sqrt[10]{x^2 - 5}$
  • Greek letters: $\alpha$, $\beta$, $\gamma$, $\sigma$, $\omega$, $\pi$ renders as $\alpha$, $\beta$, $\gamma$, $\sigma$, $\omega$, $\pi$
$$(\frac{1}{2} + 4)$$

We can have LaTeX adjust the size of parantheses using \left( and \right). For example, $$\left(\frac{1}{2} + 4\right)$$ renders as:

$$\left(\frac{1}{2} + 4\right)$$
In [ ]: