Java string comparison, printing two different string inputs into alphabetical order - java

We are learning compareTo() method and equals() method, but I am unsure how to properly print the words in alphabetical order.
I have 2 Strings:
String firstString;
String secondString;
that are assigned values (elsewhere).
I have tried:
System.out.println(firstString.CompareToIgnoreCase(secondString));
but am only getting integers in my output as opposed to full words.

As this is homework, I'll only address your stumbling block.
As per the documentation, compareToIgnoreCase() (and more generally, compareTo()) returns an integer, either negative, zero or positive, depending on whether the first parameter's order is less than, the same or greater respectively than the second parameter.
You'll need to check the result of compareToIgnoreCase(), then print based on that, for example:
if (firstString.compareToIgnoreCase(secondString) > 0) {
// do something
} else {
// do something else
}

For those taking the same class, this solves the requirements for the question:
if (firstString.compareTo(secondString) < 0) {
System.out.println(firstString + " " + secondString);
}
else {
System.out.println(secondString + " " + firstString);
}

Related

Java string arrayList: Sorting the elements in descending order (like polynomials in math)

I'm still quite new to programming, so I'm sorry if I caused you to face palm.
Right now, I am trying to create parentheses-expander in Java. The current program can already expand the parentheses, but it can not simplify the results, because the terms are not in the descending order. I do understand that you could try to add the terms without re-ordering them by comparing the variables contained in each of the elements. However, I want the program to "show work" like a human, so I need the terms in descending order.
And for that, I want to create a method that, given a string arrayList, re-orders the elements in something like descending order for polynomials in math.
If any of the variables had exponents, the variable is just repeated to the number of the exponent.
for example:
X^2 = XX,
a^3 = aaa,
Z^5 = ZZZZZ
Also, there will be no negative exponents nor parentheses.
All elements have either + or - at the beginning(and no other operators after that).
All elements have a coefficient, even if it is 1.
Capital letters have higher importance than lower case letters, and elements with just numbers should be re-located to the very end.
I forgot the mathematical word for that, but the terms should be ordered in a interest of A, then B so on until Z, and then a,b,c,...so on.(I mean, terms with most A comes first, B second ,C third... up until z)
Coefficients and operators should be ignored.
For example, if the input was this:
[-1b,+3XX,-4AA,+1aaa,+20CCa,-9ABa,-9ABaa,+20CCCa,+3BBX,+1aab,+10]
Then I want the method to return the arrayList like:
[-4AA,-9ABaa,-9ABa,+3BBX,+20CCCa,+20CCa,+3XX,+1aaa,+1aab,-1b,+10]
I'm very much stuck right here. any help will be appreciated. If I didn't describe my problem clear enough, please let me know. I will clarify.
I believe wolfram alpha already has parentheses expanding capabilities. However, I still want to make this.
If anyone can help me with this, that will be amazing. Thanks in advance!
You have a couple of challenges that need to be dealt with individually:
How do I parse something like -1b into a format I can work with?
How do I sort by a custom sorting rule?
For the first part, your rule is very well-defined and the format is pretty simple. This lends itself well to using a regular expression to parse it:
Also, there will be no negative exponents nor parentheses. All elements have either + or - at the beginning(and no other operators after that). All elements have a coefficient, even if it is 1.
So a good regular expression format might be:
([-+]\d+)(\w+)?
This would result in two "capture groups". The first would be the numeric part, and the second would be the (optional) repeated string part.
After decomposing each entry into these two separate parts, it is pretty easy to come up with a set of rules for determining the sort order:
If both of them are numbers (having only the first part), then sort as numbers
If one of them is a number, and the other has letters, sort the number afterward.
If both have numbers and letters, sort according to the letters only using normal String sorting.
An easy way to do custom sorting is to write a custom Comparator class which would be used as an argument to the sort function. Combining all the ideas presented above that might look something like this:
public class PolynomialComparator implements Comparator<String> {
private static Pattern pattern = Pattern.compile("([-+]\\d+)(\\w+)?");
#Override
public int compare(String s1, String s2) {
if (s1 == null) throw new NullPointerException("s1");
if (s2 == null) throw new NullPointerException("s2");
int compare = 0;
Matcher m1 = pattern.matcher(s1);
Matcher m2 = pattern.matcher(s2);
if (!m1.matches()) throw new IllegalArgumentException("Invalid Polynomial format: " + s1);
if (!m2.matches()) throw new IllegalArgumentException("Invalid Polynomial format: " + s2);
int n1 = Integer.parseInt(m1.group(1));
int n2 = Integer.parseInt(m2.group(1));
String p1 = m1.group(2);
String p2 = m2.group(2);
if (p1 == null && p2 == null) { // Rule #1: just compare numbers
compare = n2 - n1;
} else if (p1 == null) { // Rule #2: always sort number last
compare = 1;
} else if (p2 == null) { // Rule #2: always sort non-number first
compare = -1;
} else { // Rule #3: compare the letters
compare = m1.group(2).compareTo(m2.group(2));
}
return compare;
}
}
Finally, to tie it all together, here is a simple program that correctly sorts your provided example using this Comparator (with the exception of your second and third entry which I believe is wrong in your example):
public static void main(String args[]){
String input = "[-1b,+3XX,-4AA,+1aaa,+20CCa,-9ABa,-9ABaa,+20CCCa,+3BBX,+1aab,+10]";
String[] array = input.substring(1, input.length() - 1).split(",");
Arrays.sort(array, new PolynomialComparator());
System.out.println("[" + String.join(",", array) + "]");
}
OUTPUT: [-4AA,-9ABa,-9ABaa,+3BBX,+20CCCa,+20CCa,+3XX,+1aaa,+1aab,-1b,+10]
Hopefully you can spend some time walking through this and learn a few ideas that will help you on your way. Cheers!

