Friday, 28 March 2014

Week 11: Sorting and Efficiency

Here we are again, writing my blog for the final time. This week, we discuss the topics of sorting and efficiency. What, I talked about sorting last week? Yeah well, uh, so what. Let's talk about it more. In programming, sorting is the method of taking a list, and rearranging elements to a certain order, typically smallest to largest or vice versa. Why do we need sorting in programming you say? Well if you have to ask that, then you don't deserve an answer.

Sorting algorithms come in many different shapes and sizes, and they all have different runtimes. Runtimes are the length an algorithm takes to complete, mostly depending on the size of the list, in which case we will call 'n'. For example, the run time of a simple sort such as bubble sort takes n^2 steps. Let's analyse why.

Let's say we want to sort the list [8,2,9,6,7,3,1] from smallest to largest. Bubble sort works by looking at the first element in the list, and comparing it to the next adjacent one. If it's smaller than the one next to it, it will swap them. This goes down the list, and we do this step the same amount of times as there are elements in the list. So we sift through the list n times because we check each element, and we do that, n times, one for each element in the list, so we have n * n steps, or n^2 steps. Let's sort this list to see why.

 [8,2,9,6,7,3,1]

 [8,2,9,6,7,3,1] We look at the 8 and 2, 2 is smaller than 8, so we swap them.
  ^ ^
 [2,8,9,6,7,3,1] Then we look at 8 and 9, 8 is smaller than 9 so don't do anything.
     ^ ^
 [2,8,9,6,7,3,1] Then we look at 9 and 6, where we swap them because 6 is smaller than 8.
        ^ ^
 [2,8,6,9,7,3,1] Then we look at 9 and 7, where 9 is greater than 7 so we swap them.
           ^ ^
 [2,8,6,7,9,3,1] Then we look at 9 and 3, where 9 is greater than 3 so we swap them.
              ^ ^
 [2,8,6,7,3,9,1] Then finally we look at 9 and 1, where 9 is greater than 1 so we swap them.
                 ^ ^
Notice we did this step 7, times because there are 7 elements in the list. But we then start again and perform those 7 checks 7 times, so 7*7 steps, 49 steps. This is how we can analyse the runtime of a sorting algorithm.

