Category Archives: Education

Review: CS201: Elementary Data Structures — Saylor Foundation

Saylor’s CS201: Elementary Data Structures follows their three-course introduction to programming sequence. The course is a standard data structures course, covering arrays, stacks, queues, graphs, and hash tables, and their implementation. As in previous courses, some segments were taught comparatively. For instance, implementations of a stack were shown in C, C++, and Java. This is a nice touch, although those languages are a bit too similar to lead to interesting insights.

I don’t think the C-family of languages is particularly suited to teaching data structures and algorithms to beginners, though, since they introduce a fair amount of “accidental difficulty” that is due to the syntactic complexity of those languages and not the subject. As a consequence, two of the eight units dealt with pointers and references in C++, and dynamic memory allocation, respectively.

Apart from data structures, an intro to the analysis of algorithms (big O) was provided, which was subsequently applied to a number of searching and sorting algorithms. A prominent omission among the sorting algorithms was quicksort, though.

Overall, this course is a great complement to the many introductory programming/CS intro courses that are available online. I just checked the EdX, Udactiy, and Coursera catalogues, and there is still no dedicated course on data structures available. This means that for the time being, Saylor’s offering fills a void.

My only criticism relates to the final exam. Saylor continually improves their courses, and is very receptive to feedback, so there is a good chance that the few mistakes I spotted will be corrected soon. I don’t want to discuss specific exam questions, but to give you one example: one question asks you to identify a sorting algorithm that is unsuitable for large arrays. However, they all exhibit quadratic runtime and thus were all unfit. Yet, the answer choice “none” was seen as wrong. The expected answer was presumably that bubble sort was unsuitable for that task, but I don’t want to select an answer choice that conflicts with reality just because the examiner (or grading script) might expect it. Some other questions were on C++ syntax, which I found questionable in the context of data structures. This wasn’t a big issue, but it surprised me nonetheless. Thus, I think that it would be helpful if Saylor either offered a sample exam, or expanded their list of learning outcomes to reflect the content of the exam as well.

[Addendum: I emailed Tanner Huggins at Saylor Foundations who quickly replied to me, saying that he addressed the issues I’ve brought up. He also wrote that Saylor courses eventually go through a peer-review process, where feedback on courses and exams is solicited from qualified faculty members, and that Elementary Data Structures hasn’t gone through this process yet.]

Review: An Introduction to Interactive Programming in Python — Coursera

I just finished An Introduction to Interactive Programming in Python on Coursera, which is taught by Rice University professors Joe Warren, John Greiner, Stephen Wong, and Scott Rixner. This course has the rather unique approach of teaching programming by building games of increasing complexity, instead of teaching programming language syntax with a plethora of dull exercises. Overall, it was an excellent experience, and thoroughly enjoyable. Most of all, it was great fun.

I originally signed up because I was interested in the structure of the course. I liked the whimsical style of the instructors, and before I knew it, I was sinking a couple hours a week into programming games. Games were only used as a vehicle to teach programming, though. I think this is a much more attractive approach than coding a dreary CRUD application. Presumably, more students would stick with computer science or mere programming if they were presented with more interesting application domains. I certainly have never heard of teenagers who learned programming on their own because they wanted to write a CRUD app in Java. Games, on the other hand…

Pedagogically, the class was excellent, since it focusses on practical examples first. For a beginner, this is surely much more helpful than the misguided attempt of introducing rigorous definitions for their own sake. The content was similar to a typical introductory programming class that is taught using Python, such as MITx’s 6.00 or Udacity’s CS101. Yes, object orientation is  covered, and so are common data structures like lists, sets, dictionaries and tuples. Even more advanced concepts like list comprehension were taught.

As teaching platform an online IDE named Code Skulptor was used, which implements a subset of Python 2.6 in JavaScript. Two bundled multimedia libraries make it much easier to write games. Code Skulptor provides syntax highlighting and code folding, i.e. the ability to hide the definition of a function. This environment worked very well for most of the course. The last few assignments led to code bases in excess of 200 lines, which made programming in the browser a bit awkward, though.

Now, let’s talk about the games you’ll write in the course: the first project is an implementation of rock, paper, scissors, lizard, Spock, which uses console output. The week 2 project is not much more complicated: it’s the guessing game. You know, guess a number between 1 and 1000. This project also served as a vehicle to introduce binary search, and basics of GUI interactivity. Week 3 was only a minor step up, covering modulo arithmetic by programming a stop watch, and implementing a “game” on top of that: try to stop the counter at the start of a second. Since the counter keeps track of 100 ms segments, this is rather difficult.

