0

This is my first time posting here, so please tell me if I need to correct anything in this post. I'd like to ask for help with something that's been giving me some trouble. I need to check that the characters of one string appear in another string, but they need to be detected only once. For example, for the string "BFEABLDEG", "LABEL" should not return true, as it currently is doing.

For clarification, the aim is not to have the program count characters. It is to have the program check that the letters needed to create a word are contained in randomString, with the exact same number of each letter in both Strings. The program is partly based on the game show Countdown.

This is what I have so far. Any help would be greatly appreciated.

Edit: Thanks to everyone who helped me out with this. I've accepted Aru's contribution as the solution I was looking for as it avoids the problem I was having most accurately, given that the size of the string that needs to be checked.

public static boolean Checkword(){
String randomString = "BFEABLDEG";
 String word = "LABEL";
 {
 for(int i=0;i<word.length(); i++){
      if(randomString.contains(word.substring((i)))){
          return true;

      }
 }
return false;
 }

}

Ok, the solution I was given works for basic examples. However, the end goal was for the user to make words of any length from a string of nine random characters. Currently they can do this by putting in more occurences of any character than there are in the string. I was wondering if anyone could help me with this, given the new code that the function has been added to.

    public static boolean Checkword(String x){
    String randomString = convertToString();
     String word = x;
     {
     for(int i=0;i<word.length(); i++){
          if(randomString.indexOf(word.charAt(i)) == -1){
              return false;

          }
     }
    return true;
     }
}
user3424512
  • 13
  • 1
  • 4
  • Hey, does the letter 'L' have to appear twice in the `randomString` because there's two 'L' in `"LABEL"`? – oschlueter Mar 16 '14 at 00:10
  • `boolean`... Java? You should tag what language you are working in. – crashmstr Mar 16 '14 at 00:12
  • No. The purpose of my question is to ensure that the word "label" would return false. Currently it's returning true. – user3424512 Mar 16 '14 at 00:13
  • So it is returning `true` or is it returning `false`..? – ylun.ca Mar 16 '14 at 00:20
  • I think you need to use something like this http://stackoverflow.com/a/1816989/2591612 – Engineer2021 Mar 16 '14 at 00:22
  • It's currently returning true, but it shouldn't. The letter l is in "label" twice, but only once in randomString. My aim is to return false in this situation. – user3424512 Mar 16 '14 at 00:22
  • Or do this, just choose your haystack and needle. Once you have decided, pass the char from one string into the function to look in the haystack. Simple. http://stackoverflow.com/a/276218/2591612 – Engineer2021 Mar 16 '14 at 00:27
  • possible duplicate of [How do I count the number of occurrences of a char in a String?](http://stackoverflow.com/questions/275944/how-do-i-count-the-number-of-occurrences-of-a-char-in-a-string) – Engineer2021 Mar 16 '14 at 00:27
  • I was looking for something a little different. I'm looking to make this react to unique appearances of a character rather than relying on another method if possible. But, I will try to integrate these methods into my function. – user3424512 Mar 16 '14 at 00:31
  • What do you mean? Methods are cheap. – Engineer2021 Mar 16 '14 at 00:32
  • Yeah, you're right. I meant more in terms of, for example, changing the true and false conditions to only react to the unique occurrences of a character, in order to avoid false duplicates in randomString, which are effectively being detected now. – user3424512 Mar 16 '14 at 00:36
  • If you do the way I showed you, all you have to do is see if you get anything greater or less than 1 – Engineer2021 Mar 16 '14 at 00:41
  • Ok, I appreciate the help. When I have the chance, I'll implement those fixes and post up here with the results. – user3424512 Mar 16 '14 at 00:45
  • you could put the two string into character arrays, and do a sorting of the randomString in the array to put the word in the front as you work through the two strings, this way you avoid getting a false positive becuase you have moved the 'L' in this case to the beginning of the array. hope that made sense. – mig Mar 16 '14 at 01:05

3 Answers3

5

I'm not sure if I entirely understand what you're trying to achive, but the whole logic of your method is flawed.

One problem is, obviously, that your function will return true if just the last character matches, since substring(word.length() - 1) will check whether the last character is contained in the other string. In every other loop, you are checking whether an entire sequence is contained, starting with the entire string and reducing the amount of characters every loop.

Even if you add characters to word that are not in randomString, the function will return true as long as they are not at the end of the string.

Something like this should be what you were looking for originally:

public static boolean checkWord() {
    String randomString = "BFEABLDEG";
    String word = "LABEL";
    for (int i = 0; i < word.length(); i++) {
        if (randomString.indexOf(word.charAt(i)) == -1) {
            return false;
        }
    }
    return true;
}

A simple solution to also check for duplicated characters is to remove one occurrence of the character in the string. There are certainly more efficient solutions possible, make sure to check the thread linked in the comments.

public static void main(String[] args) throws Exception {
    System.out.println(test("BFEABLDEG", "LABEL"));
}

public static boolean test(String searchIn, String searchFor) {
    for (char c : searchFor.toCharArray()) {
        if (searchIn.indexOf(c) == -1) {
            return false;
        }
        searchIn = searchIn.replaceFirst(Character.toString(c), "");
    }
    return true;
}
Steffen
  • 3,999
  • 1
  • 23
  • 30
  • Yes, I think that's it. If that would return False with "Label", but True for "bale", for example, then that would work as I wanted it to. – user3424512 Mar 16 '14 at 01:06
  • I added one possible solution that would solve the problem of duplicated occurrences. This will create a lot of new string though, so if you're working with large strings, you should think of another solution. – Steffen Mar 16 '14 at 01:09
  • That's no problem. The strings are no longer than 9 characters long, but I will take any necessary steps to make it fit my needs otherwise, of course. – user3424512 Mar 16 '14 at 01:11
  • Unfortunately, adding this version of the method to the overall program that this was intended to be a test for throws up the same problem as before. I'm not sure entirely where I'm going wrong. – user3424512 Mar 16 '14 at 12:01
  • Which version? The first? The first will still return true for "LABEL" (because I've just corrected the general flaws of your attempt). The second, however, won't. – Steffen Mar 16 '14 at 15:13
  • Ah, I was implementing the first version instead. Would you mind showing me how I could implement the second version in the second block of code I have posted in the question? – user3424512 Mar 16 '14 at 15:32
  • You can use it exactly the way I've done it in my main. The first argument is the string that you want to search something in (e.g. "BFEABLDEG") and the second argument are the characters you're looking for ("LABEL"). So, something like `boolean contains = test(convertToString(), x);`. – Steffen Mar 16 '14 at 15:35
1

It is returning true because your testing one char of randomString

public static boolean Checkword( String pattern, String randomString ){
  return ( randomString .contains( pattern ) ) ? true : false;
}

String pattern = "LABEL";

String randomString = "BFEABLDEG";
Checkword( pattern, randomString );
//return false

randomString = "AZDAZLABELIIDZA";
Checkword( pattern, randomString );
//return true
Dimitri
  • 304
  • 3
  • 16
  • `return ( randomString .contains( pattern ) ) ? true : false;` is pretty pointless. You could just write `return randomString.contains(pattern)`. And why would you invent a new method that does nothing besides wrapping another method? – Steffen Mar 16 '14 at 00:57
  • Yes it's pointless, it was for the example, I 'll probably didn't understand what he is trying to achieve – Dimitri Mar 16 '14 at 00:58
1

Your program as it is is returning true if any character in your word variable is contained in your randomString variable. Judging from your comments it sounds like you want to check if every character from your word string is contained within your randomString variable. Here is a slightly different approach.

public static boolean Checkword(){
    String randomString = "BFEABLDEG";
    String word = "LABEL";
    for(int i=0;i<word.length(); i++){
         if(randomString.indexOf(word.charAt(i)) != -1){
             //If the letter isn't contained return false
             return false;
          } else {
              //If the letter is contained remove it from the string
              int charLocation = randomString.indexOf(word.charAt(i));
              randomString = randomString.substring(0, charLocation) + randomString.substring(charLocation+1);
          }
    }
    //If I haven't returned yet, then every letter is contained, return true
    return true;
}

This is quite inefficient since it has to create a new string each time, if you want to make it a little better, use a string builder to mutate the string to remove the characters as they are found.

Kevin DiTraglia
  • 25,746
  • 19
  • 92
  • 138
  • You're using `substring()` here as well, which is one of the biggest problems. – Steffen Mar 16 '14 at 01:11
  • Yeah I wasn't going for efficiency here. I like the use of `replaceFirst` in your answer though, wasn't aware that method existed (I'm assuming it has better than 3 string allocations per loop). – Kevin DiTraglia Mar 16 '14 at 01:12
  • Well, that's not the `substring` is was referring to. I meant this one: `randomString.contains(word.substring(i))` This will not check for the occurrence of a single character but for subsequences of the original string. In the first loop cycle, for example, it will check whether the entire string "LABEL" in contained in "BFEABLDEG". – Steffen Mar 16 '14 at 01:15
  • Ah I see what you are saying, changed it to `charAt` – Kevin DiTraglia Mar 16 '14 at 01:19
  • Hi. When I try this, it generates the following error. "The method contains(CharSequence) in the type String is not applicable for the arguments (char)" – user3424512 Mar 16 '14 at 12:25
  • @user3424512 Ah apparently contains can't take a char as a parameter, I tweaked my answer a bit to use `indexOf` instead of contains – Kevin DiTraglia Mar 16 '14 at 16:25
  • @KevinDiTraglia Sorry, but I'm now having a problem where the output will always come out false. The user input is also being compared to a dictionary file, so this might help with understanding what's going wrong. `if((letterRound.Checkword(input3) == true) && (conundrum.dictionary.contains(input3))){ System.out.println("Congratulations, " + input3 + " is a word.");` – user3424512 Mar 16 '14 at 19:45