There are many different types of sorts, with different runtime lengths. There`s runtime lengths of nlog(n), like quick or heapsort, which for our purposes is the most efficient sorting algorithm when using a standard list or scenario.

My personal experience with sorting and efficiency goes back to grade 11, and my introduction to computer science. We spent an entire unit simply discussing sorting algorithms and how to properly know which to use in certain situations as well as how to program them. A video we watched back then that we got to watch was Sorting out Sorting, a movie from 1981 which was created at University of Toronto. The video basically just goes over different types of sorts and how they execute but what I found the most interesting was during the credits, we get to see a time-lapse of a whole variety of sorts race against eachother in sorting these scattered dots. As we can see from the screenshot below, shellsort, quicksort and tree selection sort are already completed with heapsort close behind. These are because for an array of data with a large size, runtimes with logarithmic lengths will work wonders compared to ones with quadratic runtimes.
https://www.youtube.com/watch?v=SJwEwA5gOkM
 This pretty much sums up my experience with sorting algorithms and efficiency, I hope you had a fun time reading my last post or my entire blog in total. I sure had fun writing it! I wish you, the reader, farewell and good luck with your future endeavors. Happy programming!

Saturday, 22 March 2014

Week 10: Sorting

This week in class we discuss sorting. Some students may have been confused as to why we're discussing something we talked about in csc148, but I knew where this was going. Sorting is a little more complicated than most people think it to be. It's not just about getting the job done, it's about efficiency.

We discussed how different types of sorts have different runtimes. We discussed the runtimes of sorts like bubble, insertion, selection, quick and merge. We noted that in many scenarios quick and merge sort have on average better runtimes than the others with nLogn, where n represents the length of the list. This is because sorts like merge and quick recursively iterate through sorting, allowing for cutting down the amount of work it has to complete. I actually have a lot of experience with these types of sorting algorithms from high school where we had a huge section of our curriculum based around it. We even got to watch a very interesting (and boring) video called sorting out sorting, where it just races a whole bunch of different sorting algorithms. Can you guess who won? You guessed right, quicksort, with tree insertion and heap sort following closely behind. But I'll get more into that next week, when I'm forced to write about sorting.

Saturday, 15 March 2014

Week 9: Binary Search Trees



Here we are, back again, me writing, you reading about programming. What's this week you ask, binary search trees of course. "What's a binary search tree?" you may ask, well let me tell you. I binary search tree is like an ordinary binary tree, only the nodes are ordered or sorted based on certain properties. The left subtree will contain nodes with the root less than the trees root. The right subtree will contain nodes with the root greater than the trees root. Both the left and right subtrees are binary search trees as well as there are no duplicate nodes.
File:Binary search tree.svg

That's what defines a binary search tree by definition, let's look at an example of one. The image to the left is an example of a binary search tree. Notice the entire trees root is an 8. This means everything to the left of it must be less than 8. If we look at the left subtree, the root it 3, which is less than 8. Then we can look at that 3 as being the root of a binary search tree. Everything to the left of the 3 is less than it, being only the 1. Everything to the right of the 3 must be greater than it. 6 is the next root under 3. Everything to left of 6 must be less, which it is and everything to the right must be greater, which it is.

My experience with Binary search trees has contained some trouble itself. While I understand the concept of them and am comfortable with manipulating them. I find I have trouble with writing one recursively. But once again, this goes back to my trouble with recursion itself. I'm slowly improving, but I still find trouble dealing with subjects like this.

Saturday, 8 March 2014

Week 8: Linked List


Linked List, the ole list that refers to a list that refers to list that refers to... you get my point. A linked list is a data structure with two parts. A node, that contains a value of some sort, and a pointer, or a reference to another linked list. Along with trees, they are also considered abstract data types.

In class we talked about the two ways to think about a linked list. One as thinking a linked list contains a value, then the remaining list, or the rest of it. The other way is as nodes with reference to nodes, the more traditional way. We went over created a linked list using multiple classes like a node class and a wrapper class. It took me an incredible amount of time to understand what a wrapper class was. Even now, I'm not certain, but I believe it is used to hold the entire linked list and hold information that would be useful for methods like inserting or deleting nodes.

We also discussed how we can essentially create trees that are linked lists. Then we went to talk about binary search trees. Binary search trees are binary trees that for each root, it will have maximum two subtrees. All values to the left of the root will be less than the root and all values to the right of the root will be larger than the root. This assists in locating specific nodes as it assists traversing the tree when we can eliminate half the tree on each iteration through it.

To sum things up, this week we discussed linked lists and binary search trees, which both are abstract data types that revolve around nodes and references to other abstract data types of similar objects. My personal experience with this topic is that I still have a fair amount of trouble visualizing how to recursively go through and perform whatever method I want. But this goes back to my trouble with recursion itself which over the next view weeks I will try and improve.

Thursday, 27 February 2014

Week 7: Recursion

What is recursion you might ask. Well, to think about it visually, if you place a mirror in front of another mirror, both facing eachother, you would get an infinite amount of reflections. The reflection of one mirror, essentially reflects itself, reflecting itself, reflecting itself and so on... If we take that logic, and use it with computer science and math, we can do all sorts of wonderful things.

Let's say we wanted to write a function to evaluate the factorial of a given number:

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

When you give an n value, it will start to check if it is 0, otherwise known as the base case, where it returns a static value and not a recursive one. If  is not 0, it will multiply it by the factorial function of n - 1. What this does is repeatedly do the function to retrieve values until we hit the base case. In this case, we ca determine 4! = 4 * 3! = 4 * 3 * 2! = 4 * 3* 2 * 1! = 4 * 3 * 2 * 1 * 1 = 24. You have to make sure you have the base case or else the function will recurs infinitely.

So now that I've briefly talked about what recursion is and an example of how it works I guess I can get to my experience with it. I first encountered recursion in my grade 11 computer science class where we were learning C++. Every student had to pick a topic in computer science and give a brief talk on what it is and how to do it. Of course most people pick a topic that suits there likes and is easy for them. We had some simple topics like reading/writing to a file, creating a GUI, I did some game design and graphics. And then easily the smartest kid in the class goes up, and talks about recursion and trees. Every student is both amazed and completely confused at the topic. Barely anyone can code it from nothing or even comprehend it. Heck, I could barely even understand what he was saying. He goes to talk about the practicality of it and its uses, I'm just sitting there thinking that any example he was doing could be done in another way. He asks us to code a function to find the greatest common divisor of two numbers. I figure yeah I could easily do this, and I wrote something similar to this, only with C++ syntax instead:

def GCD(x, y):
    num = []
    for n in range(1,max(x,y)+1):
        if x % n == 0 and y % n == 0:
            num.append(n)
    return max(num)

I figure "yeah, I did that fast, and it looks efficient, there's no way you can do this better." Then he shows this:

def GCD_recurs(x, y):
    if (0 == x % y):
        return y
    return GCD_recurs(y, x%y) 



HOW'D HE DO THAT! That was genius. I would have never thought of that. Since that moment. Recursion has always puzzled me on how to know what to do. I still have trouble, in class and in the assignments on knowing what to recurs. 

So that is my experience with recursion, a both lovely and infuriating topic, I both hope to use it forever and never use it again. 






Saturday, 15 February 2014

Week 6: Trees

Well, here we are again, me writing and you reading about computer science. Well, now that assignment one is complete, we can now begin on trees. Trees are a completely new data structure to me, at least to program so it can provide some trouble. It's extremely difficult to visualize how trees are structured as there's no way to essentially print what a tree looks like inn python without writing your own custom str method.

The reason I presume for us to learn about trees is the way we navigate through them. And of course, as you guessed it, it's recursively. The reason we do this is because all trees start with a root node. Each root node and possibly children. But some of the children might have it's own children. We can essentially view each original child and all their children as it's own tree, therefore looking a layer deeper into the tree. When a node has no children, that node is referred to as a leaf and still can be viewed as a tree itself, just with no children.

In my continual learning of computer science and programming, I've realized if I ever need help with concepts, while I can google or ask a TA, I've only just realized that there's hundreds of other SLOGS out there for me to read. I've become fond of http://slogslogslogslog.blogspot.ca/ It seems that student, "Penguins Go Noot" and I share some of the same problems, but he/she has found solutions that have helped me out.

The hardest part of this week has just been trying to picture and visualize a tree structure, but I'm sure with a lot of practice and constant work, I'll get the hang of it.

Monday, 10 February 2014

Week 5: Tower of Hanoi

So you're given 3 stools and 3 blocks that rest on the first stool, from largest to smallest. You are given the task to move all 3 blocks from the first to last stool one block at a time and can only be placed on an empty stool or one with a larger block on it. After playing this game for a couple of rounds, you notice a pattern. You notice there are precisely efficient ways to solve this in the least amount of steps. After some guess and check, one would notice that it takes (2^n)-1 steps. This can be done for any amount of blocks, where n represents that number.

That is the classic Tower of Hanoi problem given to us this week. Only, it's been tweaked ever so slightly. They added a stool. You might think that only makes it simpler. Well, it times in terms of completing the game, but not for figuring out the most efficient way to do it.

The classic 3 stool Tower of Hanoi problem is world famous for being solvable with recursive functions, and as we discussed last week, recursion is the property of referencing itself. In the 4 stool Tower of Hanoi problem, it also used recursion, but something a little extra. There really is no defined perfect solution for the most efficient way to find the number of steps. No matter what you Google or Bing (jk, don't bing it), everyone has a different opinion. The only agreed part of solving the 4 stool Tower of Hanoi is that there's 3 steps. You move N-K blocks to an intermediate stool, then K stools to the destination, then those N-K stools you previously moved to the destination, While N is the number of blocks, and K is a dynamic amount that changes. No one really agrees on how to determine K. If you want what I think, after computation, I determined K = ciel((2n)^(1/2))-1. While this is not necessarily the best solution, it does result in the most efficient amount of steps. With 4 blocks = 9 moves, 5 blocks = 13 moves, 6 blocks = 17 moves, etc.

Well that covers the Tower of Hanoi problem we discussed this week. We also discussed scopes and namespaces. We covered topics like global, local and non-local variables and saving names in a namespace as well as proper naming of variables and functions. That should do for this week, stay tuned for next week when we talk about trees, so I'll just make like one and leaf (haha, get it?).

Sunday, 2 February 2014

Week 4: Turtle Recursion

This week in class, we delve into Turtles. Not per-say the animal known as a turtles, but the python library known as turtle. With turtle we talk about recursion, the act of calling itself, possibly creating an infinite amount of calls. We use turtles to represent lines or vectors on a window and use recursion to create new paths and split offs from eachother on each call of the turtle to move. On each call, the turtles moves a shorter distance and a new angle. Eventually, with all the paths of the turtles, we start to create a shape that represents a Sierpinski triangle, a fractal shape. With this turtle introduction, we finally reach the topic of recursion.

Ahh yes, recursion. A call within a call within a call, etc. What a tricky topic. Even though I learned recursion a few years ago, I still have trouble with it to this very day. Making sure you don't have infinite recursion is something you always need to do. A way to do this is with a base case. A base case is a circumstance in which the function doesn't call itself. Such as having it call itself if a variable known as X is above a certain value, and on each repeated call, we decrease the value of X by one, so eventually X reaches below that threshold and it stops calling itself.

Because in class we speak of recursion, I can only imagine the upcoming topic of trees. While i can lie and say I'm excited for trees, I won't. I'll simply say in a sarcastic tone," Oh boy.... trees."

Tuesday, 21 January 2014

Week 3: Object Oriented Programming

Welcome to CSC148, where the data is abstract and the types don't matter. With the introduction of classes, we're also introduced to object oriented programming, and working with abstract data types. Classes are typically new to the students of Danny Heap, but not for me. So normally, I would complain about learning stuff I have already, but I'm incredibly glad we are. I learned C++, another object oriented programming language a couple years and dipped softly into the field of classes and abstract data types. You'd think that'd make me better with classes, but precisely the opposite. I learned how to code classes, the completely incorrect way and didn't understand their purpose or function at all and why we use them. Now that we're learning it, I'm trying to erase all previous knowledge of classes, and relearn it the proper way. To be fair, learning about classes did give me a slight advantage as I understood basic concepts. Learning C# this summer also lent itself to teaching me about classes.

While learning classes, we also discuss the many of subtopics used to manipulate them, such as superclasses. Superclasses are classes that 'inherit' from base classes so that we can save precious, precious data. Inheriting is done by importing other classes we've written and editing or adding to them so that it does the more specific functions we require of it.

Furthermore, we discussed other types of classes, like exception classes, and how to raise them. I had various trouble with this, understanding the different types of exceptions, but during the second lab, I got to venture into this and raise my own exception. This also lead to learning about trying and excepting, which I used with my lab partner to try converting a string to an integer, but raising a value error if the string was unable to. Trying and excepting seem like they will become incredibly useful further on in the semester, as well as my programming career.

In the end, I've had little trouble with the problems and topics we discussed so far. Without trying to suck up, I would argue the reason for this is how in depth Danny Heap went into the topics, and going over exactly how something works, and answering any type of question the students have to offer. Next week, we're discussing recursion, another topic I ventured into previously and had trouble with. But alas, I'm quite excited for it, and will look forward to the day we get to program some recursive functions, especially trees. Until then, I suppose I'll get back to procrastinating.