Given a word, how do I find other words in an array with same length and same characters












1












$begingroup$


I tried solving the problem in the following manner; I am just a beginner and wanted to know my mistakes and a more efficient way with better time complexity (if any).



    public class d3 {
public static void main(String args){
String Search="loop";
String letters = Search.split("") ;
int counter;

String words={"pole","pool","lopo","book","kobo"};

for(int i=0;i<words.length;i++)
{
counter=0;
String ssplit = words[i].split("");
for(int j=0;j<words[i].length();j++)
{

if(letters.length==ssplit.length)
{
for(int k=0;k<letters.length;k++)
{
if(letters[j].equals(ssplit[k]))
{counter++;
ssplit[k]="*";
break;


}



}
if (counter == 4)
{
System.out.println(words[i]);

}

}
}


}

}


}










share|improve this question









New contributor




Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    Hi Aditya. Do you have to use arrays for the words and characters or can you use another structure ?
    $endgroup$
    – gervais.b
    15 hours ago










  • $begingroup$
    @gervais.b I'm currently not too familiar with other data structures. But I'm open to suggestions. Is there a better option than using arrays?
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    @PeterTaylor Thank you for pointing out the bug. I'll try to fix it and update the question as soon as possible.
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    Just for inspiration, here's something to consider, without going into the depth of a full answer. If I understand correctly, your goal is to return all the words from your dictionary that contain the same length and character set as your input word. One approach might be to take your dictionary and for every word sort the characters in alphabetical order. Then generate a one-to-many map of the sorted versions of the words to all the words they can make up. Then, once you possess such a map, perform the same operation on the input word, and you're returning a simple key/value lookup; O(1).
    $endgroup$
    – Nate Gardner
    9 hours ago










  • $begingroup$
    The advantage to such an approach would be that it can process your dictionary offline, offloading the work of testing for your condition and effectively creating a hash index for your search criteria. While generating such a map might take a while, it would only need to be done when the dictionary is modified, while making your performance of searching for these words extremely good, since you can instantly skip to your answer without ever processing any irrelevant words. This approach would make sense if you have a dictionary that stays the same for many inputs.
    $endgroup$
    – Nate Gardner
    9 hours ago
















1












$begingroup$


I tried solving the problem in the following manner; I am just a beginner and wanted to know my mistakes and a more efficient way with better time complexity (if any).



    public class d3 {
public static void main(String args){
String Search="loop";
String letters = Search.split("") ;
int counter;

String words={"pole","pool","lopo","book","kobo"};

for(int i=0;i<words.length;i++)
{
counter=0;
String ssplit = words[i].split("");
for(int j=0;j<words[i].length();j++)
{

if(letters.length==ssplit.length)
{
for(int k=0;k<letters.length;k++)
{
if(letters[j].equals(ssplit[k]))
{counter++;
ssplit[k]="*";
break;


}



}
if (counter == 4)
{
System.out.println(words[i]);

}

}
}


}

}


}










share|improve this question









New contributor




Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    Hi Aditya. Do you have to use arrays for the words and characters or can you use another structure ?
    $endgroup$
    – gervais.b
    15 hours ago










  • $begingroup$
    @gervais.b I'm currently not too familiar with other data structures. But I'm open to suggestions. Is there a better option than using arrays?
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    @PeterTaylor Thank you for pointing out the bug. I'll try to fix it and update the question as soon as possible.
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    Just for inspiration, here's something to consider, without going into the depth of a full answer. If I understand correctly, your goal is to return all the words from your dictionary that contain the same length and character set as your input word. One approach might be to take your dictionary and for every word sort the characters in alphabetical order. Then generate a one-to-many map of the sorted versions of the words to all the words they can make up. Then, once you possess such a map, perform the same operation on the input word, and you're returning a simple key/value lookup; O(1).
    $endgroup$
    – Nate Gardner
    9 hours ago










  • $begingroup$
    The advantage to such an approach would be that it can process your dictionary offline, offloading the work of testing for your condition and effectively creating a hash index for your search criteria. While generating such a map might take a while, it would only need to be done when the dictionary is modified, while making your performance of searching for these words extremely good, since you can instantly skip to your answer without ever processing any irrelevant words. This approach would make sense if you have a dictionary that stays the same for many inputs.
    $endgroup$
    – Nate Gardner
    9 hours ago














1












1








1


1



$begingroup$


I tried solving the problem in the following manner; I am just a beginner and wanted to know my mistakes and a more efficient way with better time complexity (if any).



    public class d3 {
public static void main(String args){
String Search="loop";
String letters = Search.split("") ;
int counter;

String words={"pole","pool","lopo","book","kobo"};

for(int i=0;i<words.length;i++)
{
counter=0;
String ssplit = words[i].split("");
for(int j=0;j<words[i].length();j++)
{

if(letters.length==ssplit.length)
{
for(int k=0;k<letters.length;k++)
{
if(letters[j].equals(ssplit[k]))
{counter++;
ssplit[k]="*";
break;


}



}
if (counter == 4)
{
System.out.println(words[i]);

}

}
}


}

}


}










