Thursday 3 April 2014

Brian's CSC148 SLOG # 12 Conclusions

Hello! The train is slowly coming to a halt at the final stop of CSC148. 

It has been an incredible experience that opened my eyes, captivated me entirely and bestowed every ounce of knowledge possible each week. It is hard to believe that we have learned so much in such a short time frame and there was no topic that I wasn't excited about or interested in. Recursion, comprehensions, binary trees, binary search trees, abstract data types, object-oriented programming, algorithm time complexity, regular expressions, linked lists, program design; it's ALL incredible!

I am actually not in the Faculty of Arts and Science. I am from the Architecture Faculty and it's very unfortunate that students from the architecture faculty cannot take computer science for their double major. Only the minor is possible so hopefully I will meet the cut-off mark for it but if not, I have serious intentions of pursuing computer science further and may request an internal transfer to enroll into the specialist or major program. If I don't get enrolled, I still intend to take higher-up CSC courses as an elective and learn all that I can. Even then, architecture is actually a very flexible field to go into and as far as video game design goes, level design would benefit from an architect designers' perspectives. This is an example of how different fields of studies intersect and work together to create new designs.

I really appreciate those who read my courSe LOG, so thank you! 
I hope you were able to enjoy it or learn something from my more technical entries.

It has been a blast, best wishes to everyone.
Adios.



Thursday 27 March 2014

Brian's CSC148 SLOG # 11 Sorting Algorithms and Efficiency

Hello!

This week's SLOG topic is all about sorting algorithms and efficiency.

As mentioned briefly in last week's SLOG, there are a couple sorting algorithms that we have been taught so far.

Here is the list again for reference:

Insertion Sort
Selection Sort
Quick Sort
Merge Sort
Built-In Python Sort
and the most interesting to me: Customized sorting algorithms

Each of these use different methods to sort order-able objects in a mutable collection such as lists and each have their own advantages in the different ways they sort a collection. Their respective run-times can be deduced by observing the code and identifying the worst case for a big-O run-time complexity. Bubblesort, although commonly seen as an inefficient sorting algorithm with an O(n^2) time complexity, has an advantage over other where we can immediately tell that part of the list is sorted if no exchanges are made after each pass. Merge Sort uses a divide and conquer method which recursively sorts separate parts of a list and has a very efficient time complexity of O(nlog(n)). An interesting thing to note is that these run times in Python are not optimized as opposed to other programming languages like C. Built-in Python Sort (or Timsort) uses language closer to machine code which means it is highly optimized. Timsort usually beats most sorting algorithms in terms of efficiency but some customized sorting algorithms can actually sort faster than Timsort depending on various factors such as number of elements in the list.

Efficiency and optimization of code is such an interesting topic to me because my goal is to become a video game developer. Program efficiency is incredibly important for game developers because people generally want their video game to run smoothly without putting too much strain on our CPU's (Central Processing Unit) or RAM (Random Access Memory). If we did not have optimized games, there would be no way to play them unless everyone was using top tier computers built specifically for gaming. Luckily, because optimization does exist, games are playable on lower end computers and everyone is happy! Asides from program efficiency, there is also graphics optimization which is not part of CSC148 but I hope I will have the opportunity to learn more about that as well.

Wednesday 19 March 2014

Brian's CSC148 SLOG # 10

Hello! Welcome to my 10th SLOG post!

Has everyone been having a good week?

The winter term is slowly coming to an end and the assignments are ramping up in difficulty as we approach the end of the term. This week's lecture was crammed with new course concepts and also, Assignment 2 Part 2 is due tomorrow. Both the lecture and assignment 2 has taught me very interesting concepts and helped me think in a new way for solving new problems.

This week's SLOG focus will be on:
  • Assignment 2 Part 2
  • Sorting Algorithms
  • and my current situation in 148

Assignment 2 Part 2

Although I cant reveal too much as it isn't due yet, I will discuss my experience with Part 2. The assignment overall was not too difficult with one exception: regex_match. I began assignment 2 on Thursday night and finished 3 of the functions: is_regex, all_regex_permutations and build_regex_tree by Saturday night. These functions were not too hard because we didn't have to worry too much about how each of StarTree, DotTree, BarTree and Leaf would affect each other.

The way I handled is_regex, was to find valid regexes within the string and recursively call is_regex while simplifying the string until it eventually returned True. If my function found a single false regex during it's recursive calls, it would immediately return False.

