Ordering a string alphabetically - did I miss something obvious? - java

public class Anagram {
public static void main(String[] args) {
String a = "Despera tion-".toLowerCase();
String b = "A Rope Ends It".toLowerCase();
String aSorted = sortStringAlphabetically(a);
String bSorted = sortStringAlphabetically(b);
if(aSorted.equals(bSorted)){
System.out.println("Anagram Found!");
}else{
System.out.println("No anagram was found");
}
}
public static String sortStringAlphabetically(String s) {
char[] ca = s.toCharArray();
int cnt = 0;
ArrayList al = new ArrayList();
for (int i = 0; i < ca.length; i++) {
if (Character.isLetter(ca[cnt]))
al.add(ca[cnt]);
cnt++;
}
Collections.sort(al);
return al.toString();
}
}
As a learner, I hacked up this boolean Anagram checker. My chosen solution was to create a sortStringAlphabetically method seems to do just too much type-juggling String -> chars[] -> ArrayList ->String - given that I do just want to compare 2 strings to test whether one phrase is an anagram of another - could I have done it with less type-juggling?
ps The tutors solution was a mile away from my attempt, and probably much better for a lot of reasons - but I am really trying to get a handle on all the different Collection types.
http://www.home.hs-karlsruhe.de/~pach0003/informatik_1/aufgaben/en/doc/src-html/de/hska/java/exercises/arrays/Anagram.html#line.18
EDIT
FTW here is the original challenge, I realise I wandered away from the solution.
http://www.home.hs-karlsruhe.de/~pach0003/informatik_1/aufgaben/en/arrays.html
My initial kneejerk reaction was to simply work though array a, knocking out those chars which matched with array b - but that seemingly required me to rebuild the array at every iteration - Many thanks for all your efforts to educate me.

There are different ways to improve this, if you go with this algorithm.
First, you don't necessarily need to create a character array. You can use String.charAt() to access a specific character of your string.
Second, you don't need a list. If you used a SortedMultiSet or a SortedBag, you could just add things in sorted order. If you write a function that creates the SortedMultiSet from your string, you could just compare the sets without rebuilding the string.
Note: I don't know what libraries you're allowed to use (Google and Apache have these types), but you can always 'brew your own'.
Also, make sure to use generics for your types. Just defining ArrayLists is pretty risky, IMHO.

You could just sort the string without using a list:
public static String sortStringAlphabetically(String s) {
String lettersOnly = s.replaceAll("\\W", "");
char[] chars = lettersOnly.toCharArray();
Arrays.sort(chars);
return new String(chars);
}
N.B. I haven't actually tried running the code.

Your algorithm, but shorter (and yet, slower). The "type-juggling" is done "implicitly" in Java's various library classes:
public static boolean isAnagram(String a, String b) {
List<String> listA = new ArrayList<String>(Arrays.asList(
a.toLowerCase().replaceAll("\\W", "").split("")));
List<String> listB = new ArrayList<String>(Arrays.asList(
b.toLowerCase().replaceAll("\\W", "").split("")));
Collections.sort(listA);
Collections.sort(listB);
return listA.equals(listB);
}
Optionally, replace the \W regular expression to exclude those letters that you don't want to consider for the anagram

public class Anagram {
public static void main(String[] args) throws Exception {
String s1 = "Despera tion-";
String s2 = "A Rope Ends It";
anagramCheck(s1, s2);
}
private static void anagramCheck(String s1, String s2) {
if (isAnagram(s1, s2)) {
System.out.println("Anagram Found!");
} else {
System.out.println("No anagram was found");
}
}
private static boolean isAnagram(String s1, String s2) {
return sort(s1).equals(sort(s2));
}
private static String sort(String s) {
char[] array = s.replaceAll("\\W", "").toLowerCase().toCharArray();
Arrays.sort(array);
return new String(array);
}
}

Related

Split method creates empty elements in Java Array

I have the following String "Make Me A SandWich"
Someone decided to troll me and replace the spaces with a random number of LOL.
so now the string is "LOLMakeLOLLOLLOLMELOLALOLSandWich"
My goal is to revert this change.
I tried to create a string array with split method but this caused "empty" elements inside of the array that has a value but when I try to log it, it doesn't show anything. It's also not equal to ""
Public class MyClass{
public static void main(String[] args) {
String trollText = "MakeLOLLOLLOLMELOLALOLSandWich";
String[] array = trollText.split("LOL");
if (array[1]=="")System.out.print("it's an empty string");
if (array[1]==" ")System.out.print("it's a space sign");
if (array[1]==null)System.out.print("it's equal to nothing");
if (array[1]==' '+"")System.out.print("I don't know what's that");
else System.out.print(array[1]+"<-- This is an element and it has a value");
}
}
I consider the problem solved if someone tells me what array[1] equals to.
Knowing the value will give me something to compare to when copying the elements into a new array.
When comparing two strings in java, you cannot use == operator which compares object references. You need to use array[1].equals("")
Also, if you simply want to replace all occurrences of a string, you can do following
trollText.replaceAll("LOL", " ")
Here is my solution. skipping empty or " " string and appending notEmpty values to new StringBuilder() and finally print it.
import java.util.Arrays;
public class LOL_problem {
public static void main(String[] args) {
String trollText = "MakeLOLLOLLOLMELOLALOLSandWich";
StringBuilder sb = new StringBuilder();
String[] array = trollText.split("LOL");
//System.out.println(Arrays.toString(array));
for (String str : array) {
if (!str.equals("")) sb.append(str+" ");
}
System.out.println(sb.toString().trim());
}
}
We should use equals(String str) method to check if strings are equals instead of '==' which does object reference check.
To replace all the occurrence, you can use trollText.replaceAll method as below.
public class MyClass{
public static void main(String[] args) {
String trollText = "MakeLOLLOLLOLMELOLALOLSandWich";
String result = trollText.replaceAll("LOL", " ");
System.out.println(result);
}
}
To compare Strings in Java, use:
String.equals("text");
This will return true if the Strings are identical and false if not.

Eclipse JAVA String reverse - reversing 1 word which is pre-declared [duplicate]

This question already has answers here:
Reverse a string in Java
(36 answers)
Closed 5 years ago.
Like to know how to reverse a string value (1 word) which is pre-declared in the program. I mean not using user input or scanner.
Like to reverse a word "TRAIN" which is pre-declared in the program.
Have tried the below program but no results and no error also.
// QUERY PROGRAM NOT RUNNING - NO RESULT, NO ERROR.
// STRING REVERSE PROGRAM USING ARRAY
package abnpackage;
class Play {
void REVERSE (){
String [] INPUT_WORD = {"T","R","A","I","N"};
int Q;
for(Q=INPUT_WORD.length-1; Q>=0; Q=Q--);
System.out.print ("REVERSE VALUE" + INPUT_WORD[Q]);
}
public static void main(String[]args){
Play PL = new Play();
PL.REVERSE();
}
}
Problem in Q=Q-- and ; symbol after for cylce. Try this:
class Play{
void REVERSE (){
String [] INPUT_WORD = {"T","R","A","I","N"};
int Q;
for(Q=INPUT_WORD.length-1; Q>=0; Q--) {
System.out.print(INPUT_WORD[Q]);
}
}
public static void main(String[]args){
Play PL = new Play();
PL.REVERSE();
}
}
I'd like to offer a few suggestions.
Indent your code. It not only makes it easier for you to follow, but makes it easier for others to read your code.
Naming conventions. Use Title case for classes, camelCase for both variables and methods, and UPPER_CASE for constants.
Strings and characters. A String can be decomposed into an array of characters with the built-in method, String.toCharArray(). A character array is mutable, so is often used as an intermediate structure when converting a String from one state to another for tasks like ciphers or interview problems.
Encapsulation. If you can make your methods use only what is submitted to them through their method signature, and only output their return value, it's usually best. Prefer passing values over referencing constants in your utility methods to make them easier to follow.
package abnpackage;
class Play {
private static final String INPUT_WORD = "TRAIN";
private String reverse(String word) {
char[] letters=word.toCharArray();
StringBuilder sb=new StringBuilder();
for (int q=letters.length-1; q>=0; q--) {
sb.append(letters[q]);
}
return sb.toString();
}
public static void main(String[]args) {
Play play = new Play();
System.out.println("REVERSE VALUE: " + play.reverse(INPUT_WORD));
}
}
class Play {
void REVERSE() {
String[] INPUT_WORD = {"T", "R", "A", "I", "N"};
String[] OUTPUT_WORD =new String[INPUT_WORD.length];
int length = INPUT_WORD.length;
int i = 0;
while(--length>=0){
OUTPUT_WORD[i++] = INPUT_WORD[length];
}
System.out.println(Arrays.toString(OUTPUT_WORD));
}
public static void main(String[] args) {
Play PL = new Play();
PL.REVERSE();
}
}
Your code is entering an endless loop because of the assignment "Q=Q--"
for(Q=INPUT_WORD.length-1; Q>=0; Q=Q--);
It should instead be
Q--
without a semicolon at the end.
If the code runs successfully, it will print the words "REVERSE VALUE" repeatedly prior to printing each character in reverse.
System.out.print ("REVERSE VALUE" + INPUT_WORD[Q]);
So you will want to keep the text in reverse prior to printing the whole statement at the end of the execution of the for loop.
What is the reason to use array of String instead of just String? Since it's not mentioned as a requirement, I'm suggesting the following as an alternative solution:
public class Play {
static void reverse(){
String inputWord = "TRAIN";
char[] toStrArray = inputWord.toCharArray();
char[] revisedInput = new char[inputWord.length()];
int i = 0;
for(int q=toStrArray.length-1; q>=0; q--){
revisedInput[i]=toStrArray[q];
i++;
}
System.out.print ("REVERSE VALUE: " + new String(revisedInput));
}
public static void main(String[]args){
//Play PL = new Play();
//PL.REVERSE();
reverse();
}
}
Note: You can declare the method reverse as a static method. By doing this you don't have to create an object before calling it. Hope this helps.

Get the Smallest Matching String from a Long String

Suppose I have a String
interpreter, interprete, interpret
now what i want to do is to get the smallest matching string from the above string that must be:
interpret
Is it possible using Java if it is can somebody help me out digging this problem thanks
Check out this.....
public static void main(String[] ar)
{
List<String> all=new LinkedList<String>();
all.add("interpreter");
all.add("interprete");
all.add("interpret");
String small="";
small=all.get(0);
for (String string : all) {
if(small.contains(string))
{
small=string;
}
}
System.out.println(small);
}
Let me know, Is it satisfying your requirement???
//-----------------Edited One--------------------------
public static void main(String[] ar)
{
List<String> all=new LinkedList<String>();
Set<String> result=new LinkedHashSet<String>();
all.add("interpreter");
all.add("interprete");
all.add("interpret");
all.add("developed");
all.add("develops");
String small="";
for(int i=0;i<all.size();i++)
{
small=all.get(i);
for(int j=i;j<all.size();j++)
{
if(small.contains(all.get(j)))
{
small=all.get(j);
}
}
result.add(small);
}
for (String string : result) {
System.out.println(string);
}
}
If I get you correctly, you want the shortest word in an input string s which includes a target string t="interpret".
So first, split the string into words w, e.g., using s.split("\\s*,\\s*"), then use w.contains(t) on each string w to check if it contains the word you look for. Choose the shortest string for which the contains method returns true.
you need to compare all char one by one of all string and a array of boolean flag maintain
for every pair of string then check out all Boolean array similarity(length) and then substring
of any string from that length
i hope this will help
What you are looking for is called a lemmatizer/steamer for Java.
There are a few of them (I have not used any) but you may want to search/try a few of them:
Snowball
Lemamatization
You should test each of them, because for example some (in case of snowball) will do:
Community
Communities --> Communiti // this is obviously wrong

Should the toString() method be added?

