Java Puzzle 1: Clowns

Feb 16, 2012

Introduction


This is the first in a series of Java puzzles, that put your Java skills to the test, in a challenging and fun way!
A puzzle consists of some given Java code with a line in it that seems to be impossible to reach. It's up to you to find the hole in it, abuse a subtle behavior of Java to make execution reach that line anyways.

There almost aren't any rules; any cheating inside your code is allowed; it is the whole point of the puzzle. [Clarification: Cheating the environment is not]. You must run with the security manager enabled (java -Djava.security.manager), otherwise it would be too easy (with setAccessible for example). [Update: Use common sense, and see the exact rules if you're in doubt].

The puzzle

How can you fit 20 clowns into a Volkswagen? Two classes are given: an empty Clown class, and a Volkswagen class to which you can add clowns. When you try to add a Clown, it is checked that it isn't already full. But if you just try hard enough, there's always room for some extra clowns...

package clowns;

public class Clown {
}
package clowns;

import java.util.HashSet;
import java.util.Set;

public class Volkswagen {
    private static final int CAPACITY = 5;
    private Set<Clown> clowns = new HashSet<Clown>();

    public synchronized void add(Clown clown) {
        if (clowns.size() >= CAPACITY) {
            throw new IllegalStateException("I'm full");
        } else {
            clowns.add(clown);
        }
    }

    public synchronized void done() {
        if (clowns.size() == 20) {
            // The goal is to reach this line
            System.out.println("I'm a Volkswagen with 20 clowns!");
        }
    }
}

Write a class that when executed pushes 20 clowns into the little car, and reaches the marked line. Here is one that won't really work, just to get you started:

package you;

import clowns.Clown;
import clowns.Volkswagen;

public class You {
    public static void main(String args[]) {
        // TODO put 20 clowns into a Volkswagen
        Volkswagen vw = new Volkswagen();
        for (int i = 0; i < 20; i++) {
            vw.add(new Clown());
        }
        vw.done();
    }
}

You can copy-paste the code into your IDE, or get it from github (zip).
If you've solved it, let me know (email or Twitter). If you're the first, you'll get... the honor of being the first. compare it to the solution posted here.
The solution and a new challenge will follow, so stay tuned!

Update: Don't post answers as comments here, they will be blocked by moderation. You may comment, but no spoiler. If you have an alternative solution, post it as a comment on the solution post
Update 2: Added clarification of the rules.


10 comments

Picimobile wrote on 2012-02-17 12:34

A quick and dirty solution would be: private static final int CAPACITY = 20;

Wouter wrote on 2012-02-17 14:18

I should have mentioned it more explicitly, but you are only allowed to edit the file containing the “You” class, nothing else.

Jean-Louis Willems wrote on 2012-02-17 13:32

Solution found in 30 minutes. Very nice game.

Xu ShiChang wrote on 2012-02-17 14:05

Are we allowed to use a customer classloader? It sounds too much of a cheat to me.

Wouter wrote on 2012-02-17 14:16

Good question. You are allowed to create a custom classloader and load any classes in from within your code, for as far as the security manager allows that. But “The goal is to reach this line” only applies to that line in the real Volkswagen class, not a copy of it (which will need a different name I think) in another classloader.

You are supposed to run just java -Djava.security.manager you.You, adding extra options to java (for example to use another classloader, or a non-standard security policy) is not allowed.

Jitendra wrote on 2012-02-17 20:02

I am not really expert in java so waiting for solution. :P Would it be posted here?

Wouter wrote on 2012-02-18 17:11

Yes, it’s coming soon.

Cypher wrote on 2012-02-18 18:30

I need easier puzzles! Seems that only one semester of java basics a couple of years ago just isn’t enough to solve this ;)

Wouter wrote on 2012-02-18 21:32

Yeah, I’ll also have some easier ones. Not the next one, but the third one probably…

Heinz Kabutz wrote on 2012-02-20 10:53

No please, no easier puzzles. More difficult! The web has tons of easy Java puzzles.

Ryan Schipper wrote on 2012-02-23 19:20

I have to agree with Heinz on this one.

Any lateral thinker with solid Java experience (or broad reading) should be able to get the general idea within a short period of time.

It was a good puzzle. Took me 30-45 minutes (I wasn’t tracking too closely).

Dominique Laurent wrote on 2012-02-24 03:16

I’m a Volkswagen with 20 clowns! ;-)

Not really hard when you have done the 2nd puzzle first.

eugene wrote on 2012-02-24 09:55

This is brilliant! I have not solved it myself, so nothing to be proud of, but it was a pleasure understanding it anyhow. Thx a lot!

Igor Horov wrote on 2012-02-29 02:35

Would it be considered a legit solution to use serialize-adjust_byte_code-deserialize trick? The class file is not touched and the runtime Volkswagen instance would be real…

Wouter wrote on 2012-02-29 10:09

Yes, anything in your code is allowed. But you’ll have some trouble with that trick: Volkswagen is not serializable.

thelearner wrote on 2012-06-28 22:52

Excellent puzzle, takes one to the depth of the fundamentals.