fév.
2013
Some days ago, ZeroTurnaround, of JRebel fame, published a funny Java Quiz on their website.
It is not very hard, and there are at least 3 different solutions that I know of.
Below is my solution ; but try to find your own before taking a look !
My solution :
The whole goal of this quiz is to find a way to identify and differenciate the contexts in which the two messages are used, to avoid printing any of them multiple times.
One major difficulty is that the Unicorn.pat()
method is called a random number of times for each message, so we cannot rely on some counter to allow patting or not.
But one thing we do know, is that our Unicord.pat()
method is called at two different lines in MagicalLand
, each one being responsible of the printing of a particular message. If we manage to allow only one patting per call site, we should be good.
And it is fairly easy to know where you are called from : just look at the call stack !
The implementation is straightforward : create an Exception
to get a stack trace, find the calling line, and ensure we don't allow patting more than once per call site.
public class Unicorn { static int line; public static boolean pat() { int thisLine = new Exception().getStackTrace()[1].getLineNumber(); boolean shouldPat = line==0 || thisLine!=line; line = thisLine; return shouldPat; } }
So, what is your solution ?
Commentaires
I did it using Thread.currentThread() instead of throwing a new Exception, and using a Set, taking advantage of its add method which returns true if the set was modified to shorten the code a little.
The gist is here: https://gist.github.com/agrison/499...
Huh, I was not aware that one could read the stack through the Thread class, this is interesting.
@Olivier That way and yours are the only one I know of (or I can remember of).
I imagine it may be possible to do it using aspects, retrieving the caller from the join point (it would be fun to see).
However, I would be interested in the two other ways you said knowing in your post :-).
Well, if you look at Thread.getStackTrace() here: http://grepcode.com/file_/repositor...
You'll notice this:
return (new Exception()).getStackTrace();
Are we allowed to implement a 3rd class ?
Here is a different solution:
https://gist.github.com/damienlepag...
Hi Olivier!
I hope you're been given the source of the MagicalLand class, or at least a MagicalLand.class file with debugging information.
Because if the quiz author only provides you with an already-compiled MagicalLand class with no debug info, then you're stuck!
As the javadoc says: StackTraceElement.getLineNumber() returns a negative number whatever the actual line if this line information is unavailable. And why would it be unavailable? Typically because no debug info was included while compiling the class!
Unless you explicitely disable them at compile-time, some debug informations are automatically included in the binary class files - at least file name & line number, see the -g option on http://docs.oracle.com/javase/7/doc...
And no such limitation was specified by the quiz author :)
My solution is to have Unicorn.pat() always return true and instead replace the standard System.out with a custom implementation of PrintStream which overrides the println() method in a way that only allows each output once.
public class Math {
public class Unicorn {
}
@error3 That was my first idea too.
That's also what i did to get maximum score on Olympic Games Google Doodle :)