pagetop
Javablog
by Java coders, for Java coders RSS

Escape from Zurg

October 13th, 2007 by Sam

Paul Butcher from the Texperts recently wrote a great blog post with a Ruby implementation of Escape from Zurg. I had been meaning to learn both Ruby and Haskell for a long time and recently invested in some reading material. But it wasn’t long before I got the craving to write a Java version. The idea is not to solve this specific problem, but to use it to show how more general searches may be solved in these languages.

Buzz, Woody, Rex, and Hamm have to escape from Zurg. They must cross one last bridge before they are free. However, the bridge is fragile and can hold at most two of them at the same time. Moreover, to cross the bridge a flashlight is needed to avoid traps and broken parts. The problem is that our friends have only one flashlight with one battery that lasts for only 60 minutes. The toys need different times to cross the bridge (in either direction):

  • Buzz: 5 minutes
  • Woody: 10 minutes
  • Rex: 20 minutes
  • Hamm: 25 minutes

The problem is: In which order should the four toys cross the bridge?

The problem may be solved by a brute-force search in a finite state-space (due to the “hard” limit of 60 minutes). Any valid solution (i.e. not necessarily optimal) will do, so the search is complete when the first valid solution is found. This is not really a generic search problem as search spaces may be infinite, have “soft” limits and optimal solutions may be required. However, it does make for a good programming exercise.

Search problems of this variety can be visualised as a tree graph with the vertices representing the state at a specific point in time, and the edges indicating a change of state. The hard limit in this example kills off any cycles that may arise. The algorithm employed by the original Haskell implementation is a forwards depth-first search, which is memory efficient as it does not store the entire state space in memory. We will do the same here but we’ll find all the solutions, not just the first one.

In true Java style, we’ll try to be as general as possible to begin with and come up with a dumb depth-first algorithm to print out all the valid solutions to search problems with a hard limit. We then realise that our most important object types are interfaces for State and Move, which we define as

// implementations should override equals()
public interface State {
    public State move(Move move);
    public Set<Move> moves();
}
 
public interface Move {
    public int cost();
}

and then the depth-first solution is implemented as

public class SearchProblem {
    private final State end;
    private final State initial;
    private final int limit;
 
    public SearchProblem(State initial, State end, int limit) {
        this.initial = initial;
        this.end = end;
        this.limit = limit;
    }
 
    public void solve() {
        solve(initial, 0);
    }
 
    private void solve(State state, int existingCost) {
        for (Move move : state.moves()) {
            int cost = existingCost + move.cost();
            if (cost > limit)
                continue;
            State newState = state.move(move);
            if (newState.equals(end)) {
                System.out.println("Solution discovered at " + newState);
                continue;
            }
            solve(newState, cost);
        }
    }
}

We now still need to code up the specific problem… let’s define the Toys as enums with a set time and the sides of the bridge as an enum

public enum Toy {
    Buzz(5), Hamm(25), Rex(20), Woody(10);
    private final int time;
    Toy(int time) {
        this.time = time;
    }
    public int getTime() {
        return time;
    }
}
public enum Direction { Left, Right }

and implement Move

class ToyStoryMove implements Move {
    private final Direction direction;
    private final List<Toy> toys;
 
    public ToyStoryMove(List<Toy> toys, Direction direction) {
        this.toys = toys;
        this.direction = direction;
    }
 
    @Override
    public int cost() {
        if (toys.size() == 1)
            return toys.get(0).getTime();
        return Math.max(toys.get(0).getTime(), toys.get(1).getTime());
    }
}

The generation of the moves is implemented in State (Note: updated, see comments for original)

@Override
public Set<Move> moves() {
    Set<Move> moves = new HashSet<Move>();
    if (torch == Direction.Left) {
        for (List<Toy> moving : combinations(leftBank)) {
            moves.add(new ToyStoryMove(moving, Direction.Right));
        }
    } else {
        Set<Toy> toys = exclusive(Arrays.asList(Toy.values()), leftBank);
        for (Toy toy : toys) {
            moves.add(new ToyStoryMove(Arrays.asList(toy), Direction.Left));
        }
    }
    return moves;
}

