Finding the original index after stripping a string - java

I have a function like the following:
int getIndex(String noisyString) {
String quietString = noisyString.replaceAll("[^a-z]", "");
int quietStringIndex = findIndexInQuietString(quietString);
return originalIndexInNoisyString; // ???
}
After stripping a string of all non alphabetical characters, I find an arbitrarily chosen index inside the stripped string. How can I convert this index back to one that can be used for the unstripped string?

It sounds like you are trying to get the index in the non-filtered string of the same character at the chosen index in the filtered string.
(ie. you have a String s1 = "abc123def" s1.replaceAll() = "abcdef". You want to get the original index of the character at index 4 in the filtered String.
The character at index 4 in the filtered String is e. Its index value in the unfiltered String is 7.)
The simplest brute force way to do this would be to use a counter to go through the string keeping track of what index you are up to, meanwhile having a separate counter variable to keep track of how many characters that have been passed that are valid for the filtered string.
public static int getOriginalIndex(String s, int index){
if (index > s.replaceAll("[^a-z]", "").length()) {
throw new IllegalArgumentException("index is invalid");
}
int counter;
int validCharCounter = 0;
for (counter = 0; counter < s.length() && validCharCounter < index; counter++) {
if (s.charAt(counter) >= 'a' && s.charAt(counter) <= 'z')
validCharCounter++;
}
return counter;
}

Related

Counting a specific value

I am trying to create a method that will count number of zeros in a statement/numbers (numOfZero), that a string as input and returns the number of occurrence of ‘0’ in the string.
And if there is no zero it should return zero. I have used String.length() and String.CharAt(int index). but getting some errors. Any help?
public static int countOccurance(int num){
int count = 0;
String aux = Integer.toString(num); //conversion Integer to string.
for(int i= 0; i<aux.length(); i++){
if(aux.charAt(i) == '0'){
count++;
}
}
return count;
}
This is the method. It counts how many zeros there are in your number. Try it!

Substring a String depending on int [duplicate]

This question already has answers here:
Java: How to split a string by a number of characters?
(11 answers)
Closed 5 years ago.
I wanted to substring a String depending on int that I will passed on the method. I used nested loop for this. But everytime it loops I wanted to substring only from last substring to int the I passed in the method and get also the last string. How can I achieve this?
private static void input(String s, int I)
{
List list = new ArrayList();
for(int a = 0; a < s.length(); a++)
{
for(int position = 0; position < s.length(); position++)
{
if(position + a + I <= s.length())
{
list.add(s.substring(position, position + a + I));
}
}
}
}
input("abaca", 2);
Expected output: "ab", "ac", "a"
You don't need nested loops. Just iterate over the String once, and add an I character substring in each iteration.
Note that a is the starting index of the current substring, and it therefore incremented by I in each iteration.
The last substring may have a shorter length. If a + I > s.length(), the last index of the last substring will be s.length() - 1 instead of a + I - 1.
for(int a = 0; a < s.length(); a+=I) {
list.add(s.substring(a, Math.min(a + I, s.length())));
}
This produces
[ab, ac, a]
for input("abaca", 2).
You can also simply split the string:
private static void input(String s, int i){
List list = Arrays.asList(s.split("(?<=\\G.{"+i+"})"));
System.out.println(list);
}
\\G means The end of the previous match
?<= means positive lookbehind
Thanks to positive lookbehind (?<=) it will split on all zero length strings (without cutting off anything from the input string) preceded by where previous match ends (\\G) followed by i signs (.{"+i+"}).
It's really better to completely rewrite your code, but if you want to save your structure(even though it's not correct), just remove 1 loop and do something like this:
private static void input(String s, int I) {
List list = new ArrayList();
for (int position = 0; position < s.length();position += I) {
if (position + I <= s.length()) {
list.add(s.substring(position, position + I));
} else {
list.add(s.substring(position, s.length()));
return;
}
}
}

Matching subsequence of length 2 (at same index) in two strings

