Thursday, 31 October 2013

Slog Entry Week 7

When Prof. Heap was coding in lecture this week, he used the tuple packing notation that we learned in last week's lab. I thought that was pretty slick. Both because of the advantages of tuple packing (it reduces confusion by assigning multiple variables in the same step) and because it was excellent integration of tutorial and lecture. The labs are a really great learning opportunity, and a lot of the coding that I do in a week is done in lab. Once I got a high-functioning partner relationship going, I really started enjoying the labs. I know Week 6 especially we finished all of the code in no time, with very few instances of the dreaded "getting stuck". It occurred to me that not only are labs enjoyable (and marked independently), but they're being utilized effectively to increase the amount that we can learn from lecture and tutorial combined. They make it possible to fit more content in the course without simply swamping the student with material, as I am experiencing in some other courses at the moment. *cough* Every math course *cough*.

My only other experience with labs was with first year physics last year, and I really strongly disliked them. Firstly, my TA barely spoke English at all, so his explanations and 'help' were completely useless. Secondly, the groups were too large to be high-functioning. I mean, you've got 4 people doing a lab report that ultimately has to be written by one person. Inevitably, someone ends up useless, and just through lack of assertiveness (not lack of intelligence), I end up that person. 

Beyond that there's increased risk of having a personality clash. In a group of 2 people, there's one possible personality conflict, and if that happens, you just change groups. In physics, the groups were immutable. In a 4 person group, applying some basic combinatorial methods, we obtain that there are

(4 * 3) / 2! = 6 

personal relationships, sextupling the risk of clash. And this happened, with at least 2 of the connections.

Also, in a 2 person group, generally both people have laptops anyway. But if there are no laptops, it doesn't take that long for one person to just grab the keyboard and try out the idea that they think will work but whose validity they can't convince their partner of.

The pair-programming thing is genius too. As much as my egotistical side hates to admit it, I do code better and faster when there's someone looking over my shoulder. There's a bunch of little stupid mistakes that I still make, that I think I'll always make (not putting the thing that you want to print in brackets; did anyone else learn to code on Python 2?). More importantly, if there's some fundamental flaw in the theory backing my approach to a problem, either simply by explaining my method aloud I'll realize it, or my partner will be able to (eventually) convince me of it, and we save valuable time. From the ansatz (German for approach, educated guess in Mathematics), I'll often be able to glean valuable insight into what a more effective solution might be, and if not, my partner has cooked one up in between bouts of fuming as I write my misguided code. In the end, we get a better finished product with less precious time wasted.

The exercise was not too challenging. Or so I thought. I wrote out my code, commenting as I went and running doctests like a good little CSC148 student. By the end, it passed all of the tests, and I was confident in its codified virility. The next day, when I checked the premark, I viewed the strangest result since my code for Exercise 1 failed the 'easy' tests and passed the 'hard' ones. 

My e5a code failed three tests and passed five, e5b passed three and failed 5. In both cases, one of the passes was the PEP8 style checker, so it's actually much worse than it sounds. I was baffled. I had no idead what could have gone wrong, until I actually went and took a look at my code. It turns out I had unwittingly (or witlessly, if you prefer) written my function so that it only worked on symmetrical trees. Duh. That's, like, the most obvious of the potential problems. I clearly should have checked it. In the future, I will be more careful to write an exhaustive set of tests.

This is an interesting psychological phenomenon that I've noticed when I'm programming. Often, I'll rush through the process of actually writing the code so that I can start testing less mediately (not quite immediately, but better than completely mediate). Almost without exception, my code with fail (often raising an exception of its own in the process(or)). Looking back at my script, I'll often notice some problem completely unrelated to the specific failure that got me looking at the code, and fix that, only to encounter the same failure. Eventually I fix the right problem, but the moral is that even just by thinking the code failed, you gain a piercing critical lens through which to give your code a second look, producing results leagues ahead of the initial ansatz. Perhaps when coding by hand on a test or exam, I should mentally simulate a run of the program that ends in a failure, so that I can trick my self into a more detail orientated state with which to take that all too important second look. 

Perhaps I should just code slower and more thoughtfully, and not run the test before I've taken the second look.

I went back, tried a few things, and settled on code that broke the problem down into 4 cases that correspond to the truth table for existence of a left node and existence of a right node. I had one case for two children trees, one for trees with only a left node, one for trees with only a right node, and one for trees with no children and a lot of disposable income (leaves). Although this made the code work in every test case, I was vaguely dissatisfied. I felt there was a more efficient solution somewhere. It wasn't until Week 8's lab that I would find out what this was...

No comments:

Post a Comment