The fun started in week 4, though, which focussed on Pong, using simple vector graphics. Pong may not be very exciting nowadays, but it’s quite satisfying to play a round or two (against yourself) once you’ve implemented all game mechanics. It felt satisfying just seeing the ball physics in action. Quite a few students seemed to have struggled in week 5 with the implementation of Memory, as it involved more complex game state and manipulations. In Pong everything is visible all the time, while in Memory cards aren’t always exposed. As you can see from those examples, the assignments got progressively more complex, and they required increasing sophistication.

The most time-consuming project was probably Blackjack, the week 6 project, which implemented a simplified rule set of that game. The addition was to work with tile maps. The last two weeks tied everything together with an implementation of Asteroids: game physics, sound, tile maps, collisions, game state, it’s all in there. Despite being the most elaborate project, it was very straight-forward. As such, it was a rewarding conclusion to this course. Here’s a screenshot:

RiceRocks

RiceRocks: An implementation of Asteroids

The support structure of this course was excellent, too. You could even email a help desk at Rice University if needed, and each week, a support thread was started in the forum that discussed the most common stumbling blocks. Examples of programming concepts were plentiful, and supplementary exercises helped reinforce concepts, if you needed it. I didn’t have to resort to any of those resources, but knowing that they were there was reassuring. I also appreciated that materials were posted early, on Saturdays, which gave you a head start, and made it much easier for me to find the time for this course.

There were only a few blemishes. One quibble I had was that in one of the later projects some “Java in Python” was taught as students were asked to write a “getter” method. However, in Python you can just access the attributes directly. Peer review of the weekly assignments worked well. However, the grading rubrics focussed merely on the exhibited functionality of the programs, not on the actual code. I found this questionable since it may reinforce bad habits. A grading rubric for “style” may be a reasonable addition to future iterations of this course.

To summarize, An Introduction to Interactive Programming in Python is a great way for a beginner to get started with programming. This course is also interesting for more experienced programmers, since you’ll be implementing simple games. I certainly found this enjoyable. Granted, it probably won’t provide much of a challenge if you’ve made it through an introductory programming course already, but it should be quite entertaining.

Review: CS107: C++ Programming — Saylor Foundation

There are a few MOOCs I’m interested in taking that are taught using C++. I’m not overly familiar with this language, which was motivation enough for me to go through the third course in Saylor’s Computer Science curriculum, CS107: C++ Programming. That course promises a thorough introduction to C++ programming. It is not a course for beginners, though. You are expected to have a basic familiarity with programming, including object-orientation.

CS107 has been my third course on Saylor, and so far this is the course that best illustrates the viability of their approach to teaching. Yes, all the material they use is freely available elsewhere. However, by curating content and offering a syllabus, Saylor provides a helpful structure for self-learners. This makes it easy to follow along, and greatly increases the value of the original sources. For instance, Google’s C++ class is too dense and fast-paced for anyone who isn’t an experienced programmer already, and Keith Schwartz’s Stanford hand-outs might not be overly useful without the accompanying lectures, which are missing. An older version of Stanford’s CS106B is available online, though. Further, the tutorial on cplusplus.com provides very little hand-holding, with very few examples and no exercises at all. Saylor solves all those problems by combining those and other resources.

I would recommend that you get a book to complement the material. While I do think that CS107 is a perfectly adequate university-level course, it can be quite convenient to be able to quickly look-up topics in just one place, instead of having to go through various links and sites. There are a few free sources available. I’ve used Allen B. Downey’s How To Think Like a Computer Scientist: C++ Version. It has served me well as a concise reference, even though it won’t help you much in the second half of the course, which explores more advanced topics such as templates, preprocessor directives or manual memory management. Speaking of supplementary books, Eric Roberts offers a draft of Data Abstractions in C++ free of charge. It is quite verbose, but the book looked good to me. You might appreciate the many exercises it offers.

