As all participating teams are no doubt aware, this year's competition was very tough. Though the questions were considered interesting and fun by most, there was a fair amount of complexity involved in actually attaining 100% correctly functional solutions. Given the difficulty of the tasks, and the short length of time available, we were most impressed by those teams which were nevertheless able to construct complete solutions.
We received 65 entries this year. Visual Basic was yet again by far the most popular language. While we saw a definite improvement in that teams did not seem to waste time on GUI features, candidates using Basic variants continue to struggle. Nonetheless, since a high proportion of entrants use VB, we will publish VB solutions to the tasks very shortly that will hopefully illustrate some useful programming techniques that can improve teams' programming repertoire in Basic. We generally encourage the use of C++, which is a very versatile and powerful language.
| Language | Number of Teams | Average Score | |
|---|---|---|---|
| Basic variants | 38 | 58% | 15 |
| C/C++ | 13 | 20% | 21 |
| Pascal | 6 | 9% | 22 |
| Python | 4 | 6% | 27 |
| Java | 3 | 5% | 18 |
| Haskell | 1 | 2% | 47 |
In terms of marking, we had to ensure that teams who went the extra step and made sure their solutions were fully functional were rewarded. In the real world, all that matters in the end is whether a program works correctly. And in that spirit, this competition is primarily meant to be marked based upon the output to the supplied marking data. We did look at code too, giving credit for good ideas and good programming style, but correct output was essential for high marks.
Teams competing next year should be advised to please read the instructions carefully and to make sure they submit output to the marking data. Effort is probably better spent ensuring that solutions are fully correct, working for all cases, than patchily chalking up outlines of half-solutions to as many questions as possible.
Average score: 8.2
This question, clearly the easiest, was attempted by nearly all teams, with the general method employed being to read in a string of characters, counting word lengths as one went along. The majority of teams grasped the basic idea and made a good start towards the solution. Unfortunately, many teams slipped up with minor details, forgetting to convert 10 to 0, or not handling punctuation correctly.
Many teams dealt with individual punctuation items, such as "," or ".". The best approach was to test if a character was an alphabetic letter, and if not to consider it punctuation (usually ignoring it would work just fine).
Some teams required the user to enter in every word. While this received some marks, we could not give it substantial credit as it clearly avoided the spirit in which the question was intended.
Average score: 3.2
The crux of the problem lies in converting the password into a sequence
of numbers (or "orders") that can be easily used to rearrange the text.
There were some surprisingly elegant solutions, which made the task seem
much easier than it is, though by and large teams got into a jumble themselves
using nested for loops. One of the key programming techniques that
needed to be used here was the idea of breaking up a big problem into a number
of smaller, simpler problems, that can be handled by small functions.
Average score: 2.3
This problem, essentially the only maths-oriented one, was
very widely attempted, though it turned out to be rather
challenging. Most teams tried to convert to base 10, take mn,
and then convert back to base 7. Unfortunately, there was the complication
of handling large numbers. While some programming languages have unlimited
integers (e.g. Java's BigInteger), most teams would have needed
to effectively write their own multiplication subroutine. Noticing that
only the last ten digits need to ever be recorded simplified this
trememndously. With these difficulties, while many teams were awarded partial credit,
only one teams received a mark higher than 10 (gaining 14 points).
Average score: 2.7
This question, unfortunately, was not as widely tried as Tasks 2 and 3, even though
it was probably somewhat easier, as long as teams had an idea of how to produce
random numbers. The correct probability was 0.6429, though we were fairly
generous in marking the output, accepting between 0.63 and 0.65
(to 2 decimal places) for full marks, and accepting an even wider range for partial credit.
We felt that teams needed to be aware that 1000 runs was not a good enough estimate
(unless repeated many times). The ideal was to look at the results one was
getting from a few test runs, and make sure that they were not varying too
wildly. If they varied substantially, a much greater number of runs was
needed. Many teams made very good headway with this problem, though
some neglected to tidy up small details (such as clearing the "last card" and "two cards
ago" records when players swap turns). Overall, teams that tried this
question seemed to definitely enjoy it at least.
Average score: 0.7
Hardly any teams tried this taxing problem. In nature, this problem was not very
different from Task 6, yet many more attempted that (probably harder) problem than this
one. We are not sure if the "picture" format of this problem, or having to recognise the
NO PATH case, scared students off, but many teams that coped well with Task 6
may have had more luck with this task. There were two good solutions, one a classic
breadth-based search, the other a recursion-based search. The recursion-based search,
as one would expect, produced ugly paths (looping back on themselves) but
was nonetheless correct. No-one attempted the approach we thought most
would try, to start at one of the friends, label it somehow as "1", then
label all adjacent squares "2", then all adjacent to a "2" a "3", etc.
After repeating this as much as possible, an easy trace from friend to
friend would be possible (or in the NO PATH case, the second
friend would not be labelled at all).
Average score: 1.0
This problem, though probably the hardest, seemed to generate an abundance of enthusiasm.
Many teams tried, and were able, to at least code in the four basic rules, though being
able to apply all possibilities repeatedly until CSE was reached was beyond
most. One team produced a flawless breadth-based search. Another used a very clever
heuristic approach, which basically had a strategy in mind and would attempt to use rules
according to the strategy. This, though not flawless, worked for all the marking data
provided, so it was awarded very high marks. Teams that attempted Tasks 5
and 6 might like to look at the solutions which demonstrate how to enact a
breadth-based search.