everything else is pretty much Eclipse-generated boilerplate. Running the code gives the two solutions

  • Buzz and Woody go right
  • Buzz goes left
  • Hamm and Rex go right
  • Woody goes left
  • Woody and Buzz go right

and

  • Buzz and Woody go right
  • Woody goes left
  • Hamm and Rex go right
  • Buzz goes left
  • Woody and Buzz go right

Full code available as a zip download. Admittedly, it is somewhat more verbose than the Ruby or Haskell code… but at least 1/5 of the code is in documentation and everything you don’t see above was either auto-generated by Eclipse or is a debugging assertion. The search space is exhausted within 40 milliseconds on my MacBook, but it’s a really small space so that doesn’t say much.

PS: I really like Haskell after reading this introduction.


This entry was posted by by Sam on Saturday, October 13th, 2007 at 10:23 pm, and is filed under Haskell, Java, Ruby, Search, Toy Story. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.



12 comments on “Escape from Zurg”

Hey Sam,

Nice to see that you took up the challenge :-)

It’s been a while since I last looked at “serious” Java (I’ve been stuck in the mobile, and therefore Java ME, ghetto for a while :-), so the state of the art has moved on somewhat while I wasn’t looking. But is this really necessary?!

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final ToyStoryState other = (ToyStoryState) obj;
        if (leftBank == null) {
            if (other.leftBank != null)
                return false;
        } else if (!leftBank.equals(other.leftBank))
            return false;
        if (torch == null) {
            if (other.torch != null)
                return false;
        } else if (!torch.equals(other.torch))
            return false;
        return true;
    }

I’m almost speechless! I thought that the arcane rules you had to remember had got out of hand in C++, but that’s unreal! All that code, just to check that two objects are equal?!

Anyway, that’s idiomatic code and doesn’t have much bearing on the Zurg riddle…

There’s one particular bit of the code which illustrates the difference between the Ruby and Java solutions for me. Generating moves in Ruby looks like this:

    def each_successor
      case pos
        when :left
          group.each_pair do |pair|
            yield Move.new(:right, pair), State.new(:right, group - pair)
          end
        when :right
          (Toys - group).each do |toy|
            yield Move.new(:left, [toy]), State.new(:left, group + [toy])
          end
      end

The equivalent Java code is:

    public Set<Move> moves() {
        // generate the set of all valid moves, neglecting cost
        Set<Move> moves = new HashSet<Move>();
        Direction direction;
        List<Toy> toys;
        if (torch == Direction.Left) {
            // must move to the right
            direction = Direction.Right;
            toys = new ArrayList<Toy>(leftBank);
        } else {
            // must move to the left
            direction = Direction.Left;
            toys = new ArrayList<Toy>(Arrays.asList(Toy.values()));
            toys.removeAll(leftBank);
        }
        for (int i = 0; i < toys.size(); i++) {
            Toy toy = toys.get(i);
            moves.add(new ToyStoryMove(Collections.singletonList(toy), direction));
            for (int j = i + 1; j < toys.size(); j++) {
                Toy toy2 = toys.get(j);
                moves.add(new ToyStoryMove(Arrays.asList(toy, toy2), direction));
            }
        }
        return moves;
    }

It took me quite a bit of reading and rereading this code to work out what’s going on. Whereas the Ruby code kinda “leaps out” at you.

Admittedly, the Ruby code looks much nicer because I’ve factored out the generation of unique pairs into each_pair. But how would you do this in Java? I mean, of course you could do it - but would doing so improve the readability of the Java solution? I very much doubt it. Whereas it makes the Ruby properly self-documenting (in the true meaning of the phrase).

Anyway - thanks for doing this. It’s a cute little puzzle which brings quite a bit to light :-)

Cheers!

BTW - comments on your blog could really use a “preview” button so that I can spot when I get my tags in the wrong order before posting ;-)

I must admit, the each_pair thing is nice… in Java one would have a static convenience method in a utility class. I probably should have done it that way for cleanliness (actually, we do have such a convenience method in our codebase, but I didn’t want to depend on anything). I’m also just noting that I could have used a switch statement in there instead of an if else. I’ll maybe tidy up that little bit tomorrow.