share|improve this question









New contributor




Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$




I tried solving the problem in the following manner; I am just a beginner and wanted to know my mistakes and a more efficient way with better time complexity (if any).



    public class d3 {
public static void main(String args){
String Search="loop";
String letters = Search.split("") ;
int counter;

String words={"pole","pool","lopo","book","kobo"};

for(int i=0;i<words.length;i++)
{
counter=0;
String ssplit = words[i].split("");
for(int j=0;j<words[i].length();j++)
{

if(letters.length==ssplit.length)
{
for(int k=0;k<letters.length;k++)
{
if(letters[j].equals(ssplit[k]))
{counter++;
ssplit[k]="*";
break;


}



}
if (counter == 4)
{
System.out.println(words[i]);

}

}
}


}

}


}







java






share|improve this question









New contributor




Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 11 hours ago







Aditya













New contributor




Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 16 hours ago









AdityaAditya

62




62




New contributor




Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Aditya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • $begingroup$
    Hi Aditya. Do you have to use arrays for the words and characters or can you use another structure ?
    $endgroup$
    – gervais.b
    15 hours ago










  • $begingroup$
    @gervais.b I'm currently not too familiar with other data structures. But I'm open to suggestions. Is there a better option than using arrays?
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    @PeterTaylor Thank you for pointing out the bug. I'll try to fix it and update the question as soon as possible.
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    Just for inspiration, here's something to consider, without going into the depth of a full answer. If I understand correctly, your goal is to return all the words from your dictionary that contain the same length and character set as your input word. One approach might be to take your dictionary and for every word sort the characters in alphabetical order. Then generate a one-to-many map of the sorted versions of the words to all the words they can make up. Then, once you possess such a map, perform the same operation on the input word, and you're returning a simple key/value lookup; O(1).
    $endgroup$
    – Nate Gardner
    9 hours ago










  • $begingroup$
    The advantage to such an approach would be that it can process your dictionary offline, offloading the work of testing for your condition and effectively creating a hash index for your search criteria. While generating such a map might take a while, it would only need to be done when the dictionary is modified, while making your performance of searching for these words extremely good, since you can instantly skip to your answer without ever processing any irrelevant words. This approach would make sense if you have a dictionary that stays the same for many inputs.
    $endgroup$
    – Nate Gardner
    9 hours ago


















  • $begingroup$
    Hi Aditya. Do you have to use arrays for the words and characters or can you use another structure ?
    $endgroup$
    – gervais.b
    15 hours ago










  • $begingroup$
    @gervais.b I'm currently not too familiar with other data structures. But I'm open to suggestions. Is there a better option than using arrays?
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    @PeterTaylor Thank you for pointing out the bug. I'll try to fix it and update the question as soon as possible.
    $endgroup$
    – Aditya
    12 hours ago










  • $begingroup$
    Just for inspiration, here's something to consider, without going into the depth of a full answer. If I understand correctly, your goal is to return all the words from your dictionary that contain the same length and character set as your input word. One approach might be to take your dictionary and for every word sort the characters in alphabetical order. Then generate a one-to-many map of the sorted versions of the words to all the words they can make up. Then, once you possess such a map, perform the same operation on the input word, and you're returning a simple key/value lookup; O(1).
    $endgroup$
    – Nate Gardner
    9 hours ago










  • $begingroup$
    The advantage to such an approach would be that it can process your dictionary offline, offloading the work of testing for your condition and effectively creating a hash index for your search criteria. While generating such a map might take a while, it would only need to be done when the dictionary is modified, while making your performance of searching for these words extremely good, since you can instantly skip to your answer without ever processing any irrelevant words. This approach would make sense if you have a dictionary that stays the same for many inputs.
    $endgroup$
    – Nate Gardner
    9 hours ago
















$begingroup$
Hi Aditya. Do you have to use arrays for the words and characters or can you use another structure ?
$endgroup$
– gervais.b
15 hours ago




$begingroup$
Hi Aditya. Do you have to use arrays for the words and characters or can you use another structure ?
$endgroup$
– gervais.b
15 hours ago












$begingroup$
@gervais.b I'm currently not too familiar with other data structures. But I'm open to suggestions. Is there a better option than using arrays?
$endgroup$
– Aditya
12 hours ago




$begingroup$
@gervais.b I'm currently not too familiar with other data structures. But I'm open to suggestions. Is there a better option than using arrays?
$endgroup$
– Aditya
12 hours ago