Get last number from string

I want to get the last character of a string and if it's a even number to do different actions based on that. Simple example:
Server_3
First I want to get the last value 3
String str = "Server_3";
str.charAt(str.length()-1)
The problem is next how to construct the logic to have different cased based on that is this a even number or not. Can you help me to complete this?
The correct code is:
if (Integer.valueOf(str.charAt(str.length()-1) + "") % 2 == 0) {
// Even logic
} else {
// Odd logic
}
Or.... to reduce method calls and the get rid of the funky string concatenation:
if ((str.charAt(str.length()-1) - '0') % 2) {
// Even logic
} else {
// Odd logic
}
Convert to integer and check for even
if(Integer.valueOf(str.charAt((str.length()-1) + "") % 2 ==0) {
// do your work here
}
Use the modulo (%) operator: i % 2 is 0 if i is even, and 1 if i is odd.

Comparing Two Strings Java Style

I saw this in my readings that allows you to compare two strings using the compareToCaseIgnore(String).
public class CompareWithoutCase
{
public static void main(String [] args)
{
String name1, name2; // To hold two names
// Create a Scanner object to read input.
Scanner keyboard = new Scanner(System.in);
// Get a name.
System.out.print("Enter a name: ");
name1 = keyboard.nextLine();
// Get another name.
System.out.print("Enter another name: ");
name2 = keyboard.nextLine();
// Compare the names.
if (name1.compareToIgnoreCase(name2) < 0)
{
System.out.println(name1 + " is less than " + name2);
}
else if (name1.compareToIgnoreCase(name2) == 0)
{
System.out.println(name1 + " is equal to " + name2);
}
else if (name1.compareToIgnoreCase(name2) > 0)
{
System.out.println(name1 + " is greater than " + name2);
}
}
}
My question is why would a string such as cli be different from ilc in value if they hold the same characters? I've read in another question that a lower case letter is different from a capital letter in value and I somewhat understand that, though not fully. Is there any place I can find an explanation for this in depth or can someone explain with a few examples? I input
cli
for the first string and
ilc
for the second name and got
cli is less than ilc
Why is one less than the other with the same letters in each string?
Lower case and upper case letters do have different ASCII values, but they are separated by a constant (42, I think). That is to say, A is the same distance from a as B is from b as C is from c, etc.
ilc and cli are different in that they're completely different characters.
compareToIgnoreCase (or equalsIgnoreCase) does a character by character comparison. That is, it compares the character at index 0 of str1 to the character at index 0 of str2. And so on, for every index of the two strings being compared.
If you compare ilc and cli, then i in ilc is compared to c in cli (and they're different), so the comparison returns false. The comparison doesn't care if i appears elsewhere in the second string, it only cares if i or I exists in the second string at the same index it exists in the first string (and so on for all the rest of the characters, though I imagine it's probably optimized to return false as soon as it finds one difference).

Alternative to substring

I have a strange problem when adding a value to a String array which is later involved in an array sort using a hash map. I have a filename XFR900a, and the XFR900 part is added to the array using the following code;
private ArrayList<String> Types = new ArrayList<String>();
...
Types.add(name.substring(0,(name.length() - 1));
System.out.println(name.substring(0,(name.length() - 1));
I even print the line which gives "XFR900", however the array sort later on behaves differently when I use the following code instead;
Types.add("XFR900");
System.out.println(name.substring(0,(name.length() - 1));
which is simply the substring part done manually, very confusing.
Are there any good alternatives to substring, as there must be some odd non ascii character in there?
Phil
UPDATE
Thanks for your comments everyone. Here is some of the code that later compares the string;
for (int i=0;i< matchedArray.size();i++){
//run through the arrays
if (last == matchedArray.get(i)) {
//add arrays to a data array
ArrayList data = new ArrayList();
data.add(matchedArray1.get(i));
data.add(matchedArray2.get(i));
data.add(matchedArray3.get(i));
data.add(matchedArray4.get(i));
data.add(matchedArray5.get(i));
//put into hash map
map.put(matchedArray.get(i), data);
}
else {
//TODO
System.out.println("DO NOT MATCH :" + last + "-" + matchedArray.get(i));
As you can see I have added a test System.out.println("DO NOT MATCH" ... and below is some the output;
DO NOT MATCH :FR99-XFR900
DO NOT MATCH :XFR900-XFR900
I only run the substring on the XFR900a filename. The problem is that for the test line to be printed last != matchedArray.get(i) however they are then the same when printed out to the display.
Phil
You should never use the == operator to compare the content of strings. == checks if it is the same object. Write last.equals(matchedArray.get(i)) instead. The equals() method checks if to object are equal, not if they are the same. In case of String it checks if the two strings consists of the same characters. This might eliminate your strange behaviour.
PS: The behaviour of == on string is a little unpredictable because the java virtual machine does some optimization. If two strings are equal it is possible that the jvm uses the same object for both. This is possible because String objects are immutable anyway. This would explain the difference in behaviour if you write down the substring manually. In the one case the jvm optimizes, in the other it doesn't.
Use .equals() rather than == because they are strings!
if (last.equals(matchedArray.get(i))) {}
Never use == operator if you wanted to check the value since operator will check the Object reference equality, use equals operator which check on the value not the reference i.e. for (int i=0;i< matchedArray.size();i++){
//run through the arrays
if (last.equals(matchedArray.get(i))) { // Line edited
//add arrays to a data array
ArrayList data = new ArrayList();
data.add(matchedArray1.get(i));
data.add(matchedArray2.get(i));
data.add(matchedArray3.get(i));
data.add(matchedArray4.get(i));
data.add(matchedArray5.get(i));
//put into hash map
map.put(matchedArray.get(i), data);
}
else {
//TODO
System.out.println("DO NOT MATCH :" + last + "-" + matchedArray.get(i));

Using Recursion To Compare Strings To Determine Which Comes First Alphabetically Java

I am trying to write a method that uses recursion to compare the strings str1 and str2 and determine which of them comes first alphabetically (i.e., according to the ordering used for words in a dictionary).
If str1 comes first alphabetically, the method should return int 1.
If str2 comes first alphabetically, the method should return the int 2.
If the two strings are the same, the method should return the int 0.
I know that there is a compareTo method in the Java API but i would like to know how to do this without this
This is what i have so far but i'm not entirely sure how to proceeded
} if (str1.length().equals(str2.length()))
return 0;
} else {
(str.substring(1, str.length()));
Any ideas would be greatly appreciated
Make a method int recursiveCompare(String string1, String string2, int index). Initially call it with index = 0. Compare string1.charAt(index) and string2.charAt(index), and if they're different, return 1 or 2. If they're the same, return recursiveCompare(string1, string2, index + 1).
Of course, you'll have to check the lengths of string1 and string2 before calling charAt(index). If they both reach the end at the same time, they're equal, so return 0. Otherwise, return the number of the one that has ended.
And yeah, recursion is pretty much the worst way to do this, LOL.
No recursion required... (Unless this is specifically required in the homework(?) assignement...)
As this looks a lot like homework, I'll just give a few hints
Use a integer variable, say i, to index from 0 to the length of shorter string.
As long as str1[i] == str2[i], and the last index value hasn't been reached, increment i.
If you do reach the last possible value for the index, then the shorter string comes first (or they are deemed equal if same length...)
Otherwise, compare this first character that differs, and decide which string is first accordingly... Could be as simple as:
return (str1[i] < str2[i]);
If recursion you must... (and it was readily said in other comments, this kind of problem is truly not a logical/valid candidate for recursion...)
The idea is to have a function with this kind of interface:
int RecursCompare(string str1, string str2, int i)
and which calls itself, passing the same values for str1 an str2 and passing the next value for i (i+1), as long as str1[i] == str2[i] AND neither str1 or str2 is at its end.
When this condidtion becomes false, recursion ends, and instead the function returns the appropriate value to signify tha Str1 is alphabetically before or after Str2.
#include<stdio.h>main(){ char str1[100],str2[100]; int i=0,k=0; puts("Enter string 1"); gets(str1); puts("Enter string 2"); gets(str2); i=comp(str1,str2,0); printf("\ncount is %d %d \n",i,strlen(str1)); (strlen(str1)==strlen(str2)) ?( (strlen(str1)==i) ? printf("Both are equal"):printf("Both are Not equal")):printf("Both are Not equal"); }int comp(char s1[], char s2[],int i){ printf("\n%c %c",s1[i],s2[i]); int sum=0,count =1; if((s1[i] != '\0')|| (s2[i]!='\0')) { if (s1[i] == s2[i]) { return (count += comp(s1,s2,++i)); } else { return 0; } } else { return 0; } return count; }

Categories