The equality thing is a bit of an ugliness in general (also note that hashCode must be overridden too)… but I think there are enough pitfalls to warrant such an extreme response. Josh Bloch’s “Effective Java” has a good section on this. In any OO language, the problem of equality between a class and a subclass (think of a Point and a ColouredPoint) is tricky because you can easily break associativity in equality. Eclipse auto-generates all that code anyway. That said, perhaps a cleaner solution would have been to introduce another method into State with signature boolean isEndPoint(), then there would be no need to do an equality check… but then that means the State object has to define the endpoint, not the main program.

Blame Darren for the lack of a preview button! He was the one who recommended Wordpress and it (surprisingly) doesn’t seem to have that by default. I’ll see if there are any plugins. The comments CSS could probably do with a revamp as well.

Thanks for fixing up my broken tags :-) I’ve just noticed that our site doesn’t have a preview button either (also based on Wordpress). Strikes me as something of an oversight!

I’m familiar with the argument that because code is automatically generated it doesn’t matter that it’s verbose. I don’t buy it though. It might save you time when you’re writing it in the first place, but it still dramatically affects the maintainability of the codebase. Partly because it increases the amount of “clutter” you have to pick your way through, but mainly because it leads to huge quantities of “almost” duplicated code.

Almost duplicated code is the worst kind. Purely duplicated code is bad, but almot duplicated code is really dangerous. You either have to pick your way through it every time you read it to make sure that it really is doing what you think it is, or (more likely) you skip over it thinking “ah yes - that’s the standard automatically generated boilerplate”. Which is fine right up until someone has (intentionally or accidentally) modified it. At which point your mental model is broken. And its broken in a way which is particularly difficult to spot because the pattern matching that the human brain is particularly good at suckers you into it.

It strikes me that there are two ways in which you can cope with complexity. You can automate the process of generating it or you can remove it. That’s the difference between a code generating wizard and something like Rails. I know which of the two I prefer…

Hey! Don’t take my name in vain! There are indeed several plugins for previewing comments in WordPress.

Check this:

http://wordpress.org/extend/plugins/ajax-comment-preview/

Thanks Darren! That plugin is great… I must go and fix up our horrible CSS for the comments now.

You’ve got a good point about the almost duplicated code. In Eclipse the only real code that is autogenerated is the equals and hashCode… everything else is from a template. I wonder if it would be possible to use a utility method instead of generating new code every time. Probably not (or it’d be part of the stdlib). I can’t ever imagine wanting to hack the generated code manually… but if somebody did without noting it in comments, they’d be asking for a big can of whoopass.

How does ruby handle equality (not identity) between objects? And more importantly, how does it handle the pitfall case of class compared against subclass?

I think I’ll try making those tidying edits to the move method, but I don’t think the Java solution for this problem is going to look as elegant (or anywhere near as terse!) as the ruby one ;-) The main reason being the lack of operator overriding for collections. I really really wish they’d add it one day! I can’t see it happening.

PS: I’ve added that extra Java code… I didn’t remove it though, it just wasn’t there. This whole code highlighting thing is a bit of a hack to get working with Markdown, so sometimes it just completely falls over. I’ve installed alternatives but they don’t deal with generics very well.

Hi Paul, I’ve now updated the moves method to be more readable and to look more like your Ruby version. I was lazy in not doing it this way before.

Equality (and comparisons in general) in Ruby are interesting. The simple answer to your question is that Ruby doesn’t try to handle the problem for you. But putting it like that implies that the picture is simpler than it really is. I’m not convinced that most Ruby developers (quite possibly including me) really understand the philosophy underlying Ruby’s equality operators.

Things are also different in Ruby because the philosophy underlying the type system (duck typing) is altogther from that underlying Java’s. So I’m not even sure that the same philosophical issue as the one you’re worrying about really exists in Ruby.

Ruby provides two “core” equality operators. Object#equals? and Object#==. Both of these can be overridden, and both by default just check for object identity.