This is the piece of code.
List<BDDObject> childlist = savingObject.getChildren("TherapyAreaReference");
if (childlist.size() > 1) {
for (int i = 0; i < childlist.size() - 1; i++) {
String newMedcondRefChild = ((String) childlist
.get(i)
.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim()
.concat(((String) childlist
.get(i)
.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME))
.toLowerCase().trim());
}
}
IDDConstants has public static final strings defined in it. As StringBuffer is more effective, how can it be incorporated for the concat operations?
I'm guessing that the intention is to generate a list of 'reports', one for each BDDObject record found. Based on that idea, your code should look more like this:
public List<String> getReport(List<BDDObject> records) {
List<String> reports = new ArrayList<String>(record.size());
for (BDDObject record:records) {
String newMedcondRefChild = String.valueOf(record.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim() + String.valueOf(record.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME)))
.toLowerCase().trim());
reports.add(newMedcondRefChild);
}
return reports;
}
Regarding the question on whether toString() would be helpful, the only place where I see it fitting, would be on the BDDObject itself. It would look something like this:
class BDDObject {
...
#Override
public String toString() {
return String.valueOf(getValue(IDDConstants.IDD_THERAPY_AREA_REF_VALUE)).toLowerCase().trim() +
String.valueOf(getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME)).toLowerCase().trim());
}
In which case, the function to create the report becomes trivial:
public List<String> getReport(List<BDDObject> records) {
List<String> reports = new ArrayList<String>(record.size());
for (BDDObject record:records) {
reports.add(record.toString());
}
return reports;
}
In case that what you want is a looooong string with all the values concatenated to it, you can use StringBuilder, like this:
public String getReport(List<BDDObject> records) {
StringBuilder sb = new StringBuilder();
for (BDDObject record:records) {
sb.append(String.valueOf(record.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim());
sb.append(String.valueOf(record.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME))
.toLowerCase().trim()));
}
return sb.toString();
}
This will return all the records appended after each other. I doubt its readability, but you I hope you get the idea. StringBuilder is helpful when you need to build a string iteratively (like in the previous example). StringBuilder should not be used to replace single String operations like : String a = b.get() + c.get(); given that the compiler implicitly creates a StringBuilder in these cases and therefore there's no actual performance improvement to be achieved.
In the code in your question, StringBuffer/StringBuilder will not give you any performance gains, because you concatenate only two strings. However, the question does not state what you are doing with the string in newMedconfRefChild. If your actual goal is to concatenate the strings of each loop iteration, then you should use a StringBuilder (use StringBuffer only when it is really necessary, prefer StringBuilder).

Check that word all words from one string exist in the other

How can I check that all the words from string #2 exist in String #1? It should be case insensitive and I want exclude all punctuation and special characters during comparison of words.
Any help?
Thanks.
Algorithm
Iterate through words in String #1 and insert them as keys into a dictionary/hash/associative array.
Iterate through words in String #2 and check if each word is a key in the dictionary created in step 1.
If one is not found, return false.
After the iteration has finished, return true.
Running time: O(n)
I'll let someone else implement this in Java.
To find the words in a String while ignoring the various punctuations etc you can use the StringTokenizer class.
StringTokenizer st = new StringTokenizer("Your sentence;with whatever. punctuations? might exists", " :?.,-+=[]");
This breaks up the String into Tokens using the delimiters provided in the second example. You can then use hasMoreTokens() and nextToken() method to iterate the tokens.
Then you can use the algorithm suggested by #MattDiPasquale.
You can try String's built-in split method
 