For all_regex_permutations, we were basically given the answer as we had permission to use a code provided on the 148 website that would return all the permutations of a string! 

and for build_regex_tree, the idea is similar to is_regex in using recursion to simplify each call further and further until we reach the final answer and return a RegexTree object.

So what made regex_match so difficult?

We had to worry about how each subclass of RegexTree would interact with each other and this was incredibly difficult for me because I couldn't figure out how to get StarTree objects to properly interact with other the other sub-classes. After two days, I had finally finished some code that returned the correct bool for most cases. However, some complex cases were returning the incorrect bool and there was even infinite recursion in another case. Unable to solve my function for all test cases, I went to office hours and recieved some hints from Danny in approaching StarTree cases and Dustin helped me figure out the why my function was infinitely recursing. At last, I put the two helpful hints together and finished my function on the third day! Well, okay.. maybe three and a half days!

This is one of those moments where once you find out what the answer is, the next time you come across it, it will only take a minute to solve. I believe this is somewhat like the beginnings of thinking like a computer scientist! Spending lots of time at office hours, coding, tracing your program with pencil and paper until you get closer and closer to the answer. I don't feel good about having needed 3.5 days to solve a single function whereas a few of my classmates managed to solve it in a day. Nonetheless, I am happy it is finished and confident as it seems to work for very complex cases!

Sorting Algorithms

Sorting algorithms are incredibly interesting as they can greatly impact the performance of a program depending on the number of items we are sorting. Generally, we have touched on a couple sorting algorithms which are: 

Insertion Sort
Selection Sort
Quick Sort
Merge Sort
Built-In Python Sort
and Customized sorting algorithms

By randomizing the items in a list, we were able to see how long it took each different sorting algorithm to sort for lists with a very small amount of items (10 items) and lists with a VERY VERY VERY large amount of items! (160,000 items!). This comparison is priceless because we are able to figure out how much longer it takes a sorting algorithm to run depending on the size of the list. I believe the most interesting thing in understanding this is that we can deduce which sorting algorithms are better for our programs depending on the number of items that our program will be dealing with.

CSC148 so far..

Lately I've been feeling more confident in using recursion as it showed in my ability to solve the functions in Assignment 2 Part 2. I also used some comprehensions in the assignment which I mentioned I was struggling with a few weeks ago. So I am definitely feeling more confident as I think I reached a higher level of understanding in CSC148. However, the remaining weeks will definitely be more of a challenge as we will need to analyze algorithm running times which I have very little experience with. Hopefully this won't be a tough concept for me to grasp but I will definitely be vocal with my friends in 148 and discuss algorithm running times to get a better handle on it. Being vocal and discussing problems with friends and professors have helped me learn so much more than I would have had I not said anything!

With that said, I think I have covered everything I wanted to this week's post.

Thanks for checking out my 10th SLOG installment and check back soon as next week's topic will be in-depth about sorting algorithms and efficiency!

See you soon! 

Wednesday 12 March 2014

Brian's CSC148 SLOG # 9

Hello and welcome to my 9th SLOG post!

I hope you all are doing well, this week has been havoc for me! I caught the flu, there was a snowstorm out this morning so imagine having a headache, sore throat, cough and runny nose while traversing through a flurry of snow blowing into your face. Nevertheless, I am still alive after gruesomely long commutes to and from school :P.

This week's topic will be about Assignment 2 Part 1 and a little rare surprise I had in my 8th CSC148 LAB.

Assignment 2 Part 1

Part 1 of Assignment 2 was a really unique opportunity for us students to design a RegexTree and represent it the way we wanted to. At first I thought there had to be only 1 absolute way to approach the task but we were actually given nearly boundless freedom to create the program. The only restriction that I am aware of is that we had to use inheritance and have a class hierarchy for our classes. Thus we couldn't create 1 single class to handle all the nodes.

So what knowledge was gained from completing this assignment?

Here is what I think:
  • Class hierarchy
  • Inheritance:
  • Reduction of duplicate code
  • An introduction to regular expressions used in various programming languages and utilities.

All of the above points work in tandem. Class hierarchy meant using inheritance and when calling functions from the classes, namespace would determine which function takes precedence over duplicate function names. For example: If I have a __repr__ method in my super class that calls on the __repr__ method of my Node classes, the __repr__ method of the Node classes will take precedence over the super class's __repr__ method even if we call it using the a RegexTree object.

