String Index Out Of Bound Exception error - java

I'm not really sure why I am getting this error. The code is meant to test palindromes disregarding punctuation.
So here is my code:
char junk;
String temp = "";
for (int i = 0; i < txt.length(); i++)
{
junk = txt.charAt(i);
if (Character.isLetterOrDigit(txt.charAt(jumk)))
{
temp += junk;
}
}
txt = temp;
left = 0;
right = txt.length() -1;
while (txt.charAt(left) == txt.charAt(right) && right > left)
{
left++;
right--;
}
java.lang.StringIndexOutOfBoundException : String index out of range 0
at PalindromeTester.main(PalindromeTester.java:35)
and line 35 is as following:
while (txt.charAt(left) == txt.charAt(right) && right > left)

if (Character.isLetterOrDigit(txt.charAt(yP)))
is your problem, yP is a char not a reference to a position.
What you probably meant was:
if (Character.isLetterOrDigit(yP))
Edit: My comment:
Well the value of right would be -1 and charAt would require a an integer greater than 0.. so you should check the length of txt and if it's == 0 then display a message saying an actual word is required.
You should stop execution before you get to this line:
right = txt.length() -1;
This is your fixed code:
do
{
System.out.println("Enter a word, phrase, or sentence (blank line to stop):");
txt = kb.nextLine();
}
while (!txt.equals(""));
txt = txt.toLowerCase();
char yP;
String noP = "";
for (int i = 0; i < txt.length(); i++)
{
yP = txt.charAt(i);
if (Character.isLetterOrDigit(txt.charAt(yP)))
{
noP += yP;
}
}
txt = noP;
left = 0;
right = txt.length() -1;
while (txt.charAt(left) == txt.charAt(right) && right > left)
{
left++;
right--;
}
if (left > right)
{
System.out.println("Palindrome");
cntr++;
}
else
{
System.out.println("Not a palindrome");
}

