views:

604

answers:

7

Hey guys, I know this is a rather trivial question, but what is the best way handle this situation? I have several cases and I am just using simple if, if elses. I remember using a look up table at one point and I drew one out on paper, but I am not sure how to implement it in Java. Any tips would be appreciated, even if the answer is that my way is just fine.

 private int transition(char current, int state)
{
    if(state == 0)
    {
        if(current == 'b')
        {
            return 1;
        }
        else 
            return 0;
    }
    if(state == 1)
    {
        if(current == 'a')
        {
            return 2;
        }
        else 
            return 0;
    }
    if(state == 2)
    {
        if(current == 's')
        {
            return 3;
        }
        else 
            return 0;
    }
    if(state == 3)
    {
        if(current == 'e')
        {
            return 3;
        }
        if(current == 'b')
        {
            return 4;
        }
        else 
            return 0;
    }
    if(state == 4)
    {
        if(current == 'a')
        {
            return 5;
        }
        else 
            return 0;
    }
    if(state == 5)
    {
        if(current == 'l')
        {
            return 6;
        }
        else 
            return 0;
    }
    else
        return 0;
}
+2  A: 

i switch statement would be best here:

private int transition(char current, int state)
{
    switch(state)
    {
        case 0:
            return current == 'b' ? 1 : 0;
        case 1:
            return current == 'a' ? 2 : 0;
        case 2:
            return current == 's' ? 3 : 0;
        case 3:
            return current == 'e' ? 3 : (current == 'b' ? 4 : 0);
        case 4:
            return current == 'a' ? 5 : 0;
        case 5:
            return current == 'l' ? 6 : 0;
        default:
            return 0;
    }
}

And a note, theres only 5 if statements there checking pure intergers, this is not exactly an overhead.

RobertPitt
@RobertPitt Thanks! I appreciate the extra feedback.
PFranchise
updated to complete your logic.
RobertPitt
to shrink the code even more, if you use short hand logicals and you keep them to 1 line you can then remove the `break;` commands, IF java has that within its interpretor.
RobertPitt
why the down vote ?
RobertPitt
You don't really need _brake_ if you have _return_, right? Could make it a bit smaller.
Nikita Rybak
I am pretty sure using break after a return is invalid and causes compile errors.
Willi
@Willi is absolutely correct. I took the liberty to make the code in the answer compile.
Jonik
ive never worked with Java, I was just writing the code that would usually fit into all languages, thanks for the update.
RobertPitt
+9  A: 

consider interfaces + enums:

interface State<T>
{
    public void State<T> step(T input);
}

enum MyState implements State<Character> {
    STATE0(0) { @Override public void MyState step(Character c) { return c == 'b' ? STATE1 : STATE0; }},
    STATE1(1) { @Override public void MyState step(Character c) { return c == 'a' ? STATE2 : STATE0; }},

    /* rest of states here */

    final private int value;
    MyState(int value) { this.value = value; }
    public int getValue() { return this.value; }
}

class SomeClass
{
   public MyState currentState = STATE0;

   public void step(char input)
   {
      this.currentState = this.currentState.step(input);
   }
}
Jason S
+2  A: 

Use switch statement for the outer if chain:

switch (state) {
  case 0: <code> ; break;
  case 1: <code> ; break;
  case 2: <code> ; break;
  <etc>
  default: return 0; break;
}
Oblomov
@oblomov Thanks!
PFranchise
+14  A: 

Well, you can easily utilize hash. Simple and clean.

    // declare hashtable
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("0-b", 1);
    map.put("1-a", 2);
    map.put("2-s", 3);
    ...

    // get result
    Integer result = map.get(state + "-" + current);
    // change null (nothing found) to zero
    return result == null ? 0 : result;
Nikita Rybak
Performance wise, wouldn't it be better to create a new class that holds a digit and char and have it have a hash function that generates a unique hash so that the hash table can perform faster?
mathepic
@mathepic Certainly, there's lots of room for improvement. (Although you may find that creating unique hash function isn't always easy, especially as number of states grow). I just wanted to provide simple and clean example of lookup table. And it's not like HashMap has that much overhead comparing to other methods, like one- or two-dimensional arrays.
Nikita Rybak
Yeah, I was just making a suggestion. +1.
mathepic
+5  A: 

Looks like you need a better abstraction for a finite state machine. Think about a class that encapsulates what you want in a better way so you can extend it by configuration rather than modifying code.

duffymo
Thanks for the tip. I was worried that I was hard coding too much. I will reconsider the way I am going about it.
PFranchise
+1 In my humble opinion the best suggestion here. When I see lots of if's, the first thing comming to my mind is 'Use Inheritance'.
Helper Method
As a general rule, you can *always* replace conditions with polymorphism. After all, what *is* dynamic method dispatch if not a giant switch statement? Smalltalk, for example, does not have *any* conditionals, *everything* is done through method dispatch.
Jörg W Mittag
True, you can always replace conditions with polymorphism, but I wouldn't agree that it's always the best solution. In this case, polymorphism would result in lots of small classes, and it may not be the most declarative. I'd prefer a declarative solution here.
duffymo
+5  A: 

If this code is about to be expanded over the time, why not use a state machine? Each state will return the next state based on the character it receives. Maybe it's an overkill for this code, but it'll be a lot easier to maintain, expand & read.

duduamar
Code almost always changes!
Alex Baranosky
+29  A: 

What you're trying to do looks very much like a finite state machine, and these are usually implemented with the help of a transition table. Once you set up the table, it's simply a matter of indexing to the position you want to get the return value. Assuming your return values are all less than 256, you can use a 2D byte array:

byte table[][] = new byte[NUM_STATES][NUM_CHARACTERS];
// Populate the non-zero entries of the table
table[0]['b'] = 1;
table[1]['a'] = 2;
// etc...

private int transition(char current, int state) {
  return table[state][current];
}
casablanca
+1 - Exactly, very nice.
duffymo
Haha this is exactly what I was looking for. I am actually implementing a finite state machine.
PFranchise
I'd accept this one if I were you. It's by far the best answer.
duffymo
Jason S