Monday, March 24, 2008

A lil homework

As part of my lil homework yesterday, I had this 'kahani'.

'A toy is controlled remotely over some grid like terrain. Along with its positional coordinates, the toy also maintains its facing (North, South, East, West) so that when remotecontrol commands 'move' - it moves in its facing direction. On turnLeft command, if facing North it would face West. On turnRight command, facing East then would be South. And so on .. '

Well smarty pants, I, declared an enum type.
public enum Facing {North, South, East, West;}


Writing a function to turn things right seemed simple enough!

public void turnRight() {
switch (this.currentFacing) {
case East : this.currentFacing = Facing.South; break;
case West : this.currentFacing = Facing.North; break;
case North: this.currentFacing = Facing.East; break;
case South: this.currentFacing = Facing.West; break;
default: break;
}
}


the similar way to implement the turnLeft() method!!! Now, this didn't seem to tough, eh? Ehrrrrrr! too many conditional statements? If say a new facing (NorthEast) is added, then for things to work, existing code would have to be broken and modified?

Now, Java 5 came with linguistic support for enumerated types enum. All enums implicitly extend java.lang.Enum and allow you to add typical class constructs. 'enum' is also Comparable and Serializable. Now, I could write some complicated program to solve the conditional expressions above. But hey all java enum return an array of declared enums through enum.values(). Voila!

So I wrote:

public enum Facing {North, East, South, West;} //change in order!

public Facing getFace(Facing refFace, int factor) {
int currentIdx = 0;
Facing[] faces = Facing.values();
for (int i=0; i < faces.length; i++) {
Facing face = faces[i];
if (face.equals(refFace)) {
currentIdx = i;
break;
}
}
currentIdx = currentIdx + factor;//the next facing index
if (currentIdx < 0) {
while (currentIdx < 0)
currentIdx = currentIdx + faces.length;
} else if (currentIdx >= faces.length) {
currentIdx = currentIdx - faces.length;
}
return faces[currentIdx];
}


if I consider turning left/anticlockwise as negative ..

getFace(Facing.North, -1); //=>Facing.West
getFace(Facing.North, +5); //=>Facing.East


So in the end, my turnRight() and turnLeft() turned to

public void turnRight() {
this.currentFacing = getFace(1, this.currentFacing);
}
public void turnLeft() {
this.currentFacing = getFace(-1, this.currentFacing);
}

Even if I go and change the Facing declaration to something like
public enum Facing {North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest;}
things would still work as expected if you want to turn left from say North Facing 1 step to NorthWest, 2 steps to West or even turn 720 deg! :)

Think about implementing the same for Days of week, or Months and do similar mathematics on them.
 
day = add(Day.Monday,4);
day = add(Day.Monday,-3);
month = add(Month.January,-3);


You can further generalize things further using
day.getClass().getEnumConstants()

enum is Tiger introduced. Prior to that java, standard way was like declaring a public static final constant usually in an interface/abstract class! For example, how do you add days, month or years to a calendar object?
calendarInstance.add(Calendar.DATE, 2);

Notice the similarity of definition but the differentiation? Declared in Calendar class
public static final int DATE = 5; 

if only java had operator overloading instead of the exotic darker beans and means for the riches! :((

No comments: