'String anagram in Java
i am trying to create a program for string anagram that follows these conditions:
- method should allow only letters, white space, commas and dots in an anagram. If there are any other characters, then the string cannot contain an anagram.
- The method should ignore all white space, commas and dots when it checks the text.
- If there are no letters in the text, then the text cannot be an anagram.
import java.util.Arrays;
import java.util.Scanner;
public class StringAnagram {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter first string: ");
String first = in.nextLine().toUpperCase();
System.out.print("Enter second string: ");
String second = in.nextLine().toUpperCase();
String result = isAnagram(first, second);
System.out.println(result);
}
private static String isAnagram(String first, String second) {
String answer = "";
if (first.matches("[A-Z\\.\\,\\s]")) {
String st = first.replaceAll("\\.\\,\\s", "");
String nd = second.replaceAll("\\.\\,\\s", "");
char[] arraySt = st.toCharArray();
char[] arrayNd = nd.toCharArray();
Arrays.sort(arraySt);
Arrays.sort(arrayNd);
if(Arrays.equals(arraySt, arrayNd)) {
answer = "Anagram.";
}
else {
answer = "No anagram.";
}
}
else {
answer = "No anagram.";
}
return answer;
}
}
However when the program tests these 2 sentences, they are not anagram but they should be anagram. I have no idea where to look for mistake.
- Eleven plus two is thirteen.
- Twelve plus one is thirteen.
Solution 1:[1]
If you start your method as follows, it will fulfil validations mentioned in the 1st
and the 3rd
points of your question:
if (first == null || second == null || first.equals("") || second.equals("") || !first.matches("[A-Za-z,. ]+")
|| !second.matches("[A-Za-z,. ]+")) {
return "No anagram.";
}
The next thing you should do is to replace all white space, commas and dots with ""
in order to ignore them:
String st = first.replaceAll("[,. ]+", "");
String nd = second.replaceAll("[,. ]+", "");
The complete code is as follows:
private static String isAnagram(String first, String second) {
if (first == null || second == null || first.equals("") || second.equals("") || !first.matches("[A-Za-z,. ]+")
|| !second.matches("[A-Za-z,. ]+")) {
return "No anagram.";
}
String answer = "";
String st = first.replaceAll("[,. ]+", "");
String nd = second.replaceAll("[,. ]+", "");
if (st.equals("") || nd.equals("")) {
return "No anagram.";
}
char[] arraySt = st.toCharArray();
char[] arrayNd = nd.toCharArray();
Arrays.sort(arraySt);
Arrays.sort(arrayNd);
if (Arrays.equals(arraySt, arrayNd)) {
answer = "Anagram.";
} else {
answer = "No anagram.";
}
return answer;
}
A test run:
Enter first string: london
Enter second string: britain
No anagram.
Another test run:
Enter first string: ram
Enter second string: mar
Anagram.
Another test run:
Enter first string: .
Enter second string: .
No anagram.
Another test run:
Enter first string: ,
Enter second string: .
No anagram.
Another test run:
Enter first string: ra.m
Enter second string: a.m.r
Anagram.
Solution 2:[2]
This: first.matches("[A-Z\\.\\,\\s]")
tests if the first
value is a single character that is either 1 capital letter, or a dot, or a comma, or any whitespace character.
Completely not what you want.
You can add System.out.println
statements all over the place to print where your code is and the value of relevant variables. Follow the code along like you're the computer. There where what you think should happen does not match with what the sysout statements tell you – there is a bug there (there can be many, especially if you write this much stuff without testing anything first).
Better yet, use a debugger.
NB: Something as trivial as replacing one of your No anagram.
strings with anything else just so you know which of the two got triggered would already have helped a lot.
NB: first.replaceAll("\\.\\,\\s", "");
is also broken; you've written way too much code here; test each individual moving piece. It's like a bike that doesn't do anything after you put it together: Take it apart piece by piece, test each piece individually.
Solution 3:[3]
This solution accepts strings from console input. That portion is omitted since that is working for you.
The idea is to selectively reduce the essence of what you are comparing to the bare minimum. Comments are provide to explain the logic. In the examples, all but the third one report as an anagram.
System.out.println(isAnagram("radar", "darar"));
System.out.println(isAnagram("ra.,. dar", "d.,a rar"));
System.out.println(isAnagram("r+a.,. dar", "d.,a + rar"));
System.out.println(isAnagram("Eleven plus two is thirteen.", "Twelve plus one is thirteen."));
// This method accepts mixed case strings. The conversion to upper case is
// done within the method.
public static String isAnagram(String first, String second) {
// get rid of allowed characters and convert to upper case
String st = first.replaceAll("[., ]","").toUpperCase();
String nd = second.replaceAll("[., ]","").toUpperCase();
// Now get rid of all alpha characters and compare to the empty string.
// Only if both are equal are the strings potential anagrams.
// Otherwise, the illegal characters would be present.
if (st.replaceAll("[A-Z]","").equals("") &&
nd.replaceAll("[A-Z]","").equals("")) {
// this is your original code
char[] arraySt = st.toCharArray();
char[] arrayNd = nd.toCharArray();
Arrays.sort(arraySt);
Arrays.sort(arrayNd);
// don't set a value just return it's an
// anagram
if (Arrays.equals(arraySt, arrayNd)) {
return "Anagram.";
}
}
// Otherwise, it's not
return "No Anagram.";
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | rzwitserloot |
Solution 3 |