The final exam was quite satisfying, apart from some minor issues. The majority of questions were of a practical nature, which I find laudable. The most common question type was based on tracing the execution of a program and choosing the correct output from a number of alternatives. Other questions covered language details which, for the most part, were perfectly reasonable. I found just two of the 50 questions hard to justify. One asked to evaluate a statement of the form “x = (y = 10, y + 1)”. This is syntactically legal, and does evaluate to an integer, provided both x and y have previously been declared. However, I couldn’t think of a case where you would want to write code like that. Some other question presented you with a program that reads in a file consisting of a short sequence of characters as binary, and print the content character by character as hexadecimal values. I would have been fine with a short program or a question that tests whether you can manually convert from one number system to another, but seeing instructions that say, “(Hint: you should compile the code to figure it out.)” caught me off guard, and not just because I was doing this exam on a computer on which I didn’t have any software development tools installed.

What I disliked, though, was that all code fragments were presented as unformatted code. It is quite startling how difficult it can be to read code that wasn’t properly indented. Saylor should fix this issue, and it should be a relatively easy fix too. Despite the few minor flaws, though, I think that CS107 is a solid course. It won’t turn you into a master C++ programmer, but afterwards you should know enough C++ to go through more advanced CS courses that are taught in this language.

[EDIT: On 17 June I received an email from Tanner Huggins, Content Development Associate at Saylor Foundation. He let me know that they’ve fixed the formatting issues with the exam I had pointed out.]

Review: CS102: Introduction to Computer Science II — Saylor Foundation

After covering basic concepts of programming and computer science in CS101, Saylor’s CS102: Introduction to Computer Science II moves on to discuss some more advanced material, using the C family of languages, i.e. C, C++ and Java.

I did appreciate the many historic sources I was exposed to, such as Dennis Ritchie’s article “The Development of the C Language”. I do think that in computer science textbooks there is often very little appreciation of the rich history of this field. This is a pity, since learning about the evolution of programming languages can only broaden your horizon.

The other aspect I enjoyed was the strong comparative focus. Some assignments consisted of implementing a simple program in both Java and C++, and asking to the student to pay careful attention to similarities and differences. This reminded me of CS101, which occasionally referred to both Python and Java. Overall, this strikes me as an excellent idea. Would more students be exposed to different languages early on, even if it only happened on a superficial level, you probably wouldn’t see so many insecure people online who defend Java because it’s the only language they have ever been exposed to. This isn’t necessarily a jab at Java, but at the educational system. Had they learnt Python, they would instead pollute Reddit and other places with remarks that Python is all you’ll ever need.

CS102 was mostly about concepts. You could learn about object-oriented programming and its history, tip your toes into functional programming by going through introductory examples of recursion, and familiarize yourself with the Java collections framework as well as the C++ STL on a basic level. It was all intended as a first exposure to the topics, presumably to make subsequent courses more accessible.

The teaching materials were mostly of a high quality. David Eck’s free online book, Introduction to Programming Using Java, featured prominently in the course. It is very well written. The author makes sure to explain each concept and gradually build upon it. I have seen quite a few introductory books that were full of hand-wavy explanations, or appeals to the reader to just accept something at face value for the time being. In addition, there were a few lectures taken from Stanford’s CS106B: Programming Abstractions, some from MIT’s 6.00: Introduction to Computer Science and Programming and some videos on sorting and recursion from Khan Academy. Those were sources I was familiar with already. I did not know about the accessible illustrations of sorting algorithms by Xoax.net, though. For a beginner, they may well be the most suitable resource online. I wish I had seen those videos when I first studied sorting algorithms.

I had very few gripes with the course. First, while the materials were generally very good, one (external) assessment quiz was so bad that it made me laugh. Here is a screenshot of the quick sort quiz:

Amateurish quiz

So, what are the problems with it? The presentation is poor, and so is the content. The first question is ill-defined since quick sort requires picking a pivot element first. Amusingly enough, the second question asks about this. Lastly, the definition of “divide and conquer” is far too sloppy. It should not take many resources for Saylor to drop this quiz and instead create one themselves.

Second, some sources were too specific and technical. In particular, one introduction to the STL and generic programming, in Unit 7.1, was addressing experienced programmers and was therefore inappropriate for this course. Third, even though CS102 covered a relatively wide spectrum, the final exam mostly focussed on definitions related to OOP and language particulars of Java and C++. Thus, this experience was anticlimactic. I would have expected at least some coverage of sorting algorithms, or a question or two on the analysis of algorithms. Further, a few of the questions were downright pedantic, asking for minutiae like the exact names of specific Java object methods. With a bit of programming experience, they are trivial answer, which made me think of Feynman’s statement that there is a difference between knowing the name of something and knowing something. I would have appreciated a stronger focus on conceptual understanding.