Given 2 strings, a and b, return the number of the positions where they contain the same length 2 substring. For instance a and b is respectively "xxcaazz" and "xxbaaz" yields 3, since the "xx", "aa", and "az" substrings appear in the same place in both strings.
What is wrong with my solution?
int count=0;
for(int i=0;i<a.length();i++)
{
for(int u=i; u<b.length(); u++)
{
String aSub=a.substring(i,i+1);
String bSub=b.substring(u,u+1);
if(aSub.equals(bSub))
count++;
}
}
return count;
}
In order to fix your solution, you really don't need the inner loop. Since the index should be same for the substrings in both string, only one loop is needed.
Also, you should iterate till 2nd last character of the smaller string, to avoid IndexOutOfBounds. And for substring, give i+2 as second argument instead.
Overall, you would have to change your code to something like this:
int count=0;
for(int i=0; i < small(a, b).length()-1; i++)
{
String aSub=a.substring(i,i+2);
String bSub=b.substring(i,i+2);
if(aSub.equals(bSub))
count++;
}
}
return count;
Why I asked about the length of string is, it might become expensive to create substrings of length 2 in loop. For length n of smaller string, you would be creating 2 * n substrings.
I would rather not create substring, and just match character by character, while keeping track of whether previous character matched or not. This will work perfectly fine in your case, as length of substring to match is 2. Code would be like:
String a = "iaxxai";
String b = "aaxxaaxx";
boolean lastCharacterMatch = false;
int count = 0;
for (int i = 0; i < Math.min(a.length(), b.length()); i++) {
if (a.charAt(i) == b.charAt(i)) {
if (lastCharacterMatch) {
count++;
} else {
lastCharacterMatch = true;
}
} else {
lastCharacterMatch = false;
}
}
System.out.println(count);
The heart of the problem lies with your usage of the substring method. The important thing to note is that the beginning index is inclusive, and the end index is exclusive.
As an example, dissecting your usage, String aSub=a.substring(i,i+1); in the first iteration of the loop i = 0 so this line is then String aSub=a.substring(0,1); From the javadocs, and my explanation above, this would result in a substring from the first character to the first character or String aSub="x"; Changing this to i+2 and u+2 will get you the desired behavior but beware of index out of bounds errors with the way your loops are currently written.
String a = "xxcaazz";
String b = "xxbaaz";
int count = 0;
for (int i = 0; i < (a.length() > b.length() ? b : a).length() - 1; i++) {
String aSub = a.substring(i, i + 2);
String bSub = b.substring(i, i + 2);
if (aSub.equals(bSub)) {
count++;
}
}
System.out.println(count);

Swap numbers in a string

