Find the largest ASCII character in a string recursively - java - java

I am trying to write a method which returns the largest character in a string according to ASCII (a character is greater if it comes later in the ASCII table). This is what I have so far,
public char maxChar (String s) {
char[] characters = s.toCharArray();
char character = characters[0];
return maxCharHelper(characters, character, 0);
}
private static char maxCharHelper(char[] characters, char character, int index) {
if (index >= characters.length - 1) {
return character;
}
if (characters[index] > character) {
character++;
}
return maxCharHelper(characters, character, ++index);
}
I receive three issues which are:
1) when string "helloWORLD" is used it returns 107(k) instead of 111(o)
2) when string "helloworld" is used it returns 110(n) instead of 119(w)
lastly, 3) when string "abbxL ? 12 x5y #" is used it returns 101(e) instead of 121(y)
Not sure why this happens, is there anything wrong with my code? Any help is appreciated.

replace character++; with character = characters[index] and it will work!
and replace index >= characters.length - 1 with index > characters.length - 1, else the last character wont be checked.

Related

How do I check if the preceding letter of the word that I am looking for in a string exist? Recursion

I am currently creating a java program that counts the number of occurrences of a specific word in a string using recursion, however, if the preceding letter is an 'a', the count won't be incremented. I cannot find a way to check the preceding letter before the first letter of the word I am looking for. I tried using indexOf then subtracting one to check the preceding letter, but it won't work.
Here's my working function at the moment:
//The value of text is abrichbbarichacrich
//While the value of find is rich
//Expected output should be 2
static int Count(String text, String find) {
if (text.length() == 0 || text.length() < find.length()) {
return 0;
}
if (text.contains(find)) {
return 1 + Count(text.replaceFirst(find, ""), find);
}
return 0;
}
Here's my second version, but it gives me a StringIndexOutOfBoundsException and the output should be 2, but instead it gives me an output of 3.
if (text.length() == 0 || text.length() < find.length()) {
return 0;
}
if (text.contains(find)) {
int index = text.indexOf(find) - 1;
if (text.charAt(index) == 'a')
return Count(text.replaceFirst(find, ""), find);
return 1 + Count(text.replaceFirst(find, ""), find);
}
Any help would be appreciated :)
Correct if else condition .replaceFirst() method returns the updated string.We have to update the string.
static int Count(String text, String find) {
if (text.length() == 0 || text.length() < find.length()) {
return 0;
}
if (text.contains(find)) {
int index = text.indexOf(find) - 1;
text=text.replaceFirst(find, "");
if (index!=-1&&text.charAt(index) != 'a'){
return 1+Count(text,find);
}
else
return Count(text,find);
}
return 0;
}
Just working the answer out in pseudocode, here's how I'd approach the problem.
Define a helper function as follows:
countHelper(string text, string find, bool previousWasNotA) =
if (length of text < length of find) {
0
} else {
let prefixEqualsFind = if (previousWasNotA and find is a prefix of text) {
0
} else {
1
}
in
prefixEqualsFind + countHelper(text without first character, find, first character of text != 'a')
}
count(string text, string find) = countHelper(text, find, true)
The idea here is that countHelper(text, find, previousWasNotA) returns the number of occurences of find in text, not counting any occurences where find is directly preceded by an a, and not counting an occurence of find at the very beginning of text if previousWasNotA is false.
In Java, this look like
static int countHelper(String text, String find, bool previousWasNotA) {
if (text.length() < find.length()) {
return 0;
} else {
const int prefixEqualsEnd = previousWasNotA && text.startsWith(find) ? 1 : 0;
return prefixEqualsEnd + countHelper(text.substring(1), find, text.charAt(0) != 'a');
}
}
static int count(String text, String find) {
return countHelper(text, find, true);
}
Note that this doesn't work for the case of find = "". But in that case, it's not clear the problem even has an answer at all, since we can put infinitely many ""s together to make a single "" and hence infinitely many ""s are contained in any string at all.
Also note that this is not an asymptotically optimal algorithm. For that, you'll want to use the KMP algorithm.

How do I merge the indexes in an array to create 1 main array/String in Java?