Before I enrolled in this course, I peeked ahead, and learnt that CS107: C++ Programming contains substantial programming assignments. Thus, I viewed CS102 as a course that introduces concepts in preparation for follow-up courses. Therefore, I don’t view the lack of more challenging programming exercises as negative. Overall, I think that this course is well-designed. In fact, the approach Saylor pursues by laying a strong theoretical foundation first before properly introducing students to programming may be superior to what you normally experience, i.e. either mostly ignoring theory and history and merely focussing on practical knowledge and risking that students won’t acquire a solid foundation since they don’t really know what they are doing, or trying to teach programming and CS concepts at the same time, which can be confusing for students.

Review: Games without Chance: Combinatorial Game Theory — Coursera

One of the most engaging educational experiences I’ve had so far, not just on Coursera but in general, just ended: Tom Morley’s Games without Chance: Combinatorial Game Theory. If you’re like me two months ago, you now probably wonder what a mathematical game is. So, let’s start in medias res by showing you one of the mathematical games we’ve studied. Here’s a position of Hackenbush:

Hackenbush position

The players, called “Left” and “Right” respectively, move in turns. Left cuts the blue stalks, and Right the red ones. Cut stalks are removed from the game. In addition, any other stalk that has no connection to the ground anymore after a move is removed as well. The first player to not have a move left loses the game.

The entire course can be easily described just based on this one game. Of course, you can just look at one single Hackenbush tree and enumerate all possibilities, trying to mechanically figure out who has to win or lose given best play. There are four possible outcomes. The winner is either Left, Right, the first player to move, or the second player to move. This works well with a small tree, but if you start with a complicated enough tree, add more trees to the game, or even add different kinds of games, this procedure quickly becomes impractical. So what else can you do?

Well, you could represent the trees as numbers and figure out the result of the game based on that, and you can also simplify games to positions that are easier to reason about. Of course, if it’s possible to represent a game as a number, the simplification happens numerically. On the other hand, if the game is represented as a position, you can translate it into a simplified game position, e.g. a complex Hackenbush tree into one that has the same outcome but is easier to reason about.

Those were the main points of the course. Of course, the occasional proof was thrown in as well. Further, we studied more than just Hackenbush. Above, I alluded to other games, which you could add to a given Hackenbush formation. Those were Nim, Toads and Frogs, Cut Cake, and a few others. Feel free to look them up. However, you’ll notice that they are interesting due to their mathematical properties, but that they aren’t necessarily the kind of game you’d play with your friends to pass the time. After all, the essence of mathematical games is to study rules, strategies, and outcomes using the tools of mathematics, and only incidentally to play them.

There were no prerequisites for this course, but it was “highly recommended that students have taken rigorous college level Mathematics courses”. If you’ve been exposed to college-level mathematics, particularly discrete mathematics, you should find the course very accessible. Without this background, though, you may find it difficult to make the conceptual jump to abstract reasoning. I found the material quite easy to follow, but I’ll refrain from calling Games without Chance an easy course. In the forums there were complaints that the course didn’t “make any sense”, but such statements were rather rare, presumably because the crowd seemed highly self-selecting.

The course was small, and it felt small. In fact, for the first time when taking a Coursera course I thought that skimming the forums was worth my time. Tom Morley himself contributed quite a bit, too, often with his delightful and quirky sense of humor, for instance in this exchange:

Forum Discussion

Lastly, let me remark that the course was well-organized. The people at Georgia Tech seem to have put a lot of thought into it. While most courses on Coursera greet you on the announcement page, and from there on let you explore videos, quizzes, extra problems and so on, Games without Chance had, in addition, tabs that summarized the relevant content for each of the seven weeks. From one page you could access a summary of the relevant part of the syllabus, slides, videos, quizzes, and extra problems. At the very end they sneaked in a weekly survey asking for feedback regarding how you perceived the difficulty and how much time you’ve spent on the problems.

Overall, I found that Games without Chance was well worth my time. I’d highly recommend it to anyone who enjoys abstract reasoning. If you love puzzling over problems in, say, graph theory, or enjoy formal logic, then this is probably a course you might want to consider taking when (if?) it is offered again in the future.