I've the below program.
public class swapping {
public static void main(String[] args) {
String num = "31254";
int max = Integer.MIN_VALUE, maxIndex = 0;
for (int i = 0; i < num.length(); i++) {
if (num.charAt(i) > max) {
max = num.charAt(i);
maxIndex = i;
}
}
swap(num, num.charAt(0), maxIndex);
}
private static void swap(String num, char charAt, int maxIndex) {
System.out.println("number is " + num + " Initial char is " + charAt
+ " Maximum is " + maxIndex);
char t = charAt;
char s = num.charAt(maxIndex);
System.out.println("numbers:" + t + " " + s);
char temp = t;
t = s;
s = temp;
System.out.println("Final string after swap is " + num);
}
}
here my aim is to get the maximum number in the string to be swapped with the first number in the string. i.e. I want to convert 31254 to 51234. But i'm unable to know how to do this.
number is 31254 Initial char is 3 Maximum is 3
numbers:3 5
Final string after swap is 31254
Here the swapping is not getting done, the previous number is getting printed. please let me know how to print the desired output.
Thanks
Pay attention what you are passing to the method.
You are passing the actual character in the first and max position: 3 and 5 in this case.
But then, after you print them, you call:
char t = num.charAt(initial);
char s = num.charAt(max);
charAt expects the index of the character in the string. The index should be an integer, but you are passing it a char value (the character 3 and the character 5).
Now, in Java, characters are considered numbers between 0 and 65535 - the unicode value of the character. So it allows you to pass a character where you should have passed an integer. The unicode value of 3 is 51, and for 5 it's 53. So you are actually telling it "give me the character in the string num which is in position 51".
This is not what you intended.
Instead of doing that, you should make the method accept the index of the first character and the index of the max character. Then, using charAt will be correct. But pay attention to also use charAt for your print at the beginning.
private static void swap(String num, int initialIndex, int maxIndex) {
...
}
Your other problem is that you are not actually swapping the characters inside the string.
What you did was swap the variables that contain the two characters, t and s. So now t contains what s contained, and s contains what t contained.
However, this has no bearing on the original string num. You have not done anything with the string itself.
One thing to remember is that in Java, you cannot change a string. It's immutable. If you have a string object, Java doesn't give you any way to change things inside it. It only lets you read parts of it, not write.
What you can do is assign a new string value to num. In this new string, you will put the value of the max character in the 0 position, and put the value of what was in the first position, in the max character position. And you'll copy all the other characters in the same positions where they were.
So you'll need to create a temporary string, loop on the original string character by character, and in each position, ask yourself "what character should I add to my new string at this round?". And then add that character to the string with a + operator.
Finally, assign the new, temporary string to num.
(Note: there are more efficient ways to do this in Java, like using a StringBuffer or StringBuilder, but I get the impression that you are not there yet in your studies of Java).
try the below program.
String num = "31254";
int maxIndex = 0;
char maxString = num.charAt(0);
for (int i = 1; i < num.length(); i++) {
if (num.charAt(i) > maxString) {
maxString = num.charAt(i);
maxIndex = i;
}
}
System.out.println(maxString);
System.out.println(maxIndex);
String str1 = num.substring(1,maxIndex);
String str2 = num.substring(maxIndex+1,num.length());
String str3 = num.charAt(maxIndex)+str1+num.charAt(0)+str2;
System.out.println(str3);
Initial is a char. charAt use an integer, so the char will converted in the acii code of 3 wich is 51. So your line is equals to `num.charAt(51) and that is out of range.
So hyou have to change the signature of your mathod to private static void swap(String num, int initial, int max)
Here's how I would do it in just 3 lines. Note that for digits, chars are 1 byte each.
byte[] array = number.getBytes();
Arrays.sort(array);
number = number.replaceFirst("(.)(.*?)(" + (array[array.length - 1] - '0') + ")", "$3$2$1");
Not only is this code quite terse - using regex to perform the swap in one statement - it also automatically handles the edge case of the largest digit being at the start (in which case no match/replacement will be made).
Here's some test code:
String number = "31254";
byte[] array = number.getBytes();
Arrays.sort(array);
number = number.replaceFirst("(.)(.*?)(" + (array[array.length - 1] - '0') + ")", "$3$2$1");
System.out.println(number);
Output:
51234

Find all substrings of a string - StringIndexOutOfBoundsException

I created class Word. Word has a constructor that takes a string argument and one method getSubstrings which returns a String containing all substring of word, sorted by length.
For example, if the user provides the input "rum", the method returns a
string that will print like this:
r
u
m
ru
um
rum
I want to concatenate the substrings in a String, separating them with a newline ("\n"). Then return the string.
Code:
public class Word {
String word;
public Word(String word) {
this.word = word;
}
/**
* Gets all the substrings of this Word.
* #return all substrings of this Word separated by newline
*/
public String getSubstrings()
{
String str = "";
int i, j;
for (i = 0; i < word.length(); i++) {
for (j = 0; j < word.length(); j++) {
str = word.substring(i, i + j);
str += "\n";
}
}
return str;
}
But it throws exception:
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1911)
I stuck at this point. Maybe, you have other suggestions according this method signature public String getSubstrings().
How to solve this issue?
Analysis of Exception:
From Java7 Docs of StringIndexOutOfBoundsException
public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException
Thrown by String methods to indicate that an index is either negative or greater than the size of the string.
From Java 7 Docs of substring
public String substring(int beginIndex,int endIndex)
Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.
I guess this: length of the substring is endIndex-beginIndex comes into String index out of range: -1. I have tested with multiple cases holding my assumption true but appreciate any other proof.
For -1: "rum".substring(2,1); will give you String index out of range: -1
Parameters:
beginIndex - the beginning index, inclusive.
endIndex - the ending index, exclusive.
Cause of StringIndexOutOfBoundsException:
In the given code snippet, substring is trying to fetch string which has endIndex more than the total length of String (i+j will exceed the total length of string):
str = word.substring(i, i + j);
Consider the case when i=2 and j=2 for word "rum"
then str=word.substring(2, 4);
would not be possible
Solution similar to code snippet given in Question:
This should solve the problem:
public String getSubstrings()
{
String str="",substr = "";
for (int i = 0; i < word.length(); i++) {
for (int j = 0; i+j <= word.length(); j++) { //added i+j and equal to comparison
substr = word.substring(j, i + j); //changed word.substring(i, i + j) to word.substring(j, i + j)
if("".equals(substr))continue; //removing empty substrings
str += substr; //added concatenation + operation
str += "\n";
}
}
return str+word;
}
Test Case:
For word="rum", this will give output:
r
u
m
ru
um
rum
Your logic seems convoluted , the source of exception:
str = word.substring(i, i + j);
Consider your i and j both equals word.length()-1 , then the substring() will fail.
You can simply do :
public String getSubstrings(String word){
StringBuilder sub= new StringBuilder();
for( int i = 0 ; i < word.length() ; i++ )
{
for( int j = 1 ; j <= word.length() - i ; j++ )
{
sub .append(word.substring(i, i+j)).append("\n");
}
}
return sub.toString();
}
Note: Consider using StringBuilder instead of String if you will do lots of concatenation on String.
I realize I'm a little late to this party, and I'm a very new programmer, myself -- but I was running into the same error last night while trying to write a similar method.
For me, it helped to rename the counter variables of the nested for loops to names that described what they are keeping track of. For the outer loop, I used int subLength, and for the inner loop, I used int position (starting position). I'm sure there are other ways of doing this, but I was happy with my solution. Here is some pseudocode that I hope will help someone else who looks this question up:
for each possible substring length 1 up to and including the original word length:
generate substrings starting at the 0th position, and then starting at each
proceeding letter up to but not including (word.length() - (subLength - 1))

Categories

Resources