Secondly, we can also easily reduce code by using inheritance and class heirarchy. I have actually completed two different designs of Assignment 2 Part 1 and have reviewed them with Professors Danny and Dustin. In one of my designs, I created an individual __repr__ method for every class which repeated code but on the other hand, showed how class hierarchy works. In the second design, I created a __repr__ class in the superclass RegexTree which would properly present a representation of all the different types of Regexes and since I have only 1 __repr__ method, there is less repetition of code in the program.

Another way to reduce code is in the __eq__ method. By writing a single __eq__ method in the superclass, we have reduced redundant code by rewriting one for every class. This method in particular could have been approached two ways. The first method is to simply compare the __repr__() methods of two different RegexTrees which meant that they had to have the exact same string to resolve to True.
The second method, which I think we could learn more from uses recursion. By simply checking if the symbol and children of a regex expression was equivalent, we could easily recurse over the children until both regular expressions had no children left and finally, return our desired bool.

Overall, Assignment 2 Part 1 was definitely a fun assignment to tackle given the freedom to design!

Lab 8

In this week's lab I had a rare opportunity to partner up with another friend of mine. He is a really crafty guy when it comes to programming and has knowledge of Java and uses comprehensions with ease.

His SLOG is here for those who are interested:
www.yanqilee.blogspot.ca

What made this an interesting experience is because we managed to solve the very last lab question in an interesting way. Apparently we were hinted to use the Stack class to solve BST's count_less method without using recursion. We struggled in trying to solve it using Stack but couldn't find an answer.
HOWEVER! We found a backdoor trick to solving it without using the Stack class at all!

The answer? BST's __str__ method. 

Our task was to count all the integers in a binary search tree lower than a given number for count_less method so we utilized __str__ instead. BST's __str__ method returned a representation of all the integers in a string that looked like a binary search tree. We simply split the string and removed all the newline characters. Afterwards, we looped over the integers and if it was lower than the number argument for count_less, we simply added one to count and returned count after the loop iteration.

Even the TA had a good laugh at how we accomplished the task!

That's all for this week so please check back soon for another SLOG installment!

All the best,
Brian

Wednesday 5 March 2014

Brian's CSC148 SLOG # 8

Hello! How is everyone doing?
Welcome to my eight SLOG post.

This week has been quite alright! Term papers have been given back and I achieved 77.5% (B+) which is wonderful. I was expecting a grade in the B range but on the next test and the final exam I will be working harder to achieve even higher!

What's new in this SLOG post? 

This time I will be discussing:
  • A little bit of assignment 2 
  • Challenging concepts I am facing in CSC148
Without further ado, let's begin!

Assignment 2

Assignment 2 is all about creating Regexes and parsing Regexes and matching them with strings. As of now, we are only responsible for part 1: creating Regexes and part 2: parsing Regexes while matching them with strings will come later.

So what are Regexes? Regex is an abbreviation of regular expression which is used in different programming languages and other utilities to match entire classes of strings. For this assignment we will only be dealing with  regexes over the ternary alphabet {0, 1, 2} which is a non-empty string that consists of the symbols '0', '1', '2', 'e', '|', '.', '*', ')' and '('.

I managed to get insight for A2 by first creating a master class and subclasses that will later handle the creation of a regex such as ('2'|'3'). What information about regexes can we use to start coding our classes? By looking closely, we can tell that it has similar properties to a how trees are constructed. The nodes '0', '1', '2' and 'e' are the leaves and have no children and by knowing this, we can consider the bar '|' as the parent node. Comparing to a tree example such as: Tree(1, Tree(2), Tree(3)), we know 1 is the parent node, or root and 2 and 3 are the leaves that have no children. A regex can be represented similarly like so: Regex('|', [Regex(1), Regex(2)]).

With the insight that regexes can be expressed similarly like trees can in programming, I have managed to finish part 1 of assignment 2 which I will discuss in more detail next week. The deadline has been extended this week so I don't think I am able to share my full solutions just yet but look forward to my next post as I will explain be explaining it with great detail!

Challenges

University has been challenging for computer science courses. Very often I have had to take lots of time to consider how to approach new concepts and sometimes I feel that I am in the midst of somewhat understanding the new concepts but not yet fully. Comprehensions and recursion are the challenges for me right now. Comprehensions are very difficult for me because they are written quite differently from how I'm used to coding. Recursion is somewhat difficult for me. For easy problems I have no problem using recursion to solve them but for more complex ones, I struggle for long periods of time. The tough problems for me are usually a mix of comprehension and recursion in a single function. Asides from this, I can handle recursive functions at a good level. The only question is, whether or not I can understand comprehensions + recursion together before the end of the semester. I certainly hope so!

