Tuesday, April 1, 2014

Week 11 - Sorting and Efficiency

Sorting and efficiency are two central topics in computer science, yet manage to be overlooked by most computer scientists of the 21st century. Sorting simply means to organize objects in a particular order, generally ascending or descending, and efficiency is a measure of performance versus time, in computer science this is with regards to programs. This we we combined the two together in order to see how something we take to be so trivial (sorting) is actually measured and pitting different sorting algorithms against one another in terms of efficieny.

Before we can analyze anything, we need to be aware of these "sorting algorithms". It turns out wikipedia lists a plethora of sorting algorithms, including bubble, insertion, selection, quick, merge, and tim sort. Consequently the prior list is sorted in order from least to most efficient. But what does it mean to be efficient? As a computer scientist we measure efficiency in terms of constant time and and the number of iterations we use within our algorithm. This "time complexity" lives within a notation denoted by "Big-O" and can represent an algorithms worst, average, and best expected run time with respect to constant time. The most common run times we use to analyze the run times of programs are denoted by the following; O(n), O(lg n), O(n lg n), O(n^2), O(2^n), O(n!), and O(1). It should be mentioned that the lower number within the brackets represent the most efficient run time.

Lets analyze selection sort, the algorithm can be found below:

def select(L):
    """Produce copy of L in sorted order

    >>> select([3, 1, 2])
    [1, 2, 3]
    """
    L1 = L[:]
    for i in range(len(L1)):
        m = min(L1[i:])
        j = L1.index(m,i)
        L1[i], L1[j] = L1[j], L1[i]
    return L1


We have a list <L1> which is being iterated through by the for loop, assuming our list length is n, iterating through n items will take O(n) time. Everything else within the loop is O(1) time approximately because we generalize variable assignments and such to this order, rendering the program O(n). This makes sense, but the line where we copy <L> to <L1> could also take O(n) steps if we were to imagine it with a for loop. This is to say the program has O(n) + O(n) time, but this is would simply be 2*O(n) which is a constant multiplied by our scaling time complexity. The key to time complexity is that we only care about scaling variables, therefore we drop the 2 and end up with O(n) time.

With this being said, tim sort is the most interesting sorting algorithm brought up this week seeing that it is a compilation of many sorts and utilizes certain aspects for certain scenarios, yielding the most optimal results. Although quick sort may be slower than selection sort when it comes to really small lists, tim sort would use the better of the two in the best case.

Tuesday, March 25, 2014

Week 10 - Sorts and BST

This week we covered various kinds of sorts. Some of them include selection, quick, merge, and tim sort. Of the sorts mentioned, we go from slowest sorting time to fastest respectively. Reasons for this were analyzed in class, mentioning how selection sort iterates n time to see what needs to be swapped, then another n times to swap. This results in O(n^2) time, as opposed to merge sort which cuts the list in half each time, then joines them back together, the join in itself is about n times, but the splitting is log(n), yielding a combined time of n log(n) time. Now we just observe these sorts based on their strict algorithms that do the same job yet in a different way, so why not combine all these sorts to form a gigantic one that does the job best in certain scenarios? Well that is the definition of tim sort, made specifically for Python.

Finishing up BST's we covered deleting from a BST and forming linked lists out of them. This was fairly challenging because creating the Linked List nodes required you to remember that once an object is created on the stack in python, it stays there until the code is done with it, so if you create a linked list node in the call, it is that object that will be within the prior. This was a key component to solving the lab and caused great pain for my partner and I to solve. Other than that BST's were fairly straight forward and I can see great applications of this being to store a list of contacts or numbers where indexing is crucial.

Sunday, March 16, 2014

Week 9 - Projects and Stress

This week we have our exercise due, and the second part of our second assignment due next week. I have finished the exercise and just checked my automarking results. Thankfully they show perfect, but for our second part of assignment two I am quite puzzled. The assignments in computer science are pretty vague and I always feel as if they do not teach you everything you need to know for them. Sure, the tools we use are all taught, but the concepts are quite advanced, mainly the cheese algorithm in the first assignment. It's a pleasure getting to deal with such high level algorithms, but it's also scary when your mark is on the line. I've actually gotten a partner for the first time this year to help me out with this assignment, so this collaboration is certainly new and welcomed.