The variable yP is your character at index i, not an index (as you are using it on the line giving you the error). Change that line to:
if (Character.isLetterOrDigit(yP)) { ...
EDIT FOR THE NEW PROBLEM:
You don't need a while loop to check if the user entered nothing, since you don't want to do something repeatedly in this case (which is what loops are for). Since you only want to do something once, i.e. print out how many palindromes they have found, you can just use an if statement. The structure would look like this:
do {
get user input
if they entered the empty string "" {
print out how many palindromes they have found so far
} else { // they must have entered text, so check for palindrome
your normal palindrome checking code goes here
}
} while (your condition);
EDIT 2:
Try changing
if (left > right)
to
if (left >= right)
Since if left==right, that means they are both on the median character in an odd-length string (e.g. the 'y' in kayak) which means the string is a palindrome.

Related

Recursive method to replace all occurrences of a value in a 2D array

I have created a recursive method that replaces all occurrences of an element in a two dimensional double array. The issue is that I cannot seem to get this working without encountering a stack overflow error. Could someone please look at my code below and show me how to fix this? I have tried setting this up several times over the past few days. Thank you. Note that my arrays are 2 x 3, so the first if means that if you are at column 1 row 2, you are at the end of the array, and in that case you are done searching.
private static int replaceAll(double number, double replacementTerm) {
int i = 0;
int j = 0;
double searchFor = number;
double replace = replacementTerm;
if (i == 1 && j == 2) {
System.out.println("Search complete!");
}
if (twoDimArray2[i][j] == searchFor) {
System.out.println("Replaced An Element!");
twoDimArray2[i][j] = replace;
System.out.println(twoDimArray2[i][j]);
j++;
return replaceAll(searchFor, replace);
}
if (j == twoDimArray2.length) {
i++;
return replaceAll(searchFor, replace);
} else {
j++;
return replaceAll(searchFor, replace);
}
}
i and j should be method parameters instead of local variables so changes to their values can be tracked. Try to move right and down recursively if it does not exceed the bounds of the array. Note that this is much less efficient that iteration with two layers of for loops, as it will check multiple positions in the array more than once; to mitigate this, one can use a visited array to store all positions previous visited so they will not be checked again. See the below code in action here.
private static void replaceAll(double number, double replacementTerm, int i, int j) {
double searchFor = number;
double replace = replacementTerm;
if (twoDimArray2[i][j] == searchFor) {
System.out.println("Replaced An Element!");
twoDimArray2[i][j] = replace;
System.out.println(twoDimArray2[i][j]);
}
if (i == twoDimArray2.length - 1 && j == twoDimArray2[0].length - 1) {
System.out.println("Reached the end!");
return;
}
if (i + 1 < twoDimArray2.length) {
replaceAll(number, replacementTerm, i + 1, j);
}
if (j + 1 < twoDimArray2[0].length) {
replaceAll(number, replacementTerm, i, j + 1);
}
}

Improving Program Efficiency

public class cowcode {
public static void main(String[] args) {
long index = 1000000
String line = HELLO
boolean found = false;
if (index <= line.length())
found = true;
while (!found) {
line += buildString(line);
if (index <= line.length())
found = true;
}
if (found)
System.out.println("" + charAt(line, index-1));
}
public static String buildString(String str){
String temp = "" + str.charAt(str.length()-1);
for (int i = 0; i < str.length()-1; i ++){
temp += str.charAt(i);
}
return temp;
}
public static String charAt(String line, long index){
for (int i = 0; i < line.length(); i ++){
if (i == index)
return line.charAt(i) + "";
}
return "";
}
}
Hey! The code above works perfectly fine. However the only problem is runtime.
The objective of this program is to build a string from "HELLO" (which will eventually have the length of at least size index). This is done by rotating the String to the right ("HELLO" --> "HELLOOHELL", and concatenating the original String and the rotated version together. This process will not stop until the index that the program is looking for is found in the String. (so in this example, the String will become "HELLOOHELLLHELLOOHEL" after going through the loop twice).
Do you guys see anything that could be eliminated/shortened to improve runtime?
What I guess is killing you is all of the String concatenations you're doing in buildString. You can cut it down to this:
public static String buildString(String str){
return str.charAt(str.length()-1) + str.substring(0, str.length()-1);
}
You need to calculate the index without actually building the string. The right half of the composite string it rotated, the left one is not. If You have index in the left half of the string, You can just throw away the right half. Hence You simplified the situation. If You have index in the right half, You can transform it to index in the left half. You just need to undo rotation of the string in the right half. So You rotate the index left by one character. Now You can substract legth of half of the string and You have index in the left half of the string. This situation is already described above. So You shorten the string and start again at the beginning. In the end You end up with the string, that is not composed. It is the original string. Now You can address the characters directly with the index as it is now in range of the string.
index = 1000000 - 1;
line = "HELLO";
int len = line.length();
long len2 = len;
while (len2 <= index) {
len2 *= 2;
}
while (len2 > len) {
long lenhalf = len2 / 2;
if (index >= lenhalf) {
index -= lenhalf;
index -= 1;
if (index < 0) {
index += lenhalf;
}
}
len2 = lenhalf;
}
System.out.println(line.charAt((int)index));

Why will my for loop not read my last char of the string?

I am trying to write a basic java program to compress a java string from an input; such as aabbccdddd, into a2b2c2d4. The program does what I ask except it doesn't process the last char, I am getting an output of a2b2c2 instead of the a2b2c2d4. What am I doing wrong?
for(x = 0, y = 1; x<input.length()-1; x++)
{
if (input.charAt(x) != input.charAt(x+1) && count == 1)
{
System.out.print(input.charAt(x));
System.out.print(count);
}
else if (input.charAt(x) == input.charAt(x+y))
{
count++;
}
else if (input.charAt(x) != input.charAt(x+1) && count >= 2)
{
System.out.print(input.charAt(x));
System.out.print(count);
count = 1;
}
else
{
System.out.println("fail");
}
}
You print the count when the next character is not same as the current one. There is no next character for the last character. That is why it is not displayed in the output.
Approach 1
You should add following two lines after the loop:
System.out.print(input.charAt(input.length()-1));
System.out.println(count);
Approach 2
If you do not have problem with modifying the original input. You can add a additional character in the end of the input. This additional character must be a character which will never appear in the original string. Say it is #
Do this before beginning of the loop:
input += "#";
for(...)
The loop is incorrect, you have "-1" after input.length(). Try:
for(x = 0, y = 1; x<input.length(); x++) {
// CODE HERE...
}
Your for loop ends before you hit a condition that forces you to print out what's being buffered, ie. count of 4 for the current (last) character. You need to print out the last character and the current count after the loop.
The following should do what you want
public static void main(String[] args) throws Exception {
String input = "aabbccdddd";
int count= 1;
int x, y;
for (x = 0, y = 1; x < input.length() - 1; x++) {
char charAtX = input.charAt(x);
char charAtXPlus1 = input.charAt(x + 1);
if ( charAtX != charAtXPlus1 && count == 1) {
System.out.print(input.charAt(x));
System.out.print(count);
}
else if (charAtX == input.charAt(x + y)) {
count++;
}
else if (charAtX != charAtXPlus1 && count >= 2) {
System.out.print(input.charAt(x));
System.out.print(count);
count = 1;
} else {
System.out.println("fail");
}
}
System.out.print(input.charAt(x));
System.out.println(count);
}
You should learn how to use a proper debugger and use proper debugging techniques. For example, I've assigned the value returned by input.charAt(x) to a variable because we reuse that value in the various if-else conditions and because it's easier to see it in a debug window.
You are not able to get the desired result because of the condition
else if(input.charAt(x)!=input.charAt(x+1)&&count>=2)
that fails as there is not character at x+1 location.
So, you could add another condition to check if it's the last character and then go ahead with your code
while (input.charAt(x) != input.length()-1)

some weird stff im running into on java

So im working on java codingbat and this is the question:
Given a string, look for a mirror image (backwards) string at both the beginning and end of the given string.
In other words, zero or more characters at the very begining of the given string, and at the very end of the string in reverse order (possibly overlapping).
For example:
the string "abXYZba" has the mirror end "ab". mirrorEnds("abXYZba") → "ab" mirrorEnds("abca") → "a" mirrorEnds("aba") → "aba" .
My code passed all the test except for the other test, which is not specified. I dont know what's wrong with it.
public String mirrorEnds(String string) {
String input = string, mirror = "";
int length = string.length();
for (int n = 0; n < (length+1) / 2; n++) {
if (input.charAt(n) != input.charAt(length - n - 1)) {
break;
}else if(length%2 == 1 && n == (length - 1)/2){
// System.out.println("length/2 = " );
return input;
}
else {
mirror += input.charAt(n);
}
}
return mirror;
}
You were correct in not needing to go though the entire word, but your logic is more complex than it needs to be, making it harder to find and fix the problem. The root cause of the test failure is in the last return statement. It must return string if the loop completes without breaking. You can fix your code by changing break; to return mirror; and changing the last return mirror; to return input;
The test that is failing is one like this:
mirrorEnds("abba") -> "abba"
A much simpler version of your code can be created like this:
public String mirrorEnds(String string) {
int len = string.length();
for (int i=0; i < len/2; ++i)
if (string.charAt(i) != string.charAt(len - 1 - i))
return string.substring(0, i);
return string;
}
mirrorEnds("abba")?
Anyways, I'm sure you could come up with a better question name than "some weird stuff"...
Since you are dividing n by 2 in your loop termination condition, it will end when halfway through the word. This is enough to tell the word is a palindrome, but not enough to build your output correctly. You have a condition handling palindrome with odd numbers of letter, but not even numbers of letters. I believe the failing test will be of the form "abba", where I believe what you have will return "ab", instead of "abba".
If you change you loop to:
for (int n = 0; n < length; n++) {
I believe it should be doing what you want. This also makes the short circuit case unnecessary, so:
for (int n = 0; n < length; n++) {
if (input.charAt(n) != input.charAt(length - n - 1)) {
break;
}
else {
mirror += input.charAt(n);
}
}
The first test I tried was with the string "abba" which fails. It returns ab, and not abba. As femtoRgon mentioned, you're not going through the entire word, which may some times be necessary. femtoRgon's solution works, as well as taking a slightly different approach to iterating through the word as follows:
public String mirrorEnds(String string) {
boolean matches = true;
StringBuilder mirrorEnd = new StringBuilder();
int index = 0;
while (matches && index < string.length()) {
if (string.charAt(index) == string.charAt(string.length() - index - 1))
mirrorEnd.append(string.charAt(index));
else
matches = false;
index++;
}
return mirrorEnd.toString();
}
public String mirrorEnds(String string) {
String comp="";
for(int i=0; i<string.length(); i++){
if(string.charAt(i)==string.charAt(string.length()-(i+1)))
comp= comp+ string.charAt(i);
else break;
}
return comp;
}

Using a binary search algorithm as a basis to implement a binary insert

I'm trying to implement a binary insert method.
Currently this method is very simple, it takes an argument, in a while loop it searches for an element that is bigger than the argument (in this case a String that is the last name of a person), it breaks once it finds it and shifts the rest of the array to the right. Then the argument is inserted at the position of breaking.
I tried changing it to one that would search for the insert position by borrowing from the binary search algorithm. However, I just can't get it to work.
Could you please let me know what I'm doing wrong? Here's my code:
public void insert(Person person)
{
String lastName = person.getLastName();
int position = -1; // the position from which the array will be shifted to the right and where the argument will be inserted, will be assigned properly below
int lowerBound = 0;
int upperBound = numElems - 1;
int currIt;
if (numElems == 0)
array[0] = person; // if array empty insert at first position
else
{
while (true)
{
currIt = (lowerBound + upperBound) / 2; //the item to compare with
int result2 = 0;
int result1 = array[currIt].getLastName().compareTo(lastName);
if (array[currIt+1] != null) // if the next element is not null, compare the argument to it
result2 = array[currIt+1].getLastName().compareTo(lastName);
if (currIt == 0 && result1 > 0) // this is when the argument is smaller then the first array element
{
position = 0;
break;
}
// if the position to insert is the last one, or we have found a suitable position between a smaller and a bigger element
else if ( (result1 < 0 && (currIt == numElems-1)) || (result1 < 0 && result2 > 0) ) {
position = currIt+1;
break;
}
else
{
if (result1 < 0) // the place to put it should be in the upper half
lowerBound = currIt + 1;
else
upperBound = currIt - 1; //in the lower half
}
}
}
// position has been set to anything else other -1, then we have found our spot, probably a redundant check but useful for debugging
if (position != -1)
{
//shift array to the right and insert element
for (int j = numElems; j > position; j--)
array[j] = array[j-1];
System.out.println("Inserted an element");
array[position] = person;
numElems++;
}
}
Your "probably [] redundant check" prohibits initial inserting. Position is -1 the first time.
Setting position to 0 at the top, should fix the problem.

Categories

Resources