it looks like
public String[] split(String regex)
and it returns an array of Strings based on the regular expression you use. There are examples in the link above.
You can easily generate two arrays this way (one for String #1 and one for String #2).
Sort the arrays and then check if the arrays are equal. (size and order)
You can simplify array sorting if you utilize java.util.Arrays
Arrays in Java have a lot of library methods and you should learn about them because they are incredibly useful sometimes:
http://leepoint.net/notes-java/data/arrays/arrays-library.html
This is slightly less efficient than building a dictionary/hash table/ADT with your selected delimiters (like in MattDiPasquale's answer), but it might be easier to understand if you are not very familiar with hash functions or dictionaries (as a datatype).
isContainsAll(s1, s2)
1 . split s2 by " "; s.split("")
2 . check if s1 contains all the element of s2
public static boolean isContainsAll(String s1, String s2){
String[] split = s2.split(" ");
for(int i=0; i<split.length; i++){
if(!s1.contains(split[i])){
return false;
}
}
return true;
}
public static void main(String... args){
System.out.println(isContainsAll("asd dsasda das asd; asds asd;/ ", "asd;/"));
}
While the algorithm to do this is simple, the implementation is more involved if you want to support multiple locales. Below is a sample code that supports multiple locales. I've verified this with English as well as Chinese (But I am not sure if it passes the Turkey Test ;-)). Anyways the below code needs some refactoring but this will get you started.
NOTE: Even if you doesn't want support for other languages than English, I still would use the below as the word boundarie/punctuations/grammar etc are locale/language dependent which might not be well addressed by StringTokenizer, String.split(...) and other basic APIs.
import java.text.BreakIterator;
import java.text.Collator;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang.StringEscapeUtils;
public class UnicodeWordCount
{
public static void main(final String[] args)
{
testEnglish();
testChinese();
}
public static void testEnglish()
{
BreakIterator wordIterator = BreakIterator.getWordInstance(Locale.ENGLISH);
String str = "This is the source string";
String match = "source string is this";
String doesntMatch = "from Pangea";
Set<String> uniqueWords = extractWords(str, wordIterator, Locale.ENGLISH);
printWords(uniqueWords);
System.out.println("Should print true: " + contains(match, wordIterator, uniqueWords));
System.out.println("Should print false: " + contains(doesntMatch, wordIterator, uniqueWords));
}
public static void testChinese()
{
BreakIterator wordIterator = BreakIterator.getWordInstance(Locale.CHINESE);
String str = "\u4E0D\u70BA\u6307\u800C\u8B02\u4E4B\u6307\uFF0C\u662F[\u7121\u90E8]\u70BA\u6307\u3002\u201D\u5176\u539F\u6587\u70BA";
String match = "\u5176\u539F\u6587\u70BA\uFF0C\u70BA\u6307";
String doesntMatch = "\u4E0D\u70BA\u6307\u800C\u8B02\u4E4B\u6307\uFF0C\u662F[\u517C\u4E0D]\u70BA\u6307\u3002";
Set<String> uniqueWords = extractWords(str, wordIterator, Locale.CHINESE);
printWords(uniqueWords);
System.out.println("Should print true: " + contains(match, wordIterator, uniqueWords));
System.out.println("Should print false: " + contains(doesntMatch, wordIterator, uniqueWords));
}
public static Set<String> extractWords(final String input, final BreakIterator wordIterator, final Locale desiredLocale)
{
Collator collator = Collator.getInstance(desiredLocale);
collator.setStrength(Collator.PRIMARY);
Set<String> uniqueWords = new TreeSet<String>(collator);
wordIterator.setText(input);
int start = wordIterator.first();
int end = wordIterator.next();
while (end != BreakIterator.DONE)
{
String word = input.substring(start, end);
if (Character.isLetterOrDigit(word.charAt(0)))
{
uniqueWords.add(word);
}
start = end;
end = wordIterator.next();
}
return uniqueWords;
}
public static boolean contains(final String target, final BreakIterator wordIterator, final Set<String> uniqueWords)
{
wordIterator.setText(target);
int start = wordIterator.first();
int end = wordIterator.next();
while (end != BreakIterator.DONE)
{
String word = target.substring(start, end);
if (Character.isLetterOrDigit(word.charAt(0)))
{
if (!uniqueWords.contains(word))
{
return false;
}
}
start = end;
end = wordIterator.next();
}
return true;
}
private static void printWords(final Set<String> uniqueWords)
{
for (String word : uniqueWords)
{
System.out.println(StringEscapeUtils.escapeJava(word));
}
}
}

Categories

Resources