0

I have a Scrabble Clock with a verification tool inside. The verification word space looks in green or red if the word that I check is in the list.

The thing is, if I use sbuffer.toString().contains, and write a word like ABA, the word space looks in green though ABA is not in the list, but ABAC, ABACA are in the list.

I would like to know how I can implement a condition in my code to check the exact complete word.

I've researched regex, boundary and matches, but I couldn't find a line code that words in my code.

Here is my code until now.

public class MainActivity extends AppCompatActivity {

    TextView textView;
    TextView textInV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.texto_1);
        textView.setMovementMethod(new ScrollingMovementMethod());
        textInV = findViewById(R.id.textIn);

        String data = "";
        StringBuffer sbuffer = new StringBuffer();

        InputStream is = this.getResources().openRawResource(R.raw.fruits);

        BufferedReader reader = new BufferedReader((new InputStreamReader(is)));

        if (is != null)
        {
            try
            {
                while((data =reader.readLine())!=null)
                {
                    sbuffer.append((data + "\n"));
                }

                is.close();

            }
            catch (Exception e){ e.printStackTrace();}
        }

        textView.setText(sbuffer);
    }
}
Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
ddaudiosolutions
  • 131
  • 2
  • 15

4 Answers4

2

The contains method on a string tests whether the target is contained as a substring; if ABAC is contained as a substring then so is ABA, since ABA is a substring of ABAC and hence it is also a substring of any string which ABAC is a substring of. Therefore, it is not logically possible for the String.contains method to return true for ABAC and false for ABA.

You want to test if the target is one of the elements of a collection of strings, so you should use contains on a collection of strings, not on a string. The best choice is a HashSet, since this performs membership tests in O(1) time on average.

> import java.util.*;
> Set<String> allowed = new HashSet<>();
> allowed.add("ABAC");
> allowed.add("ABACA");
> allowed.contains("ABA")
false
> allowed.contains("ABAC")
true
kaya3
  • 47,440
  • 4
  • 68
  • 97
  • There are ~171,000 words in the English language, so while it's definitely a good idea to use a data structure with O(1) access, it's not strictly necessary here. – otoomey Dec 14 '19 at 17:39
  • That depends how many words you want to check. If you're writing a Scrabble AI which tries to maximise its score by trying many possible options, then O(*n*) membership tests will probably not be good enough. But regardless of time complexity, the point is that substring containment is logically the wrong thing to check for. – kaya3 Dec 14 '19 at 17:42
  • To play devils advocate, if you wanted the best performance while searching (as an AI might do), it would make more sense to use a tree structure, where each branch is the next letter in a word. – otoomey Dec 14 '19 at 18:31
  • Yes in a Scrabble check words, there are thousands of words. So...how can i input a .txt ina hashset to check the word...? – ddaudiosolutions Dec 22 '19 at 08:59
  • You open the file, read the words, and insert each word into the HashSet instead of writing them to a StringBuffer. Even if you have 200,000 words, it will still only take a few megabytes of memory. – kaya3 Dec 22 '19 at 09:38
0

StringBuffer's contains() check if the given string is a substring of the text in the sbuffer. That means, it will output true for searching "ABC" in "ABC", "ABCBC", "ZABC", "ZABCBC"...

If you want to search for a complete word in the sbuffer, then you can look for "\n" + "ABC" + "\n" since you're adding "\n" when adding words to sbuffer: sbuffer.append((data + "\n"));. But, you must also initialize sbuffer with "\n": StringBuffer sbuffer = new StringBuffer("\n");.

sbuffer.toString().contains("\n" + "ABC" + "\n"); // this will do the trick

Test code:

class Main {
  public static void main(String[] args) {
    StringBuffer sbuffer = new StringBuffer("\n");
    StringBuffer sbuffer2 = new StringBuffer("\n");

    sbuffer.append("ABC" + "\n");
    sbuffer.append("ABCBC" + "\n");
    sbuffer.append("ZABC" + "\n");
    sbuffer.append("ZABCBC" + "\n");

    System.out.println("Is ABC in sbuffer = " + sbuffer.toString().contains("\n" + "ABC" + "\n"));

    sbuffer2.append("ABCBC" + "\n");
    sbuffer2.append("ZABC" + "\n");
    sbuffer2.append("ZABCBC" + "\n");

    System.out.println("Is ABC in sbuffer2 = " + sbuffer2.toString().contains("\n" + "ABC" + "\n"));
  }
}

Test output:

Is ABC in sbuffer = true
Is ABC in sbuffer2 = false
IamAshKS
  • 749
  • 4
  • 14
  • This way, works, but only with the first word of the list. – ddaudiosolutions Dec 22 '19 at 09:01
  • @ddaudiosolutions It works for every word - if it's first, in the middle, or the last word in the list. Are you following my example correctly? That is, adding "\n" to StringBuffer on initialization, adding "\n" with every insert, and checking for "\n" + WORD + "\n". I just tested it: https://repl.it/repls/FluidCraftyCells – IamAshKS Dec 26 '19 at 13:39
0

As @Ashutosh KS has already mentioned, String.contains is not really what you are looking for in this case: You want to check if two strings are identical, not if one contains the other.

The Java String class contains a few methods that you can use to compare the content of two strings, of which you can choose accordingly to match your exact use case:

  1. contentEquals(CharSequence cs) and contentEquals(StringBuffer sb) both check if the passed string representation's content matches the current one.
  2. equals(Object str) is similar to contentEquals in that it makes an exact comparison between both strings, however it also checks to make sure that the passed object is in fact a string.
  3. equalsIgnoreCase(String anotherString), as the name implies, will do a check while ignoring the string case.

These are the 'proper' ways to compare two strings exposed by the native API, so while it is absolutely possible to use other methods, it is a good idea to stick to these.

otoomey
  • 939
  • 1
  • 14
  • 31
0

Now i have this, and works, but i have a file with the words, and i would like to add the files in the diccionario.

But i don't know how to read the file. I have try bufferread, but i need try/catch, and not works....

Some other solutions....

Thanks

boton2.setOnClickListener(new View.OnClickListener()
        {

           String content;
           @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
           @Override
            public void onClick(View view)
            {
                HashSet<String> diccionario = new HashSet<String>();
                //Adding elements to HashSet
                diccionario.add("CASA");
                diccionario.add("ABAC");

                if(diccionario.contains(textIn.getText().toString().toUpperCase()))
                {
                    textIn.setBackgroundColor(Color.GREEN);
                }
                else
                {
                    textIn.setBackgroundColor(Color.RED);
                }

            }
ddaudiosolutions
  • 131
  • 2
  • 15