Monday, 14 October 2013

Slog Entry Week 5

A Couple of Definitions:

Object Oriented Programming:

This is the way Python works. In Python, to accomplish programming goals, you define classes. Within that class, objects have attributes. The class also has methods that work with its objects. This is very intuitive, because it allows you to think about any object in Python as an analogue to a physical object with physical properties. An object is just a particular instance of a broader class of things. As soon as you initialize an object of a class, you know what attributes it has and what you can do with it.

Recursion:

Recursion is the process of a function calling itself. Recursive functions have a base case and a recursive step. The base case is the simplest possible instance of the task. The goal of the recursive step is to break the task down into base cases. Often this is a matter of calling the function itself with different parameters, in an attempt to solve some subtask within the task as a base case. Recursion is useful for solving problems where the solution is simply breaking it down into simpler problems and solving them, like solving for the nth Fibonacci number, for example.

This was also the week that the assignment was due. Phew! What a load of work! For the week leading up to the deadline, I felt like I didn't have any courses except CSC148. It was a full time job.
My partner and I got the first couple of steps going the previous week, and decided that over the weekend I would work on the algorithm to solve the three stools (and then the four stools) problem, while my partner worked on implementing DomainStools so that it provided a flawless visual representation. I left the bulk of the task to Sunday, and I spent a lot of time staring at the computer screen. After spending a lot of time coming up with the code for the three stools solution, Prof. Heap posted some high functioning sample code that accomplished the same task. I was a little bit frustrated. However, I do think that working out the code myself helped improve my understanding of what was happening during the solution, and of recursion in general.

When I later began working on the four stools solver, my hands were tied by the lack of 4 arguments designed for the stools in the tour_of_four_stools function. I mucked around a for a couple of hours in this framework, wrote sole complicated code that involved a lot of control flow to designate which stool was the beginning, which were the two interim stools and which was the destination. However, I couldn't quite get it to work, so I wrote a separate helper function that took all four stools as arguments, and it was really easy to write. It worked almost the first time through.

The only problem was that many of the cases were sub-optimal, as according to figures from Piazza and other academic studies of the four stools problem that I found on Google. My algorithm was more efficient than the three stools 2**n - 1, but sub-optimal. I initially hard-coded a different formula for the optimal split up to n == 14, but eventually came to my senses and wrote a split(n) function that returned the optimal i for any n. This required writing an M(n, i) function that recursively calculated the least number of moves to solve the four stools problem with n cheeses and a split of i, using the recursive formula given on the assignment.

One of the things I found interesting was that my M(n, i) function called the split function, to determine the optimal split to use in each call of itself, while the split(n) function called the M(n, i) function to compare the minimal number of moves for each split. They built an interdependent recursive network that still boggles my mind a little bit. Intuitively, it almost seems like they are both defined circularly, so neither should work, but they both do, through the magic/science of recursive calls.

Overall, I really enjoyed this assignment, because of the mathematical aspect. A lot of the time while working on it, I really had a strong sense that I was using computer science to do mathematics, which was a really good feeling. I'm a mathematics specialist, and one of my reasons for studying computer science is to learn enough coding so that I'll be able to write programs to help me conduct mathematical research, and I really felt like I was making progress towards that goal. In addition, the approach to problem solving is very similar in Mathematics and Computer Science. Often, I'll get stuck, and have no idea how to proceed. It's good to review the readings, and your objectives, and all of your previous code, but a lot of the time it comes down to just trying something. Even if it's a bad idea, you can always Ctrl + z it away, and you might get a better idea from the attempt, or be able to refine it into a working solution. These problems that we use computers to solve often quickly escalate beyond the grasp of human understanding. That's where the science comes in. You do an 'experiment' with some new code, see what happens and learn from it. If it doesn't work, figure out why and refine the approach or try a new one. If it does, and you don't quite understand why, there's a lot to be gained from figuring out why it works. Then you can solve an analogous problem confidently.

All in all, I learned a lot about programming, and about problem solving, from this assignment. This may be a bit overoptimistic, but I'm starting to finally feel like I can write and understand code!

1 comment:

  1. Great post Alaric! Here are a few things to think about: What types of problem would you code using OOP paradigm? What are the disadvantages of OOP? When do you need to use recursion to solve a problem?

    ReplyDelete