The difference is that the intention is that you shouldn’t override equals? (i.e. it should remain object identity), whereas the expectation is that == should implement “natural” equality, whatever that means in context. Most of Ruby’s standard classes do override == (so, for example, Array#== returns true if both arrays contain the same number of elements and if each element is equal according to their own implementation of ==).

So, basically, it’s down to you to provide value semantics. The language doesn’t try to do it for you. If you build your app mainly from standard classes, though, mostly it “just works” because they have done most of the work for you.

It’s complicated (or simplified, depending on how you look at it) by the fact that Ruby provides other comparison operators over and above equals? and ==, specifically:

=== (case equality) which is used within case statements

eql? which is used when inserting objects into hashes (so, overriding eql? implies that you should also override hash)

<=> (the “spaceship” operator) which implements comparison for objects which support ordering.

=~ which implements regular expression matching.

Your question has prompted me to do a bit of searching to see if I can find a good discussion of the various different comparison operators in Ruby, and there doesn’t really seem to be anything out there (although there is quite a bit of misinformation!). I may see if I can knock something together for our blog :-)

Those operators sound similar to the Java ones… except == and equals are the other way round. There have been some requests in Java for a === operator so that a === b would be the same as ((a == b) || ((a != null) && a.equals(b))). I’m in favour of this, and it would certainly help to make the above generated code a lot cleaner! null is a real pain in the ass.

Java doesn’t have special equality of switches or entry into hash tables… I don’t really see why one would want to make these different.

The spaceship operator doesn’t have an equivalent operator in Java, but it seems the same as the Comparable interface.

Regex matching in Java is through the Pattern and Matcher classes. It’s a bit more formal than the Ruby equivalents… the String.matches() method is a convenience for simple regexes. I’d also like to see more attention given to indexing of Strings for repeated searching, but nobody seems to have picked up on my post.

Ruby is a very interesting language… the book I bought concentrated on comparing Rails to the insane J2EE frameworks out there. There were parts were I believe Java won hands down (Hibernate for persistence), and others where Ruby destroys Java (e.g. templating)… but as for the language itself, I was comparing it more with Python than Java. As a prototyping language, I’d probably go with Python, but I’m still interested enough in Ruby to continue learning it. The lack of IDE support is a pain, but that’s probably because Eclipse has spoilt me these last few years.

Things Java could learn from Ruby are:-

  • limited subset of operator overriding (even C++ has this… come on Java!)
  • shorthand notation for getter/setter variables
  • the int/Integer/BigInteger thing is a real pain in the butt. It would be amazing if this were transparently built into the language like in Ruby. The Haskell solution is even better… Int is basically {int, Integer} and Integer is BigInteger. However, that would break so much backwards compatibility it’d have to be a new language; It has performance consequences and would break almost all native code out there.

Regarding equal? versus == versus eql? think about it like this:

  • equal?: object identity
  • ==: objects have the same meaning
  • eql?: objects represent the same value

So if you consider numbers:

1 == 1.0
=> true
1.eql? 1.0
=> false

This means that you can have a hash with a keys of both 1 and 1.0 (which wouldn’t be true if hash used ==):

h = {}
h[1] = 'an integer'
h[1.0] = 'a float'
h
=> {1=>"an integer", 1.0=>"a float"}

Regarding ===, this exists to enable some of the nice syntactic sugar that Ruby’s case statement supports. For example:

(1..10) == 4
=> false
(1..10) === 4
=> true

Which means that you can write this kind of thing:

kind = case lines
  when 1..10: "Short"
  when 11..25: "Medium"
  when 26..50: "Long"
  else "Too long!"
end

Regular expressions can play the same kind of trick:

kind = case moment
  when /\d\d:\d\d:\d\d/: 'time'
  when /\d\d\/\d\d\/\d\d/: 'date'
  else 'other'
end

As can classes

case thing
  when String: # Handle strings here
  when Numeric: # Handle numbers here
  # etc...
end

So, as threatened, I’ve written a blog post describing how equality works (as far as I understand it!) in Ruby:

http://www.texperts.com/2007/10/16/navigating-the-equality-maze/

Leave a comment

Markdown is supported.

To include code snippets in your comment, use

<pre><code># lang java
... code here ...
</code></pre>

or use 4 spaces at the start of the line instead of using code and pre tags.

Comment feed: RSS