I have a list of words as follows.
pear amleth dormitory tinsel dirty room hamlet listen silnet
I want to find out all anagrams and list them in sorted order. If nothing is found just output that word. So in the above case the output should be.
amleth,hamlet dirty room,dormitory listen,silnet,tinsel pear
Below is the java code I have written for that.
public class Anagram {
private boolean isAnagram(String s1, String s2) {
if (s1.length() != s2.length()) {
return false;
}
Map<Character, Integer> anagramMap = new HashMap<>();
for (char ch = 'a'; ch <= 'z'; ++ch)
anagramMap.put(ch, 0);
for(int i=0; i<s1.length(); i++){
anagramMap.put(s1.charAt(i), anagramMap.get(s1.charAt(i))+1);
}
for(int j=0; j<s2.length(); j++) {
if (anagramMap.get(s2.charAt(j)) != 0) {
anagramMap.put(s2.charAt(j), anagramMap.get(s2.charAt(j)) - 1);
}
}
for(int value : anagramMap.values()) {
if (value != 0) {
return false;
}
}
return true;
}
private void solveChallenge(List<String> words) {
for(int i=0 ;i<(words.size()-1); i++) {
Set<String> result = new TreeSet<>();
for(int j=(i+1); j< words.size(); j++) {
if (isAnagram(words.get(i), words.get(j))){
result.add(words.get(i) + " " + words.get(j));
System.out.println(result);
words.remove(j);
}
}
}
}
public static void main(String[] args) {
Anagram anagram = new Anagram();
List<String> words = new ArrayList<>();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
String line = reader.readLine();
Integer numTestCases = Integer.parseInt(line);
while (--numTestCases >= 0){
words.add(reader.readLine().replaceAll("\\s+","").toLowerCase());
}
System.out.println(words);
new Anagram().solveChallenge(words);
} catch (IOException e) {
e.printStackTrace();
}
}
}
But it's not listing the desired output. The output I get is [amleth hamlet] [dormitory dirtyroom] [tinsel lisetn]
Can someone tell me what is wrong here?
This will solve your problem
public class Anagram {
private boolean isAnagram(String s1, String s2) {
if (s1.length() != s2.length()) {
return false;
}
Map<Character, Integer> anagramMap = new HashMap<>();
for (char ch = 'a'; ch <= 'z'; ++ch)
anagramMap.put(ch, 0);
for(int i=0; i<s1.length(); i++){
anagramMap.put(s1.charAt(i), anagramMap.get(s1.charAt(i))+1);
}
for(int j=0; j<s2.length(); j++) {
if (anagramMap.get(s2.charAt(j)) != 0) {
anagramMap.put(s2.charAt(j), anagramMap.get(s2.charAt(j)) - 1);
}
}
for(int value : anagramMap.values()) {
if (value != 0) {
return false;
}
}
return true;
}
private void solveChallenge(List<String> words) {
for(int i=0 ;i<(words.size()-1); i++) {
Set<String> result = new TreeSet<>();
int j = i+1;
while(j < words.size()) {
if (isAnagram(words.get(i), words.get(j))){
result.add(words.get(i) + " " + words.get(j));
System.out.println(result);
words.remove(j);
} else {
j++;
}
}
}
}
public static void main(String[] args) {
Anagram anagram = new Anagram();
List<String> words = new ArrayList<>();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
String line = reader.readLine();
Integer numTestCases = Integer.parseInt(line);
while (--numTestCases >= 0){
words.add(reader.readLine().replaceAll("\\s+","").toLowerCase());
}
System.out.println(words);
new Anagram().solveChallenge(words);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You should increment j only when you are not removing any element because that remove() method caused problems.
Now I would recommend you should use HashMap< String, ArrayList< String>> something like this data structure. Hope this helps :)
This is how I would go about it:
Map<Character, Integer>
that contains the characters of the word (excluding spaces) and the number of occurence - you have already done something similar Map<Map<Character, Integer>, List<String>>
, where the key is the map of occurences and the value is a list of all the words that match (anagrams). Map::equals
will do the comparison automagically for you. A sample implementation could look like this:
String[] words = ("pear", "amleth", ... }'
Map<Map<Integer, Long>, List<String>> characters = new HashMap<> ();
for (String word : words) {
//here I'm using a stream, but you can build the occurences map manually
Map<Integer, Long> occurences = word.replaceAll("\\s+", "") //remove spaces
.chars().boxed()
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
if (characters.containsKey(occurences)) { //anagram found !
characters.get(occurences).add(word); //add the word to the list
} else { //no anagram found, create the list, with only one item
List<String> list = new ArrayList<> ();
list.add(word);
characters.put(occurences, list);
}
}
//you may want to sort the lists here
characters.values().forEach(System.out::println);
You have made few mistakes in the code. First of all you need to change the logic of storing the anagrams in the set. You are storing here pair
in the set rather you should store all anagrams here. So you can have a StringBuilder
to store the anagrams
in a single
pass and after the iteration, You can add it to the set.
Another mistake is in this loop:
for(int j=(i+1); j< words.size(); j++) {
if (isAnagram(words.get(i), words.get(j))){
result.add(words.get(i) + " " + words.get(j));
System.out.println(result);
words.remove(j);
}
}
Here you are removing an element
from the list and then incrementing j
So it is possible that after removal, all elements gets shifted ahead by 1
place so If next element is anagram
then you will miss it as you are incrementing j
. And last mistake is that you need to check for all elements of words
list. Because it may possible that last element is not anagram with any other element, Then it is required to be taken separately.
So Make few changes in solveChallenge()
function:
private void solveChallenge(List<String> words) {
for(int i=0 ;i<(words.size()); i++) {
Set<String> result = new TreeSet<>();
StringBuilder resultant_string = new StringBuilder(words.get(i)); //To store the all anagrams
for(int j=(i+1); j< words.size(); j++) {
if (isAnagram(words.get(i), words.get(j))){
resultant_string.append(" ").append(words.get(j));
words.remove(j);
j--; //If anagram found, stay on the current element
}
}
result.add(resultant_string.toString());
System.out.println(resultant_string);
}
}
As per your need, I have made some changes in the program.
Code:
class Anagram {
private boolean isAnagram(String s1, String s2) {
s1=s1.replaceAll("\\s+","");
s2=s2.replaceAll("\\s+","");
if (s1.length() != s2.length()) {
return false;
}
Map<Character, Integer> anagramMap = new HashMap<>();
for (char ch = 'a'; ch <= 'z'; ++ch)
anagramMap.put(ch, 0);
for(int i=0; i<s1.length(); i++){
anagramMap.put(s1.charAt(i), anagramMap.get(s1.charAt(i))+1);
}
for(int j=0; j<s2.length(); j++) {
if (anagramMap.get(s2.charAt(j)) != 0) {
anagramMap.put(s2.charAt(j), anagramMap.get(s2.charAt(j)) - 1);
}
}
for(int value : anagramMap.values()) {
if (value != 0) {
return false;
}
}
return true;
}
private void solveChallenge(List<String> words) {
List<String> result = new ArrayList<>();
for(int i=0 ;i<(words.size()); i++) {
List<String> resultant_strings=new ArrayList<> ();
resultant_strings.add(words.get(i));
for(int j=(i+1); j< words.size(); j++) {
if (isAnagram(words.get(i), words.get(j))){
resultant_strings.add(words.get(j));
words.remove(j);
j--;
}
}
Collections.sort(resultant_strings);
String resultant_string=resultant_strings.toString();
result.add(resultant_string);
}
Collections.sort(result);
System.out.println(result);
}
public static void main(String[] args) {
Anagram anagram = new Anagram();
List<String> words = new ArrayList<>();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
String line = reader.readLine();
Integer numTestCases = Integer.parseInt(line);
while (--numTestCases >= 0){
words.add(reader.readLine().toLowerCase());
}
System.out.println(words);
new Anagram().solveChallenge(words);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Prints result:
[[amleth, hamlet], [dirty room, dormitory], [listen, silnet, tinsel], [pear]]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.