Other than projects in computer science, I have a job application I'm currently working on. The program I need to build for this application is far more advanced than the topics we cover in first year computer science, so hopefully I have enough energy to see me through this test.

Tuesday, March 11, 2014

Week 8 - Linked Lists

This week we covered linked lists and talked about how they are data structures which are made of nodes that point from one to another. The nodes are represented by objects and contain pointers allowing for a way to explore the list iterating from one object to the next via pointers. Linked lists can come in two forms. One being a singley linked list allowing for appending and deleting from the end, and doubley linked lists that can be appended to and deleted from both the beginning and end of the list. This data structure differs from that of a normal list or array in the sense that it is not indexed, and the only way to explore the list is through iteration. This being the case, exploring and finding an element in a linked list will take O(n) time. 

In addition to linked lists we talked about binary trees and demonstrated methods that were used in the __repr__ method to make them more humanly readable. It is through this demonstration that we saw the power of the traversal techniques learned in the prior weeks. 

Thursday, February 27, 2014

Week 7 - Recursion

Up until now we've been taught recursion at a very basic level with nested lists as our starting block, and have expanded to more complex things such as trees. Through this transition the simple concepts of recursion have stayed stagnant.

Recursion is the process of repeating items in a self-similar way, with respect to functions it is the act of calling a function definition within itself. This in itself sounds like an infinite series of process considering that a definition is made up of itself (which is forbidden in English grammar). The solution to this problem is what's called a base case. A base case is defined as something we know for sure, and is unchanging. For example, if we were calculating the n'th factorial, we always know that if n is 0 then the 0th factorial is 1. Why? Well based on the definition of a factorial (n*(n-1)*...*1). Since 0 is a special case, it is independent of the definition of a factorial, hence we always know the answer to it. Using this base case, we have a result that will exit the infinite calls. This being the case, we just have to make sure that we reduce the larger problem to many smaller problems involving the base case, thus yielding the appropriate recursive result.

It is this ideology of recursion that enhances an individuals thought process to be expanded across multiple areas of thinking, thus altering that thought process to be adaptable to multiple scenarios. Just as we were introduced to recursion through lists, we are now adapting this ideology to trees and linked lists. This is a transition to abstract data structures, which involves some high order thinking yet retains that constant definition of recursion.

Saturday, February 15, 2014

Week 6 - Scavenging Tree's

This week we reviewed tree's and various ways to search them involving; pre-order, post-order, in-order. These are traversal techniques which end up exploring every node within the tree, but a particular order. We've learned some new terminology with respect to trees, the main one's being the root, leaves, children and parents. The root is the starting node of a tree, a tree which is defined as a node and all it's children. Leaves are nodes which have no children. Nodes which have children are referred to as parents. All of these terms help us better describe trees, and further in the course will help develop algorithms with respect to trees.

In addition to learning about general trees, we were introduced to the binary tree. This is a specialized tree in which each node only refers to two children (otherwise none) are organized in such a way that the right child is greater than the parent, and consequently, the left child is less than the parent. This organization strategy allows for in-order traversals of this tree to result in exploring the tree from smallest values to largest.

As important as trees are claimed to be, I personally don't find a great use for them right now. We've seen them recursively implemented through lists in Python, but they appear to be more an organizational strategy better suited for Object Oriented Programming architecture.

Sunday, February 9, 2014

Week 5 - More Recursion and Assignments!

This week in lecture and tutorial we covered more approaches to recursion. Recursion is a pretty complicated topic to understand, once understood you have to train your mind to think in that "recursive" term. This is something that's plagued me for 2 years (yes I started tackling recursion a mere 2 years ago). I've seen many people fail completely at recursion and those who get it in an instant. I've always leaned towards the failing end, although I would understand the reasoning behind it, I've never been able to code my ideas recursively. This week however I think I've achieved something great in my life because I've realized the secret to recursion and have demonstrated that in tutorial.