The input is supposed to be
ABDECDEABCAADD
ABCDE
The first line is a random piece of text. The second line is a circular shift.
The output is supposed to be:
yes
This program is supposed to take a piece of text and determine if it contains a circular shift based on the second line of input.
A circular shift is when you take the first letter of the string and move it to the back of the string. Thus creating a new string.
If the text entered contains a circular shift from the second line then the output would be yes otherwise it would be no.
Since ABDECDEABCAADD contains DEABC which is a shift of ABCDE the output would be yes.
Scanner scan = new Scanner(System.in);
String text;
System.out.println("Enter text:");
text=scan.nextLine();
System.out.println("Enter shift:");
String shift=scan.nextLine();
String[] split1=shift.split("");
String[] array2=new String[split1.length];
String[] array3=new String[split1.length];
for(int z=0;z<split1.length;z++) {
array2[split1.length-1]=split1[0];
for(int x=0;x<split1.length-1;x++) {
array2[x]=split1[x+1];
array3[0]=array2[x]+array2[x+1];
}
//if(text!=)
}
for(int y=0;y<array2.length;y++) {
System.out.print(array2[y]);
}
How I wanted to tackle this question was to first get the input then separate the second line into characters so I can create a circular shift. Once I'm done with that I would take the new order of characters and merge them to create a string.
I need help when it comes to the merging but also with how I can create multiple shifts.
If you see this pleas help.
Don't create shifts. For best performance, do it like this:
String text = "ABDECDEABCAADD";
String shift = "ABCDE";
Scan text for the first character in shift, i.e. scan for 'A'.
When found, match as many of the following characters as possible.
If not all characters in shift were matched, get the count of missing characters.
Grab that many characters from before the found 'A', if available.
If found and they match the remaining characters in shift, your search is done.
Repeat from step 1, searching for the next 'A'.
Example
static int matchShift(String text, String shift) {
if (shift.isEmpty())
throw new IllegalArgumentException("Shift value is empty");
char first = shift.charAt(0);
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == first) {
int j = 1;
while (j < shift.length() && i + j < text.length()
&& text.charAt(i + j) == shift.charAt(j))
j++;
if (j == shift.length())
return i; // Match found at index 'i', with unshifted value
int start = i + j - shift.length();
if (start >= 0 && text.substring(start, i).equals(shift.substring(j, shift.length())))
return start; // Match found at index 'start', with shifted value
}
}
return -1; // No match found
}
Test
public static void main(String[] args) {
test("ABDECDEABCAADD", "ABCDE");
}
static void test(String text, String shift) {
int i = matchShift(text, shift);
if (i == -1)
System.out.printf("'%s', '%s': No Match%n", text, shift);
else
System.out.printf("'%s', '%s': Match at index %d ('%s')%n",
text, shift, i, text.substring(i, i + shift.length()));
}
Output
'ABDECDEABCAADD', 'ABCDE': Match at index 5 ('DEABC')
It could also have responded with Match at index 4 ('CDEAB'). If that is important, change the logic to search for the last character instead of the first, match backwards, then compare substrings after.

Remove consecutive duplicate characters from a String

I'm trying to remove duplicate characters from a string recursively.
I don't know how to fix this code to remain the first character when characters have different cases.
/**
* Remove consecutive duplicate characters from a String. <br>
* Case should not matter, if two or more consecutive duplicate <br>
* characters have different cases, then the first letter should be kept.
* #param word A word with possible consecutive duplicate characters.
* #return A word without any consecutive duplicate characters.
*/
public static String dedupeChars(String word){
if ( word.length() <= 1 )
return word;
if( word.substring(0,1).equalsIgnoreCase(word.substring(1,2)) )
return dedupeChars(word.substring(1));
else
return word.substring(0,1) + dedupeChars(word.substring(1));
}
You were on the right track, but your logic was a bit off. Consider this version, with explanation below the code:
public static String dedupeChars(String word) {
if (word.length() <= 1) {
return word;
}
if (word.substring(0,1).equalsIgnoreCase(word.substring(1,2))) {
return dedupeChars(word.substring(0, 1) + word.substring(2));
}
else {
return word.substring(0,1) + dedupeChars(word.substring(1));
}
}
System.out.println(dedupeChars("aaaaBbBBBbCDdefghiIIiJ"));
This prints:
aBCDefghiJ
For an explanation of the algorithm, your base case was correct, and for a single character word, we just return than character. For the case where the first character be identical to the second one, we splice out that second character and then recursively call dedupeChars() again. For example, here is what happens with the input string shown above:
aaaaBbBBBbCDdefghiIIiJ
aaaBbBBBbCDdefghiIIiJ
aaBbBBBbCDdefghiIIiJ
aBbBBBbCDdefghiIIiJ
That is, we splice out duplicates, always retaining the first occurrence, until there are no more duplicates.
By the way, in practice you might instead want to use regex here, for a much more concise solution:
String input = "aaaaBbBBBbCDdefghiIIiJ";
input = input.replaceAll("(?i)(.)\\1+", "$1");
System.out.println(input);
This prints:
aBCDefghiJ
Here we just tell the regex engine to remove all duplicates of any single letter, retaining only the first letter in the series.
I have a different way to achieve your purpose
and I think your code is too expensive to remove duplicate characters(ignore uppercase or lowercase,just keep the first one).
public static String removeDup(String s) {
char[] chars = s.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = chars.length - 1; i > 0; i--) {
if (chars[i] == chars[i - 1]) {
continue;
}
if (chars[i] < 97) {
if (chars[i] == (chars[i - 1] - 32)) {
continue;
}
} else {
if (chars[i] == (chars[i - 1] + 32)) {
continue;
}
}
sb.append(chars[i]);
}
sb.append(chars[0]);
return sb.reverse().toString();}
For the input "aaaaBbBBBbCDdefghiIIiJ" the output will be "aBCDefghiJ"