$begingroup$
@PeterTaylor Thank you for pointing out the bug. I'll try to fix it and update the question as soon as possible.
$endgroup$
– Aditya
12 hours ago




$begingroup$
@PeterTaylor Thank you for pointing out the bug. I'll try to fix it and update the question as soon as possible.
$endgroup$
– Aditya
12 hours ago












$begingroup$
Just for inspiration, here's something to consider, without going into the depth of a full answer. If I understand correctly, your goal is to return all the words from your dictionary that contain the same length and character set as your input word. One approach might be to take your dictionary and for every word sort the characters in alphabetical order. Then generate a one-to-many map of the sorted versions of the words to all the words they can make up. Then, once you possess such a map, perform the same operation on the input word, and you're returning a simple key/value lookup; O(1).
$endgroup$
– Nate Gardner
9 hours ago




$begingroup$
Just for inspiration, here's something to consider, without going into the depth of a full answer. If I understand correctly, your goal is to return all the words from your dictionary that contain the same length and character set as your input word. One approach might be to take your dictionary and for every word sort the characters in alphabetical order. Then generate a one-to-many map of the sorted versions of the words to all the words they can make up. Then, once you possess such a map, perform the same operation on the input word, and you're returning a simple key/value lookup; O(1).
$endgroup$
– Nate Gardner
9 hours ago












$begingroup$
The advantage to such an approach would be that it can process your dictionary offline, offloading the work of testing for your condition and effectively creating a hash index for your search criteria. While generating such a map might take a while, it would only need to be done when the dictionary is modified, while making your performance of searching for these words extremely good, since you can instantly skip to your answer without ever processing any irrelevant words. This approach would make sense if you have a dictionary that stays the same for many inputs.
$endgroup$
– Nate Gardner
9 hours ago




$begingroup$
The advantage to such an approach would be that it can process your dictionary offline, offloading the work of testing for your condition and effectively creating a hash index for your search criteria. While generating such a map might take a while, it would only need to be done when the dictionary is modified, while making your performance of searching for these words extremely good, since you can instantly skip to your answer without ever processing any irrelevant words. This approach would make sense if you have a dictionary that stays the same for many inputs.
$endgroup$
– Nate Gardner
9 hours ago










2 Answers
2






active

oldest

votes


















0












$begingroup$

Whitespace is very important for readability. For posting to Stack Exchange sites I recommend replacing tabs with spaces, because otherwise the site does that for you and the tabstops might not match. Here, though, the whitespace is so crazy that I think you need to look at configuring your IDE to pretty-print the code. Reformatting so that I can understand the structure:




public class d3 {
public static void main(String args){
String Search="loop";
String letters = Search.split("") ;
int counter;

String words={"pole","pool","lopo","book","kobo"};

for(int i=0;i<words.length;i++)
{
counter=0;
String ssplit = words[i].split("");
for(int j=0;j<words[i].length();j++)
{
if(letters.length==ssplit.length)
{
for(int k=0;k<letters.length;k++)
{
if(letters[j].equals(ssplit[k]))
{
counter++;
ssplit[k]="*";
break;
}
}
if (counter == 4)
{
System.out.println(words[i]);
}
}
}
}
}
}





Names



Java convention is that camel-case names which start with a capital letter are types (classes, interfaces, etc), so Search as the name of a variable is unexpected.



counter is not entirely uninformative, but a better name would tell me what it counts. Similarly, it would be helpful to distinguish which variables relate to the search query and which to the items searched. The best convention I've seen there is PHP's needle and haystack, so I would suggest needleLetters and haystackWords.





foreach statement



Instead of for(int i=0;i<words.length;i++) ... words[i] you can use for (String word : words) ... word. This removes a variable and simplifies the naming, making it easier to see what the code does.





Decomposing strings



String has a method toCharArray(). I think it would make more sense to use that than split("").





Don't put something in a loop which can go outside it




            for(int j=0;j<words[i].length();j++)
{
if(letters.length==ssplit.length)
{
...
}
}



could be rewritten



            if(letters.length==ssplit.length)
{
for(int j=0;j<ssplit.length;j++)
{
...
}
}


Executing the test once is more efficient, and it's also easier to understand because the maintainer doesn't have to reason about loop invariants to work out what might have changed the second time the test is executed.



Since there's nothing after this test in the loop body, an alternative would be



            if(letters.length!=ssplit.length)
{
continue;
}

for(int j=0;j<ssplit.length;j++)
{
...
}




Beware hard-coded constants



Why



                    if (counter == 4)
{
System.out.println(words[i]);
}


? That's a bug. The comparison should be with letters.length. Also, it would make more sense to move the test outside the loop over j.