Thanks for reading my eight SLOG post! 
Have a wonderful week.

Wednesday 26 February 2014

Brian's CSC148 SLOG # 7

Hey, how's it going!?

So this week, I had completed 148's FIRST TEST and I'm feeling quite good.

Sadly, after the test, I realized I made two small mistakes on two questions but I don't think I can provide precise details here but I can say that I have already looked into them and have learned from my errors :]. It's one of those computer science moments where you have a trick question and you know the answer is either Zero, None or Error.
My reasoning led me to the wrong answer (Doh!) but it was a good attempt and at least I was right about it being one of the three!

So what'll this week's SLOG be about? 

Hm... since I have been talking a lot about course material lately and I recently talked in-depth about OOP and recursion, I figured this week would be a good chance to talk about non-material course related things. Let's get started!

Piazza

At the start of 148, I didn't think much of Piazza and thought I could learn the course materials without relying on it. I was totally mistaken and my perspective of Piazza flipped right around at the beginning of exercise # 1.
It's an incredible experience when classmates, professors and TA's take time to discuss course concepts with you and try to hint you in the right direction if you're ever stuck on a submission. By discussing course concepts, or hinting someone who is stuck, everyone who is involved refines their knowledge of the computer science topic and even when we're mistaken, I noticed that the instructors will usually step in and correct our assumptions.
Without Piazza, I honestly think that most students in the program would have a lesser level of knowledge than they do now. That being said, I also hope that Piazza is included in future CSC courses.

Office Hours and Help Center

These two places are the place to be. Sometimes it's difficult to discuss a complicated code on Piazza so if further help is required, I would personally recommend one of the two. During assignment 1, I could not debug my code for TOAHModel.py. In fact, everything looked perfect but the default doctest would keep failing 3 out of 20 tests. After trying on my own for hours, I decided that I needed to discuss the code with someone who was well-versed in programming. I went to the Help Center and the friendly TA went over my code with me. We worked together and tracked down the error, which turned out to be a big issue but very easy to fix!
The issue? I wasn't creating Cheese objects when filling the first stool, just using regular integers for the cheeses which was why the doctest was failing. So the fix was quite simple: fill the first stool with Cheese objects instead!

I have been to office hours a few times this semester and I can't be thankful enough to Prof. Danny and Prof .Dustin for clarifying course material for me and showing me useful tricks to handle difficult problems such as recursive problems.
On another note, they have been replying to all of my e-mails within a day (Even on weekends!) and I am also thankful for that.

Office hours, Piazza, and the Help Center are truly indispensable resources for computer science learning.

Thoughts on Group Work

Let me first state that I strongly believe the current labs have been indubitably helpful to my own understanding of computer science. Nearly every school week there is a group lab where my partner (Ben) and I work through the challenging problems together. We discuss, brainstorm ideas and try them out until our answers are correct. We do try to get the code right the first time, but if it's inevitable we have multiple attempts until we arrive at the correct answer.
Personally, I enjoy the group work with Ben. We help point out each others mistakes and help each other understand things that we're unsure of. In fact, the labs have been so influential for us that we even discuss course concepts outside of school via Skype, phone and e-mail!
For those who are interested, please check out my partner's SLOG: http://mycsc148experience.blogspot.ca/

However, this is where I think a line must be drawn for group work. Although we are allowed to have groups for assignments, I also strongly believe that these should be done alone. By working alone, more students will develop their problem solving abilities but by working together, one group member may understand the solution whereas the others do not. If these students don't understand the concepts then they are at risk of doing poorly on the tests and perhaps in future courses as well.
I realize that in the real world we will be working with other peers but I think it would be meaningless if us students do not have a solid foundation on computer science concepts in the first place.

This is why I believe the perfect balance is to have groups for labs but not for assignments!


Thanks for reading my SLOG.
I will be finishing up assignment 2 this week so I'll make sure to discuss it in next week's entry.

Have a great week and see you again soon!



Monday 17 February 2014

Assigned SLOG Topic # 2 - RECURSION! SLOG # 6

Wow! It's already the seventh week of the winter term.. how is everyone?

I have midterms in the coming week so I am hard at work. Writing tests are personally not my forte so I tend to double up the effort on assignments and even more so for test preparation.

