0

I am trying to create a method in java that would tell whether string is well formed. Each character in a string should be equal to one of the pre-defined characters and nothing else. First character should be equal to one of the values in first array. Second character should be equal to one of the values in columns array. Third character should be equal to one of the values in rows array. Fourth character should be equal to one of the values in fourth array. I have this code so far.

public static boolean formedGoodOrNot(String input) {
    char[] first = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'};
    int[] columns = {1, 2, 3, 4, 5, 6, 7, 8};
    char[] rows = {'A', 'B', 'C', 'D'};
    int[] fourth = {0, 1, 2, 3, 4, 5, 6, 7};
    if(input.length()==4) {
      for (int j = 0; j < first.length+1; ) {
        for (int k = 0; k < columns.length+1; ) {
          for (int l = 0; l < rows.length+1; ) {
            for (int m = 0; m < fourth.length+1; ) {
              if (input.charAt(0) == first[j]) {
                if (input.charAt(1) == columns[k]) {
                  if (input.charAt(2) == rows[l]) {
                    if (input.charAt(3) == fourth[m]) {
                      return true;
                    } else{
                      m++;
                    }
                  } else {
                    l++;
                  }
                } else{
                  k++;
                }
              } else{
                j++;
              }
            }
          }
        }
      }
    } else{
      return false;
    }
    return false;
  }

However, it gives me an error

java.lang.ArrayIndexOutOfBoundsException: 12

What is wrong here?

Thank you

Joe Smirth
  • 19
  • 1
  • 5
  • P.S. let me know if there is a more efficient way of doing this please – Joe Smirth Aug 25 '18 at 16:17
  • Possible duplicate of [What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?](https://stackoverflow.com/questions/5554734/what-causes-a-java-lang-arrayindexoutofboundsexception-and-how-do-i-prevent-it) – Max Vollmer Aug 25 '18 at 16:21
  • 2
    Welcome to Stack Overflow! Please do not vandalise your post. This may result in a [question ban](http://stackoverflow.com/help/question-bans). By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/)). By SE policy, any vandalism will be reverted. If you would like to disassociate this post from your account, see [What is the proper route for a disassociation request?](https://meta.stackoverflow.com/q/323395) –  Aug 25 '18 at 16:51

4 Answers4

1

All of your index checks should be

< first.length; 

not

< first.length+1; 

etc...

For example, your first array is 0..11 and your are accessing 12.

BTW Welcome to Stack Overflow!

public static boolean formedGoodOrNot(String input) {
    char[] first = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'};
    int[] columns = {1, 2, 3, 4, 5, 6, 7, 8};
    char[] rows = {'A', 'B', 'C', 'D'};
    int[] fourth = {0, 1, 2, 3, 4, 5, 6, 7};
    if(input.length()==4) {
      for (int j = 0; j < first.length; ) {
        for (int k = 0; k < columns.length; ) {
          for (int l = 0; l < rows.length; ) {
            for (int m = 0; m < fourth.length; ) {
              if (input.charAt(0) == first[j]) {
                if (input.charAt(1) == columns[k]) {
                  if (input.charAt(2) == rows[l]) {
                    if (input.charAt(3) == fourth[m]) {
                      return true;
                    } else{
                      m++;
                    }
                  } else {
                    l++;
                  }
                } else{
                  k++;
                }
              } else{
                j++;
              }
            }
          }
        }
      }
    } else{
      return false;
    }
    return false;
  }
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
1

REGEX

You should use regex for this purpose! The regex matching this pattern is :

^[a-l][1-8][A-D][0-7]$

Now you just gotta plug this into a function :

 private static final Pattern PATTERN = Pattern.compile("^[a-l][1-8][A-D][0-7]$");
  

 public boolean formedGoodOrNot(String input) {
     return PATTERN.matcher(input).matches();
 }

and there you go, much more readable and short than your implementation!

Edit

To understand how this regex works, please check out this link that explains it : https://regex101.com/r/SDlnzi/1/

Community
  • 1
  • 1
Louis-wht
  • 535
  • 5
  • 17
  • This does not answer the OP question of 'what is wrong here?'. Nice idea though. – Steven Spungin Aug 25 '18 at 16:51
  • @StevenSpungin yes it does, he added this as a comment after his question : "P.S. let me know if there is a more efficient way of doing this please". This is a more effcient way of doing this ;) – Louis-wht Aug 25 '18 at 17:42
  • OP should have been directed to ask another question. – Steven Spungin Aug 25 '18 at 17:50
  • So generally speaking, it means that if OP asks 2 questions in a single question, only the first one should be answered? (Sorry for being a newbie on stackoverflow :) ) – Louis-wht Aug 25 '18 at 17:52
  • Yes. Generally only 1 question per post is the rule. https://meta.stackexchange.com/questions/222735/can-i-ask-only-one-question-per-post – Steven Spungin Aug 25 '18 at 17:55
1

Since your question is What is wrong here?, let's have a look:

  1. Your loops are nested before you check each character, causing unnecessary checks. Hint: You don't need to enter the loops for the 2nd, 3rd or 4th character when the 1st isn't valid.

  2. Two of those arrays contain ints, not chars, yet you simply compare the chars in the String with the int values, which doesn't work.

  3. You compare your counters with length+1 instead of length, thus going out of bounds. (The length of those arrays isn't length+1, it's length.)

  4. You have an infinite loop for any invalid String that starts with at least one valid character, as you only increment the counter in the else branch, but have no break/return condition for a partially invalid String.

Max Vollmer
  • 8,412
  • 9
  • 28
  • 43
1

You've used nested for loops which is not necessary for your problem. And also array.length + 1 is causing the exception to throw. It should be array.length.

        char[] first = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'};
        int[] columns = {1, 2, 3, 4, 5, 6, 7, 8};
        char[] rows = {'A', 'B', 'C', 'D'};
        int[] fourth = {0, 1, 2, 3, 4, 5, 6, 7};

        boolean firstTest;
        boolean columnTest;
        boolean rowsTest;
        boolean fourthTest;

        if(input.length()==4) {
          for (int j = 0; j < first.length; j++){
               if (input.charAt(0) == first[j]){
                   firstTest = true;
                   break;
               }
           }
           if(!firstTest)
                 return false;

           for (int j = 0; j < columns.length; j++){
               if (input.charAt(0) == columns[j]){
                   columnsTest= true;
                   break;
               }
           }

           if(!columnTest)
                 return false;

          // Do the same for other tests as well


          // if all tests are passed
          return true;
}

If you want a quicker method, you can use a Hashset and save the time for looping.

Set<Character> first= new HashSet<>(Arrays.asList('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'));

Set<Integer> columns= new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8));

// create other sets

if(first.contains(input.charAt(0)) && columns.contains(input.charAt(1)) && /*other similar checks*/)
    return true;
return false;
pahan
  • 567
  • 1
  • 8
  • 22