Algorithms
and
Data
Structures

Spring 2022
course
site
-->

Feb 24

Welcome back.

0'th order of business : SEPC reps.

I had several people ask for more context and background for the python coding style that I showed in the last class.

So let's take a bit of time to do an overview and discussion of python and its programming styles.

python overview

I'll walk through examples of a number of concepts - slow me down and ask for clarification as needed.

Looking things up : docs at python.or ... or just googling e.g. "python class tutorial"

Visualizing python's execution model : pythontutor.com

Packages : import math

Data types : int, float, string, list ... "nouns"

Functions : built-in and user defined ... "verbs"

   some function specifics in python :
     * docstrings
     * optional and default arguments
     * return values vs side effects (i.e. modifying globals) ... pros & cons

Using dir() and dir(thing) to "look inside" python constructs.

>>> import math
>>> dir(math)
>>> type(math.pi)
>>> type(math.cos)

>>> name = "Jim Mahoney"
>>> dir(name)
>>> name.lower()   # object.method() ... a function "inside" a thing

>>> values = [1, 2, 3]
>>> values.sort()      # modify in place - no return value (hmmm)
>>> sorted(values)     # or instead return a new array

So all these things "strings, lists, packages" are "objects" in python.

And we can define our own, new "objects", which in python are called "classes". Here are my lecture notes on how that works.

For our purposes, classes are a convenient way to bundle up several functions that work on a common set of data values - for example the IndexedArray API that I defined in the last class.

class IndexedArray:
    """ An indexed array with a fixed size """

    def __init__(self, size):
        # special : invoked to initialize an array
        self.size = size          # the number of elements in this array
        self.values = [0]*size

    def get(self, i):
        """ return the i'th value in this array """
        return self.values[i]

    def put(self, i, value):
        """ assign the i'th entry in the array to this value """
        self.values[i] = value

    def __str__(self):
        # special : redefines str(array)
        return f"<IndexedArray size={self.size} values={self.values}>"

array = IndexedArray(4)
array.put(0, 20)
array.put(1, 10)
print("The 0'th element of the array is ", array.get(0))
print("The array is ", array)

But the "object oriented" style is not needed ... and in fact C doesn't have any of that. We could implement essentially the same IndexedArray API without objects ... like this :

def new_indexed_array(n):
    """ Return a new Indexed Array """
    return [0] * n

def put(array, index, value):
    """ Assign a value to the array at index """
    array[index] = value

def get(array, index)
    return array[index]

array = new_indexed_array(4)
put(array, 0, 20)
put(array, 1, 10)
print("The 0'th element of the array is ", get(array, 0))
print("The array is ", array)

another way

Can you think of a different implementation of an "indexed array" in python? How about using a python dictionary? Do you think that's better or worse? Faster? Slower? More or less memory?

We did this in class, using a python dictionary; I've attached an indexedArray2.py file with the code.

picking up from last class

Here are my more fully fleshed out versions of the pythagorean stuff.

Do you see a pattern in the times? Hmmm.

sorting

Let's talk about some sorting algorithms that you folks came up with ... in pseudo-code, at least.

Here's an example .

O() notation

Our next topic is analyzing the run-time of algorithms ... by looking at the trend as the size of the problem, n, gets large.

Here are a few sources to read about "big O notation" :

This "O()" is actually a terrible notation, for several reasons, but it's what everyone uses, so you should understand it and be able to sling the lingo.

Problem 1 : people generally mean "big Theta" (the running time is approximately equal") when they say "big O" (the running time is bounded by).

Problem 2 : these are sets ; we should be using membership notations, not equality.

numerical experiments

To visualize the running time of algorithms, we will usually do and plot numerical experiments, trying different values of N (the size of the problem) on randomly generated data, and see if the trend we get is what we expect.

See my plotting examples for some examples of plots in jupyter python notebooks. You're welcome to use other tools if that's what you're used to.

logs

We'll be using logarithms this semester, so if that math is unfamiliar to you, please review it. (I can give a pep talk if that's helpful).

Basically \( a = b^c \) is equivalent to \( \log_b(c) = a \).

what's next

The homework for next week is posted.

On Monday, we'll continue discussing any of this stuff that we didn't get to today, and working some examples.

https://cs.bennington.college /courses /spring2022 /algorithms /notes /feb24
last modified Thu February 24 2022 3:55 pm

attachments [paper clip]

  last modified size
TXT indexedArray2.py Thu Feb 24 2022 03:55 pm 632B