Directory of solutions and tests
for (Object i : ys)
if (i.equals(x))
return true; // just check if x is an element of ys
return false;
i.e. single-line blocks marked only by indentation, not {}. The fact that
this is legal doesn't make it a good idea. Just don't, unless you're
putting the whole block on the same line with the conditional, e.g.
if (i.equals(x)) return true; // fine even according to me ;-)
Trust me on this, it's asking for someone else (or even you) to be misled
by the indentation and introduce a bug later. (Admittedly, less likely than
it used to be, now that most people use syntax aware editors; but still.)
Most people who tried it got (a) right, though some made "let's throw away marks in the exam" type errors like not implementing a main as requested, or giving the function the wrong name! The point is that doing % 2 on a negative number gives, not 1, but -1. (Note that in base 2, -1 = 1, so if Java were really implementing that, there wouldn't be a difference to be seen - but Java doesn't have a "base 2 integer" type...)
There were two reasonably succinct bodies for isTrulyOdd:
return i % 2 != 0;
and
return Math.abs(i) % 2 == 1;
(actually the abs can be applied either to i or to the entire LHS, and I
saw both). Perhaps the former is slightly preferred, as not requiring a
call to a library function, and being only two characters different from
the given body.
To (b) and (c) I saw only one correct answer (well done Adam!). How could it possibly be that a while loop with condition (i == i + 1) could be executed even once, never mind go on for ever? Note to start with that we are not told the type of i. We can see that it's something on which + makes sense; that could be any numeric type, or String. The name i suggests it's an integer, but it's already clear this is a trick question... As a children's riddle, the question "what number stays the same when you add one to it?" has the fairly obvious answer "infinity", and that gets you on the right track. Type int doesn't have infinity as a value... but type double does have a defined constant Double.POSITIVE_INFINITY, and that's the definition we want.
Having got (b), (c) is fairly easy as it requires the same kind of thinking. How can a loop with condition (i != i) go on for ever? It turns out that Double.NaN ("not a number"), or any expression that evaluates to that, will do fine.
Here's my cut-down version to which I'd have given full marks. Note the half-hearted attempt at being something less than horribly inefficient: at least mine doesn't copy the entire backing array on every add or remove...
Many people wrote code where indexOf blindly sent equals to each element of the list in turn, and thus would break if any element were null, although their code did permit null to be entered as an element. I think you do need either to check that you don't permit anyone to add a null element, or else to handle null elements properly. But I didn't penalise it.
In the add method, I several times saw code a bit like this, where myList is an existing array (the old backing array)
int[] temp = new int[size];
temp = myList;
Note that the allocation in the first line is completely pointless! The
second line does not do an array copy; it just makes temp be a new
reference to the same array that myList is (and its length is whatever the
length of myList is, for example - the value of size is irrelevant, though
in most people's code it did happen to be the length of myList also). Now
the new int[size] created in the first line is garbage collected, as
nothing points to it any more... What you wanted was simply
int[] temp = myList;
The real ArrayList has two versions of remove, one taking an index and one
taking an Object; I didn't tell you which to implement. Most people did the
former, but either was fine.
I saw quite a few bits of code a bit like this:
int i=0;
for(String str1 : aList){
bList[i] = str1;
i++;
}
If you want to use the loop variable explicitly, it's better - less
error prone - to use a conventional for loop, e.g. for (int i=0; i <
aList.length; i++)
. Save the foreach loop for where you don't care
about the loop variable.
Note that the best way to do this in Java turns out to be an oft-discussed question. Here is one place to start.
About how the Haskell version works: almost everyone did what I did, on the assumption that in this case the evaluation would be strict and the map would be done before the fold was begun. Then, when one student didn't, I wondered whether Haskell's laziness actually means that that map will be done only as demanded by the foldr... to which the answer seems to be Probably. The Haskell expert I asked commented that "Haskell's cost model is, er, non-trivial." and gave various helpful advices which I haven't followed up yet... maybe you'd like to.
Very few people (including me!) took notice of the fact that this is a foldr not a foldl, and I didn't expect it, but well done those who did. Note that equals is required to be symmetric (ish) so we don't need to worry (much...) about which object we call equals on.
(My code assumes, as did most of yours, that the input String is non-null: as so often with null, this is the kind of thing that ought to be specified in a precondition. As I hadn't mentioned it in the question (only in my code!), I gave credit for both ways.)
Many people did it the hard way by building their own, and it's not really that hard if you do it efficiently; that was fine. Here are some tests too.
Thanks to Kerri for starting these off!
Perhaps because my error made it so confusing, or perhaps because few people have looked into concurrency much yet, there were very few attempts at this and no really good ones. Consider having a go now!
Do not synchronize the whole run method! You're then removing the concurrency from the program altogether, basically: whichever thread gets to start first gets to do all its counting before the other can start. That was the force of "Take care not to slow the program's execution more than you must.". See this Stackoverflow page for example.