Use advanced data structures




            for(int j=0;j<words[i].length();j++)
{
for(int k=0;k<letters.length;k++)
{
if(letters[j].equals(ssplit[k]))
{
counter++;
ssplit[k]="*";
break;
}
}
}



takes time proportional to words[i].length() * letters.length. If you use java.util.HashMap<Character, Integer> to store a per-character count, you can generate a representation for each word in time proportional to the length of the word, and you can compare the representations of two words in time proportional to the length of each word. In this toy example it doesn't matter, but for real applications the difference between $O(n^2)$ and $O(n)$ can be the difference between a project being feasible and not. The first place to look for optimisations is always the algorithm.






share|improve this answer









$endgroup$





















    -1












    $begingroup$

    welcome on Codereview.



    I am pretty sure that you will find many other ways to do it the comments from @NateGardner is already a good suggestion. But the goal is to review your code so I will just try to suggest some improvements to your code.



    First of all I will just reformat the code, create a dedicated class for it and define the input and output.



    class WordFinder {
    private final String words;
    WordFinder(String words) {
    this.words = new String[words.length];
    System.arraycopy(words, 0, this.words, 0, words.length);
    }
    String find(String word) {
    // Your code here
    }
    }


    Then you can start to split your nested logic in different methods and use exiting methods to simplify your code (like String#toCharArray() instead of String#split(""))



      String find(String word) {
    String result = new String[this.words.length];
    char letters = word.toCharArray();
    int counter = 0;
    for (String candidate : this.words) {
    if ( this.matches(letters, candidate.toCharArray()) ) {
    result[counter++] = candidate;
    }
    }
    return Arrays.copyOf(result, counter);
    }


    As said in the beginning, there is a lot of way to test two words for matching and I am sure that you will find the best one. For this answer, I decided to compare the hash of each array of char.





    Here is my code if you want. But if you can use other structure from the collections or the stream API, this one can be totally different.



    public class WordFinder {

    private final String words;

    public WordFinder(String words) {
    this.words = new String[words.length];
    System.arraycopy(words, 0, this.words, 0, words.length);
    }

    public String find(String word) {
    String result = new String[this.words.length];
    char letters = word.toCharArray();
    int counter = 0;
    for (String candidate : this.words) {
    if ( matches(letters, candidate.toCharArray()) ) {
    result[counter++] = candidate;
    }
    }
    return Arrays.copyOf(result, counter);
    }

    private boolean matches(char requirement, char candidate) {
    return candidate.length==requirement.length &&
    hash(candidate)==hash(requirement);
    }

    private int hash(char array) {
    char copy = Arrays.copyOf(array, array.length);
    Arrays.sort(copy);
    return Arrays.hashCode(copy);
    }
    }





    share|improve this answer









    $endgroup$













    • $begingroup$
      The most significant suggestion of this answer introduces a bug. Comparing hashes is a valid way of showing that two objects are different, but it is not a valid way of showing that they're the same.
      $endgroup$
      – Peter Taylor
      4 hours ago











    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });






    Aditya is a new contributor. Be nice, and check out our Code of Conduct.










    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211538%2fgiven-a-word-how-do-i-find-other-words-in-an-array-with-same-length-and-same-ch%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0












    $begingroup$

    Whitespace is very important for readability. For posting to Stack Exchange sites I recommend replacing tabs with spaces, because otherwise the site does that for you and the tabstops might not match. Here, though, the whitespace is so crazy that I think you need to look at configuring your IDE to pretty-print the code. Reformatting so that I can understand the structure:




    public class d3 {
    public static void main(String args){
    String Search="loop";
    String letters = Search.split("") ;
    int counter;

    String words={"pole","pool","lopo","book","kobo"};

    for(int i=0;i<words.length;i++)
    {
    counter=0;
    String ssplit = words[i].split("");
    for(int j=0;j<words[i].length();j++)
    {
    if(letters.length==ssplit.length)
    {
    for(int k=0;k<letters.length;k++)
    {
    if(letters[j].equals(ssplit[k]))
    {
    counter++;
    ssplit[k]="*";
    break;
    }
    }
    if (counter == 4)
    {
    System.out.println(words[i]);
    }
    }
    }
    }
    }
    }





    Names



    Java convention is that camel-case names which start with a capital letter are types (classes, interfaces, etc), so Search as the name of a variable is unexpected.



    counter is not entirely uninformative, but a better name would tell me what it counts. Similarly, it would be helpful to distinguish which variables relate to the search query and which to the items searched. The best convention I've seen there is PHP's needle and haystack, so I would suggest needleLetters and haystackWords.





    foreach statement



    Instead of for(int i=0;i<words.length;i++) ... words[i] you can use for (String word : words) ... word. This removes a variable and simplifies the naming, making it easier to see what the code does.





    Decomposing strings



    String has a method toCharArray(). I think it would make more sense to use that than split("").





    Don't put something in a loop which can go outside it




                for(int j=0;j<words[i].length();j++)
    {
    if(letters.length==ssplit.length)
    {
    ...
    }
    }



    could be rewritten



                if(letters.length==ssplit.length)
    {
    for(int j=0;j<ssplit.length;j++)
    {
    ...
    }
    }


    Executing the test once is more efficient, and it's also easier to understand because the maintainer doesn't have to reason about loop invariants to work out what might have changed the second time the test is executed.



    Since there's nothing after this test in the loop body, an alternative would be



                if(letters.length!=ssplit.length)
    {
    continue;
    }

    for(int j=0;j<ssplit.length;j++)
    {
    ...
    }




    Beware hard-coded constants



    Why



                        if (counter == 4)
    {
    System.out.println(words[i]);
    }


    ? That's a bug. The comparison should be with letters.length. Also, it would make more sense to move the test outside the loop over j.





    Use advanced data structures




                for(int j=0;j<words[i].length();j++)
    {
    for(int k=0;k<letters.length;k++)
    {
    if(letters[j].equals(ssplit[k]))
    {
    counter++;
    ssplit[k]="*";
    break;
    }
    }
    }



    takes time proportional to words[i].length() * letters.length. If you use java.util.HashMap<Character, Integer> to store a per-character count, you can generate a representation for each word in time proportional to the length of the word, and you can compare the representations of two words in time proportional to the length of each word. In this toy example it doesn't matter, but for real applications the difference between $O(n^2)$ and $O(n)$ can be the difference between a project being feasible and not. The first place to look for optimisations is always the algorithm.






    share|improve this answer









    $endgroup$


















      0












      $begingroup$

      Whitespace is very important for readability. For posting to Stack Exchange sites I recommend replacing tabs with spaces, because otherwise the site does that for you and the tabstops might not match. Here, though, the whitespace is so crazy that I think you need to look at configuring your IDE to pretty-print the code. Reformatting so that I can understand the structure:




      public class d3 {
      public static void main(String args){
      String Search="loop";
      String letters = Search.split("") ;
      int counter;

      String words={"pole","pool","lopo","book","kobo"};

      for(int i=0;i<words.length;i++)
      {
      counter=0;
      String ssplit = words[i].split("");
      for(int j=0;j<words[i].length();j++)
      {
      if(letters.length==ssplit.length)
      {
      for(int k=0;k<letters.length;k++)
      {
      if(letters[j].equals(ssplit[k]))
      {
      counter++;
      ssplit[k]="*";
      break;
      }
      }
      if (counter == 4)
      {
      System.out.println(words[i]);
      }
      }
      }
      }
      }
      }





      Names



      Java convention is that camel-case names which start with a capital letter are types (classes, interfaces, etc), so Search as the name of a variable is unexpected.



      counter is not entirely uninformative, but a better name would tell me what it counts. Similarly, it would be helpful to distinguish which variables relate to the search query and which to the items searched. The best convention I've seen there is PHP's needle and haystack, so I would suggest needleLetters and haystackWords.





      foreach statement



      Instead of for(int i=0;i<words.length;i++) ... words[i] you can use for (String word : words) ... word. This removes a variable and simplifies the naming, making it easier to see what the code does.





      Decomposing strings



      String has a method toCharArray(). I think it would make more sense to use that than split("").





      Don't put something in a loop which can go outside it




                  for(int j=0;j<words[i].length();j++)
      {
      if(letters.length==ssplit.length)
      {
      ...
      }
      }



      could be rewritten



                  if(letters.length==ssplit.length)
      {
      for(int j=0;j<ssplit.length;j++)
      {
      ...
      }
      }


      Executing the test once is more efficient, and it's also easier to understand because the maintainer doesn't have to reason about loop invariants to work out what might have changed the second time the test is executed.



      Since there's nothing after this test in the loop body, an alternative would be



                  if(letters.length!=ssplit.length)
      {
      continue;
      }

      for(int j=0;j<ssplit.length;j++)
      {
      ...
      }




      Beware hard-coded constants



      Why



                          if (counter == 4)
      {
      System.out.println(words[i]);
      }


      ? That's a bug. The comparison should be with letters.length. Also, it would make more sense to move the test outside the loop over j.





      Use advanced data structures




                  for(int j=0;j<words[i].length();j++)
      {
      for(int k=0;k<letters.length;k++)
      {
      if(letters[j].equals(ssplit[k]))
      {
      counter++;
      ssplit[k]="*";
      break;
      }
      }
      }



      takes time proportional to words[i].length() * letters.length. If you use java.util.HashMap<Character, Integer> to store a per-character count, you can generate a representation for each word in time proportional to the length of the word, and you can compare the representations of two words in time proportional to the length of each word. In this toy example it doesn't matter, but for real applications the difference between $O(n^2)$ and $O(n)$ can be the difference between a project being feasible and not. The first place to look for optimisations is always the algorithm.






      share|improve this answer









      $endgroup$
















        0












        0








        0





        $begingroup$

        Whitespace is very important for readability. For posting to Stack Exchange sites I recommend replacing tabs with spaces, because otherwise the site does that for you and the tabstops might not match. Here, though, the whitespace is so crazy that I think you need to look at configuring your IDE to pretty-print the code. Reformatting so that I can understand the structure:




        public class d3 {
        public static void main(String args){
        String Search="loop";
        String letters = Search.split("") ;
        int counter;

        String words={"pole","pool","lopo","book","kobo"};

        for(int i=0;i<words.length;i++)
        {
        counter=0;
        String ssplit = words[i].split("");
        for(int j=0;j<words[i].length();j++)
        {
        if(letters.length==ssplit.length)
        {
        for(int k=0;k<letters.length;k++)
        {
        if(letters[j].equals(ssplit[k]))
        {
        counter++;
        ssplit[k]="*";
        break;
        }
        }
        if (counter == 4)
        {
        System.out.println(words[i]);
        }
        }
        }
        }
        }
        }





        Names



        Java convention is that camel-case names which start with a capital letter are types (classes, interfaces, etc), so Search as the name of a variable is unexpected.



        counter is not entirely uninformative, but a better name would tell me what it counts. Similarly, it would be helpful to distinguish which variables relate to the search query and which to the items searched. The best convention I've seen there is PHP's needle and haystack, so I would suggest needleLetters and haystackWords.





        foreach statement



        Instead of for(int i=0;i<words.length;i++) ... words[i] you can use for (String word : words) ... word. This removes a variable and simplifies the naming, making it easier to see what the code does.





        Decomposing strings



        String has a method toCharArray(). I think it would make more sense to use that than split("").





        Don't put something in a loop which can go outside it




                    for(int j=0;j<words[i].length();j++)
        {
        if(letters.length==ssplit.length)
        {
        ...
        }
        }



        could be rewritten



                    if(letters.length==ssplit.length)
        {
        for(int j=0;j<ssplit.length;j++)
        {
        ...
        }
        }


        Executing the test once is more efficient, and it's also easier to understand because the maintainer doesn't have to reason about loop invariants to work out what might have changed the second time the test is executed.



        Since there's nothing after this test in the loop body, an alternative would be



                    if(letters.length!=ssplit.length)
        {
        continue;
        }

        for(int j=0;j<ssplit.length;j++)
        {
        ...
        }




        Beware hard-coded constants



        Why



                            if (counter == 4)
        {
        System.out.println(words[i]);
        }


        ? That's a bug. The comparison should be with letters.length. Also, it would make more sense to move the test outside the loop over j.





        Use advanced data structures




                    for(int j=0;j<words[i].length();j++)
        {
        for(int k=0;k<letters.length;k++)
        {
        if(letters[j].equals(ssplit[k]))
        {
        counter++;
        ssplit[k]="*";
        break;
        }
        }
        }



        takes time proportional to words[i].length() * letters.length. If you use java.util.HashMap<Character, Integer> to store a per-character count, you can generate a representation for each word in time proportional to the length of the word, and you can compare the representations of two words in time proportional to the length of each word. In this toy example it doesn't matter, but for real applications the difference between $O(n^2)$ and $O(n)$ can be the difference between a project being feasible and not. The first place to look for optimisations is always the algorithm.






        share|improve this answer









        $endgroup$



        Whitespace is very important for readability. For posting to Stack Exchange sites I recommend replacing tabs with spaces, because otherwise the site does that for you and the tabstops might not match. Here, though, the whitespace is so crazy that I think you need to look at configuring your IDE to pretty-print the code. Reformatting so that I can understand the structure:




        public class d3 {
        public static void main(String args){
        String Search="loop";
        String letters = Search.split("") ;
        int counter;

        String words={"pole","pool","lopo","book","kobo"};

        for(int i=0;i<words.length;i++)
        {
        counter=0;
        String ssplit = words[i].split("");
        for(int j=0;j<words[i].length();j++)
        {
        if(letters.length==ssplit.length)
        {
        for(int k=0;k<letters.length;k++)
        {
        if(letters[j].equals(ssplit[k]))
        {
        counter++;
        ssplit[k]="*";
        break;
        }
        }
        if (counter == 4)
        {
        System.out.println(words[i]);
        }
        }
        }
        }
        }
        }





        Names



        Java convention is that camel-case names which start with a capital letter are types (classes, interfaces, etc), so Search as the name of a variable is unexpected.



        counter is not entirely uninformative, but a better name would tell me what it counts. Similarly, it would be helpful to distinguish which variables relate to the search query and which to the items searched. The best convention I've seen there is PHP's needle and haystack, so I would suggest needleLetters and haystackWords.





        foreach statement



        Instead of for(int i=0;i<words.length;i++) ... words[i] you can use for (String word : words) ... word. This removes a variable and simplifies the naming, making it easier to see what the code does.





        Decomposing strings



        String has a method toCharArray(). I think it would make more sense to use that than split("").





        Don't put something in a loop which can go outside it




                    for(int j=0;j<words[i].length();j++)
        {
        if(letters.length==ssplit.length)
        {
        ...
        }
        }



        could be rewritten



                    if(letters.length==ssplit.length)
        {
        for(int j=0;j<ssplit.length;j++)
        {
        ...
        }
        }


        Executing the test once is more efficient, and it's also easier to understand because the maintainer doesn't have to reason about loop invariants to work out what might have changed the second time the test is executed.



        Since there's nothing after this test in the loop body, an alternative would be



                    if(letters.length!=ssplit.length)
        {
        continue;
        }

        for(int j=0;j<ssplit.length;j++)
        {
        ...
        }




        Beware hard-coded constants



        Why



                            if (counter == 4)
        {
        System.out.println(words[i]);
        }


        ? That's a bug. The comparison should be with letters.length. Also, it would make more sense to move the test outside the loop over j.





        Use advanced data structures




                    for(int j=0;j<words[i].length();j++)
        {
        for(int k=0;k<letters.length;k++)
        {
        if(letters[j].equals(ssplit[k]))
        {
        counter++;
        ssplit[k]="*";
        break;
        }
        }
        }



        takes time proportional to words[i].length() * letters.length. If you use java.util.HashMap<Character, Integer> to store a per-character count, you can generate a representation for each word in time proportional to the length of the word, and you can compare the representations of two words in time proportional to the length of each word. In this toy example it doesn't matter, but for real applications the difference between $O(n^2)$ and $O(n)$ can be the difference between a project being feasible and not. The first place to look for optimisations is always the algorithm.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 4 hours ago









        Peter TaylorPeter Taylor

        15.9k2759




        15.9k2759

























            -1












            $begingroup$

            welcome on Codereview.



            I am pretty sure that you will find many other ways to do it the comments from @NateGardner is already a good suggestion. But the goal is to review your code so I will just try to suggest some improvements to your code.



            First of all I will just reformat the code, create a dedicated class for it and define the input and output.



            class WordFinder {
            private final String words;
            WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }
            String find(String word) {
            // Your code here
            }
            }


            Then you can start to split your nested logic in different methods and use exiting methods to simplify your code (like String#toCharArray() instead of String#split(""))



              String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( this.matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }


            As said in the beginning, there is a lot of way to test two words for matching and I am sure that you will find the best one. For this answer, I decided to compare the hash of each array of char.





            Here is my code if you want. But if you can use other structure from the collections or the stream API, this one can be totally different.



            public class WordFinder {

            private final String words;

            public WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }

            public String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }

            private boolean matches(char requirement, char candidate) {
            return candidate.length==requirement.length &&
            hash(candidate)==hash(requirement);
            }

            private int hash(char array) {
            char copy = Arrays.copyOf(array, array.length);
            Arrays.sort(copy);
            return Arrays.hashCode(copy);
            }
            }





            share|improve this answer









            $endgroup$













            • $begingroup$
              The most significant suggestion of this answer introduces a bug. Comparing hashes is a valid way of showing that two objects are different, but it is not a valid way of showing that they're the same.
              $endgroup$
              – Peter Taylor
              4 hours ago
















            -1












            $begingroup$

            welcome on Codereview.



            I am pretty sure that you will find many other ways to do it the comments from @NateGardner is already a good suggestion. But the goal is to review your code so I will just try to suggest some improvements to your code.



            First of all I will just reformat the code, create a dedicated class for it and define the input and output.



            class WordFinder {
            private final String words;
            WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }
            String find(String word) {
            // Your code here
            }
            }


            Then you can start to split your nested logic in different methods and use exiting methods to simplify your code (like String#toCharArray() instead of String#split(""))



              String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( this.matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }


            As said in the beginning, there is a lot of way to test two words for matching and I am sure that you will find the best one. For this answer, I decided to compare the hash of each array of char.





            Here is my code if you want. But if you can use other structure from the collections or the stream API, this one can be totally different.



            public class WordFinder {

            private final String words;

            public WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }

            public String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }

            private boolean matches(char requirement, char candidate) {
            return candidate.length==requirement.length &&
            hash(candidate)==hash(requirement);
            }

            private int hash(char array) {
            char copy = Arrays.copyOf(array, array.length);
            Arrays.sort(copy);
            return Arrays.hashCode(copy);
            }
            }





            share|improve this answer









            $endgroup$













            • $begingroup$
              The most significant suggestion of this answer introduces a bug. Comparing hashes is a valid way of showing that two objects are different, but it is not a valid way of showing that they're the same.
              $endgroup$
              – Peter Taylor
              4 hours ago














            -1












            -1








            -1





            $begingroup$

            welcome on Codereview.



            I am pretty sure that you will find many other ways to do it the comments from @NateGardner is already a good suggestion. But the goal is to review your code so I will just try to suggest some improvements to your code.



            First of all I will just reformat the code, create a dedicated class for it and define the input and output.



            class WordFinder {
            private final String words;
            WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }
            String find(String word) {
            // Your code here
            }
            }


            Then you can start to split your nested logic in different methods and use exiting methods to simplify your code (like String#toCharArray() instead of String#split(""))



              String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( this.matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }


            As said in the beginning, there is a lot of way to test two words for matching and I am sure that you will find the best one. For this answer, I decided to compare the hash of each array of char.





            Here is my code if you want. But if you can use other structure from the collections or the stream API, this one can be totally different.



            public class WordFinder {

            private final String words;

            public WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }

            public String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }

            private boolean matches(char requirement, char candidate) {
            return candidate.length==requirement.length &&
            hash(candidate)==hash(requirement);
            }

            private int hash(char array) {
            char copy = Arrays.copyOf(array, array.length);
            Arrays.sort(copy);
            return Arrays.hashCode(copy);
            }
            }





            share|improve this answer









            $endgroup$



            welcome on Codereview.



            I am pretty sure that you will find many other ways to do it the comments from @NateGardner is already a good suggestion. But the goal is to review your code so I will just try to suggest some improvements to your code.



            First of all I will just reformat the code, create a dedicated class for it and define the input and output.



            class WordFinder {
            private final String words;
            WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }
            String find(String word) {
            // Your code here
            }
            }


            Then you can start to split your nested logic in different methods and use exiting methods to simplify your code (like String#toCharArray() instead of String#split(""))



              String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( this.matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }


            As said in the beginning, there is a lot of way to test two words for matching and I am sure that you will find the best one. For this answer, I decided to compare the hash of each array of char.





            Here is my code if you want. But if you can use other structure from the collections or the stream API, this one can be totally different.



            public class WordFinder {

            private final String words;

            public WordFinder(String words) {
            this.words = new String[words.length];
            System.arraycopy(words, 0, this.words, 0, words.length);
            }

            public String find(String word) {
            String result = new String[this.words.length];
            char letters = word.toCharArray();
            int counter = 0;
            for (String candidate : this.words) {
            if ( matches(letters, candidate.toCharArray()) ) {
            result[counter++] = candidate;
            }
            }
            return Arrays.copyOf(result, counter);
            }

            private boolean matches(char requirement, char candidate) {
            return candidate.length==requirement.length &&
            hash(candidate)==hash(requirement);
            }

            private int hash(char array) {
            char copy = Arrays.copyOf(array, array.length);
            Arrays.sort(copy);
            return Arrays.hashCode(copy);
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 7 hours ago









            gervais.bgervais.b

            1,083410




            1,083410












            • $begingroup$
              The most significant suggestion of this answer introduces a bug. Comparing hashes is a valid way of showing that two objects are different, but it is not a valid way of showing that they're the same.
              $endgroup$
              – Peter Taylor
              4 hours ago


















            • $begingroup$
              The most significant suggestion of this answer introduces a bug. Comparing hashes is a valid way of showing that two objects are different, but it is not a valid way of showing that they're the same.
              $endgroup$
              – Peter Taylor
              4 hours ago
















            $begingroup$
            The most significant suggestion of this answer introduces a bug. Comparing hashes is a valid way of showing that two objects are different, but it is not a valid way of showing that they're the same.
            $endgroup$
            – Peter Taylor
            4 hours ago




            $begingroup$
            The most significant suggestion of this answer introduces a bug. Comparing hashes is a valid way of showing that two objects are different, but it is not a valid way of showing that they're the same.
            $endgroup$
            – Peter Taylor
            4 hours ago










            Aditya is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            Aditya is a new contributor. Be nice, and check out our Code of Conduct.













            Aditya is a new contributor. Be nice, and check out our Code of Conduct.












            Aditya is a new contributor. Be nice, and check out our Code of Conduct.
















            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211538%2fgiven-a-word-how-do-i-find-other-words-in-an-array-with-same-length-and-same-ch%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Сан-Квентин

            Алькесар

            Josef Freinademetz