how do i iterate through a string of characters to find a specific character?

I am having a hard time figuring out why my code will not work. I am trying to stop the output on a specific letter, but it keeps iterating through the entire string instead. This is what I have,
public static char stringIterator(String string) {
System.out.println(string);//Keep this line
char lastChar = string.charAt(string.length() - 1);
if (lastChar == 'M') {
return lastChar;
}
else if (string.length() == 1) {
return lastChar;
}
else {
return stringIterator(string.substring(0, string.length() - 2));
}
}
if you want to just see if it has it then you would use
string.contains('char');
if you want to traverse/iterate then
for( int i = 0; i < string.length(); i++)
if(string.at(i) == '#')
{ //whatever you want here
}
You might be over-thinking this...
Java has very good resources for dealing with Strings, check out the docs:
Java String Documentation
if (string.contains('m')){
//dostuff
}
if (string.endsWith('m')){
//dostuff
}
etc.
As for your iteration problem, you'll have to post the rest of your code, as it looks like your Loop is Calling stringIterator(String) from somewhere outside this method.
(It's not really a stringIterator if it doesn't iterate anything)
Also this last line of code:
return stringIterator(string.substring(0, string.length() - 2));
Is recursive (calls itself)... which can cause you trouble. There's certainly uses for recursion, finding something in a 1d array is not one of those uses. Assuming your loop is working properly this could be what's preventing you from stopping the output.
public String substring(int begIndex, int endIndex) - returnsĀ a new stringĀ that is a substring of the string
Parameters :
beginIndex : the begin index, inclusive.
endIndex : the end index, exclusive.
(eg): String string = "NAME"
string.substring(0, string.length() - 2) - returns "NA"
string.substring(0, string.length() - 1) - returns "NAM" . Use this, thus you will be able to subtract the last character of the string.
Iterative approach
public static char stringIterator(String string) {
char lastChar = string.charAt(0);
for(int i = string.length()-1 ;i>=0;i--) {
System.out.println(string);//Keep this line
lastChar = string.charAt(i);
if (string.length() == 1 || lastChar == 'M') {
break;
} else {
string = string.substring(0, i);
}
}
return lastChar;
}

Java String trim has no effect

Java String trim is not removing a whitespace character for me.
String rank = (some method);
System.out.println("(" + rank + ")");
The output is (1 ). Notice the space to the right of the 1.
I have to remove the trailing space from the string rank but neither rank.trim() nor rank.replace(" ","") removes it.
The string rank just remains the same either way.
Edit: Full Code::
Document doc = Jsoup.connect("http://www.4icu.org/ca/").timeout(1000000).get();
Element table = doc.select("table").get(7);
Elements rows = table.select("tr");
for (Element row: rows) {
String rank = row.select("span").first().text().trim();
System.out.println("("+rank+")");
}
Why can't I remove that space?
The source code of that website shows the special html character . Try searching or replacing the following in your java String: \u00A0.
That's a non-breakable space. See: I have a string with "\u00a0", and I need to replace it with "" str_replace fails
rank = rank.replaceAll("\u00A0", "");
should work. Maybe add a double \\ instead of the \.
You should assign the result of trim back to the String variable. Otherwise it is not going to work, because strings in Java are immutable.
String orig = " quick brown fox ";
String trimmed = original.trim();
The character is a non-breaking space, and is thus not removed by the trim() method. Iterate through the characters and print the int value of each one, to know which character you must replace by an empty string to get what you want.
Are you assigning the String?
String rank = " blabla ";
rank = rank.trim();
Don't forget the second assignment, or your trimmed string will go nowhere.
You can look this sort of stuff up in the API as well: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#trim()
As you can see this method returns a String, like most methods that operate on a String do. They return the modified String and leave the original String in tact.
I had same problem and did little manipulation on java's trim() method.
You can use this code to trim:
public static String trimAdvanced(String value) {
Objects.requireNonNull(value);
int strLength = value.length();
int len = value.length();
int st = 0;
char[] val = value.toCharArray();
if (strLength == 0) {
return "";
}
while ((st < len) && (val[st] <= ' ') || (val[st] == '\u00A0')) {
st++;
if (st == strLength) {
break;
}
}
while ((st < len) && (val[len - 1] <= ' ') || (val[len - 1] == '\u00A0')) {
len--;
if (len == 0) {
break;
}
}
return (st > len) ? "" : ((st > 0) || (len < strLength)) ? value.substring(st, len) : value;
}
Trim function returns a new copy of the string, with leading and trailing whitespace omitted.
rank = rank.trim();// This will remove and save rank without leading and trailing spaces
will give the result you want.
Replace method will not work if you pass empty string for replacement.
Since String in java are immutable ie they cannot be changed. You need to reassign it to some temporary string. And then using that string you can convert it into int.
String temp=rank.trim()
int te= Integer.parseInt(temp)

Categories

Resources