When taught recursion in lecture, Prof.Heap made it clear to think of the most simplest case and work up from there, using the values obtained previously to propel your examples further and further until you have a generalized formula. Now although this idea is relatively simplistic to understand, being able to combine this ideology with that of pythonic paradigms is yet another challenge. What I mean by this is list comprehensions. Thinking in terms of list comprehensions seemed like an impossible task when I was first introduced to it, all I could think of was "how did he think of this?". It wasn't until tutorial when I was faced with a similar problem that I was able to think like Prof.Heap and end up coding an example that he would have created himself. This was a moment in which I realized the secret to recursive programming, but much is still yet to be learned.

We have our first assignment due this week, an assignment I figured would be easy like CSC108's last semester. Boy was I Wrong. This assignment is the hardest assignment I've been given, why? Well, this assignment is based around solving a conjecture, something that no one in the world has created a definitive solution to. We are asked to provide a "good" approximation? This is a seemingly impossible task but a task we are forced to take on. I've tried many techniques of thinking of the problem and only have one issue which is how to switch between free stools, this is the trick to the problem but I have no idea how to do it with recursion. Previously I said that I now understood recursion, but I am still not a master at it since I cannot solve this problem.

In summary, this week has opened my mind to many new possibilities of programming, and has also humbled me with the task of attacking a conjecture.


Friday, January 31, 2014

Week 4 - Recursion and Unit Testing

       This week we tackled a different programming technique called recursion, and a structured method of code testing called Unittest.

       Recursion is not new to me, I've done it plenty of times in high school through means of contests and clubs. Although I've done it before, I can easily say I am no expert in the area seeing that I was rather confused with regards to tracing Prof Heaps one line code. It's not that his code is too compact, it's more so our methods of tracing recursion slightly differ. He detests the stack based model in which I grew up on, thus forcing me to change my ways. Although I'd say I have fully converted to his ways, I still find it a challenge to think of recursion starting from very simple cases and growing more and more complicated with each step. This building block method is excellent, I can see how it trains you to more easily grasp the concept, It's just difficult having been used to a prior method. None the less the Wednesday lecture with the Turtle animations were really cool and fully engage you with understanding recursion through a pictorial representation.

       Unittest was something we were introduced to in CSC108 but I never bothered to actually learn it because I did not have intentions of furthering Python. This being the case, creating my own personalized test cases in lab this week were rather difficult because I had no idea of what to do. My TA refused to help me figure out how to make my test cases work, but I never refuse knowledge when it comes to programming so I ended up figuring it out on my own and getting everything to work perfectly in the end with both my understanding and my code. I can now see the beauty in Unittest although the applications we build in CSC148 are rather trivial so it feels like I'm going over board at the moment.

      All in all this week has been great because I was able to somewhat learn new things which is a nice change from CSC108.

Tuesday, January 21, 2014

Week 3 - Object Oriented Programming

                   This week in CSC148 we tackled a new programming paradigm called OOP, short for Object-Oriented programming. This programming model introduces many new topics such as inheritance, various levels of abstraction, and improved ways of handling errors. Take for instance running out of space in a stack, with procedural programming we would return -1 to notify the user of popping from an empty stack, but with OOP comes a technique called exception handling in which we can halt a program and relay more specific information to the user about the error they committed. This is one of the many important aspects of OOP which will prove its usefulness in large scale code.

                   Re-usability is a key component to the three central characteristics of a programmer, specifically being laziness. In order to fully captivate this core characteristic, we must first learn of shortening code which we've already seen through the use of functions and procedures. With OOP the whole point is to create a blueprint for which we can build more specific objects based off of it. If we want to create a volvo volkswagon and a dodge caravan, both these objects are called vehicles from which we derive their specific attributes belonging to each. Instead of having to redefine the engine, steering wheel and other attributes among all vehicles, we can inherit these general characteristics, and tweak them however we please! Who would want an engine in a volkswagon that's also in a dodge caravan? That would make for awfully terrible gas mileage as well as horsepower loss.

                   This is just the tip of the iceberg in Object-Oriented programming design, I'm sure more will be understood later on in the course, for which I am looking forward too.