Happy
Happy

Reputation: 169

Need Help in java android application

I am trying to generate 5 letters word from random letters. Everything works fine but when I click my button to generate words it takes near about 2 minutes to generate those words and for those 2 minutes my button remains tapped(In blue color), which doesn't look good. I thought to put processing ring but that also doesn't work. Below is some coding for my method

String finalWrd = searchWrd.toUpperCase();
        String twoLetterString = "";
        int wordLen = searchWrd.length();//searchWrd is a random letter entered by user
        String[] array = finalWrd.split("");    
        for(int i =1; i<=wordLen; i++)
            for(int j=1; j<=wordLen; j++)
                for(int K=1; K<=wordLen; K++)
                    for(int l=1; l<=wordLen; l++){
                        for(int m=1; m<=wordLen; m++){
                            twoLetterString += array[i] + array[j]+ array[K]+ array[l] + array[m] +",";
                        }

                    }

String[] array2Letters = twoLetterString.split(",");




    int a =array2Letters.length, b = dictLinesArray.length;

    for(int i =0;i<a; i++)
    { 

        for(int l=0;l<b;l++)
        {
            if(array2Letters[i].equals(dictLinesArray[l]))
            {
                dictString2Lettes += dictLinesArray[l] +"," ;
            } 
        }
    }


    text = dictString2Lettes;

Please help me, I need it for my college project. Thanks in advance

Upvotes: 2

Views: 130

Answers (4)

Sanchit
Sanchit

Reputation: 2260

I'll attempt to offer you a decent solution to improve the performance of your algorithm. Use @Seraphim 's (or similar) answers to improve your user friendliness.

Fix your dictionary data structure.

1) Make your dictionary a Map<String,ArrayList<String>>.

2) Add words in your dictionary like such:

String[] oldDictionary = {"using","suing","apple","orange"};
HashMap<String, ArrayList<String>> map = new HashMap<>();
for (int i = 0; i < oldDictionary.length; i++) {
  char[] sort = oldDictionary[i].toCharArray();
  Arrays.sort(sort);
  String alphabetical = new String(sort);
  if (map.containsKey(alphabetical)) {
    map.get(alphabetical).add(oldDictionary[i]);
  } else {
    ArrayList<String> tmp = new ArrayList<>();
    tmp.add(oldDictionary[i]);
    map.put(alphabetical, tmp);
  }
}

You can now use this new and improved data structure to find words super easily.

String inputWord = "iusgn";
char[] sort = inputWord.toCharArray();
Arrays.sort(sort);
inputWord = new String(sort);

if (map.containsKey(inputWord)) {
  StringBuilder sb = new StringBuilder();
  for (String word : map.get(inputWord)) {
    sb.append(word + ",");
  }
  sb.deleteCharAt(sb.length() - 1);
  System.out.println(sb.toString());
} else {
  System.out.println("Nothing found :(");
}

Upvotes: 2

BobTheBuilder
BobTheBuilder

Reputation: 19284

I guess what takes you the most time is the second loop (because dictLinesArray is big)

Try to change dictLinesArray to Set and use contains. The dictLinesSet initialization should be done only once (at some init function).

Set<String> dictLinesSet = new HashSet<String>(Arrays.asList(dictLinesArray));


for(int i =0;i<a; i++){
    if (dictLinesSet.contains(array2Letters[i])){
         dictString2Lettes += array2Letters[i] +"," ;
    }
}

Upvotes: 0

Lucullan
Lucullan

Reputation: 1

Some thoughts, I hope they help.

In your construction you are actually doing some less-than-optimal data management. Since the strings are immutable, for each time you go through the inner most loop (which is wordLen^5 iterations) you are creating 6 total String objects (right of the = sign), and making a seventh (left of the = sign). Strings are immutable in Java, and memory is a bigger concern in mobile apps than in laptop/desktop development. So for a word length of 5 you are creating 21,875 Objects. For a wordLen of 8 you are creating 229,376 Objects, and it only gets worse.

Better is to use a StringBuilder and store the value after you're done:

You would also want to make the twoLetterString a string builder from the get go.

StringBuilder twoLetterStringBuilder = new StringBuilder();
//inside the loop
    twoLetterStringBuilder.append(array[i]).append(array[j]). ... .append(",");

At the end, just use

twoLetterStringBuilder.toString().split(",");

AsyncTask will keep things from locking up, but this should help you be much more efficient with your creation of objects and overall processing time.

Is the reason for all of the for loops some necessity to have an array of all possible permutations? If not just use:

Random r = new Random();
int arrayIndex = r.nextInt(wordLen);

Upvotes: 0

Seraphim&#39;s
Seraphim&#39;s

Reputation: 12768

I'll not comment the inefficency of your algorithm (try to find something better! :)). I'll simply give a solution for the UI that looks freezed:

"my button remains tapped(In blue color), which doesn't look good"

When your computation need time to be done, you need something like AsyncTask:

http://developer.android.com/reference/android/os/AsyncTask.html

Suppose you are in your activity named MyActivity:

public class MyActivity extends BaseActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main_menu);

        Button btn = (Button)findViewById(R.id.button);
    btn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            //execute async task
            new FindWordsTask().execute();              
        }
    });
}

Than you set up you AsyncTask like that:

private class FindWordsTask extends AsyncTask<Void, Void, Void> {

    ProgressDialog progressDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = ProgressDialog.show(MyActivity.this,
                "Title",
                "Finding words...", true);
    }

    @Override
    protected Void doInBackground(Void... params) {

        //do the computation,
        //use here your function

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        progressDialog.dismiss();
    }
}

Upvotes: 1

Related Questions