Before I start this week's SLOG off, I have written a mid-week post on Object Oriented Programming (OOP) to discuss it in more detail since I had mistakenly not done so for the first assigned topic. Please give that a read if you have the time to and share your thoughts.

Seven weeks into the course, I'm finally comfortable with recursion to talk about it in depth, so let's get started!

How do we use recursion?

When solving a problem by repetitively using the same trick to get closer and closer to the final answer, we are using recursion.

Here is a real-life example of where recursion can be seen:

Imagine you've discovered a small diamond at the beach while going for a walk. Being the super clever person you are, you wonder if there are more undiscovered diamonds around this area. Using a metal detector and a shovel, you dig around the area, trying to uncover more. If there are no diamonds, you look around with the metal detector again and try the next spot. THIS is the example of recursion! You are repetitively doing the same task (shoveling and using the metal detector) in an attempt to get closer to the answer (the precious diamonds). Congratulations if this real-life recursion actually works out for you!

Programming example of recursion:

Perhaps you have a program that runs at different speeds depending on variable X and you'd like your program to run more efficiently. By using different cases of value X and running your program, you could deduce which case will be the most efficient. To do this, simply observe the amount of time it took each case to complete and trace the X value that completed your program in the shortest time. Although this sounds simple on paper, you are recursively calling your program for these different cases until you find the most optimal solution.

Here is a related example of another 148 student testing his functions for different run times:
http://berkeycolortran.wordpress.com/2014/02/15/week-6/
We should do so similarly as we want our program to run optimally by recursively testing various cases of X.

Define a stopping point!

When it comes to coding recursion, it's important to let our program know - "OK, that's enough!". It is super important to find a point where the program will finally stop recursively calling itself, otherwise it will continue on until our computers are out of memory. Some simple stopping points come from using for-loops over an iterable object such as lists, dictionaries and tuples or using conditions such that when the recursive function reaches the condition, it will stop rather than trying to call itself until our computers are out of memory.

A little technical example

As always, it's important to share some code as well. Simply talking about recursion without code isn't very helpful, especially to people who are new to it.

Let's define a function that will count the number of alphabetical objects in a nested list and let's define our list to be:
nested_list = [ 'race', 1, 'car', 2, 3, '4', ['hello!'], [1, ['ace', ['diamonds', 5]]]]

This should return a count of 4. Note that 'hello!' is not an alphabetical object since it has an exclamation mark (!) within the string. 'race', 'car', 'ace', 'diamonds' are all alphabetical.

def count_alpha(x: list) -> int:
    """
    Precondition: Items in x must be nested lists or string, integer and float objects.
 
    Returns the number of alphabetical objects inside a list.
    """
    count = [ ]
    def helper(x: list):
        for items in x:
            if isinstance(items, list):
                helper(items)
            else:
                if str(items).isalpha():
                    count.append(1)
    helper(x)
    return len(count)

Here is what this example does:
  • First we defined an empty list count as part of the outer function. 
  • We have defined an inner function 'helper(x)' so that when we recall our function, count does not get reset to an empty list.
  • For the body of helper(x), we utilize a for-loop so the program will stop after it iterates over all the items in list x; as stated above, it's important to define a stopping point for recursive functions.
  • The for-loop then iterates over x and if the items inside x happen to be a list, helper(items) is called which will loop through the items within the nested list.
  • Finally, if the for-loop happens to iterate through an object that is not a list, it will check if the object is alphabetical with the built-in isalpha().
    If this returns True, 1 is appended to count and the function will continue this pattern until the for-loop is completed.
  • len(count) is then returned, giving us our final answer.
Let's check our answer in Python Shell!

>>> nested_list = [ 'race', 1, 'car', 2, 3, '4', ['hello!'], [1, ['ace', ['diamonds', 5]]]]
>>> count_alpha(nested_list)
4

Voila!

Learning Recursion

Lastly but most importantly, I wanted to mention that learning recursion can be made MANY times easier by tracing your program on pencil and paper! I have done this for my labs, my assignments and for study material which helped me more than just reading about recursion or playing with recursive functions in Python. Tracing will provide tons of insight and is priceless for anyone interested in recursive functions. Using a visualizer helps as well but pencil and paper has personally been my saving grace.


Thanks for reading my lengthy but hopefully interesting SLOG post on recursion.

I have midterms to study for but do not fret, for I will be back with another post soon! :)
Wish me luck and see you readers later.