Finding palindrome String throws StringIndexOutOfBoundsException, possible cause? - java

Provided a String, my objective is to check if I can make that String a palindrome string even after re-arranging the characters.
For eg: aaabbbb can be made palindrome by changing to : bbaaabb
So what I did try is to compare all the permutations of the string with its reverse, if it exists, print a YES! . And here is the code so far:
private static void permutation(String prefix, String str)
{
temp.setLength(0); //temp is a StringBuilder
int n = str.length();
if((n==0) && (str.charAt(0)==str.charAt(n-1)))
{
temp.append(prefix);
temp.reverse();
if(prefix.equals(temp.toString()))
{
System.out.println("YES");
System.exit(0);
}
}
else
{
for(int i=0;i<n;i++)
permutation(prefix+str.charAt(i),str.substring(0,i)+str.substring(i+1,n));
}
}
Now the problem is, at runtime I get a java.lang.StringIndexOutOfBoundsException at this line: permutation(prefix+str.charAt(i),str.substring(0,i)+str.substring(i+1,n));
What might be possibly causing this?

This line will give you the exception too:
if((n==0) && (str.charAt(0)==str.charAt(n-1)))
If n==0 then the string is empty, and charAt(0) will fail. Not sure what you're testing here.

I'm not going to debug this for you, but I will suggest a process for how to debug this kind of thing yourself.
Identify the problem. All of the detail about the palindromes is irrelevant. The problem is a java.lang.StringIndexOutOfBoundsException when calling one of the methods on the String.
Narrow in on exactly what's failing. There are several method calls in the line that is failing. If it's not obvious which method call is the problem, either single-step through it with a debugger or break that line into several lines, e.g. by creating intermediate variables to hold intermediate state.
Reproduce the problem in a simplified example. Create a new class with a main() method or write a unit test and write code that shows the problem. Remove everything that isn't absolutely essential to show the problem.
Fix your example. Once you've isolated the problem and read the documentation, it will probably be obvious how to fix it. If it's not, and you're still stuck, post the simple example on Stack Overflow and explain what you are expecting and what you're getting.
Fix your code. Apply the same fix to your original code.

String index out of bound exception -This exception is thrown by the methods of the String class, in order to indicate that an index is either negative, or greater than the size of the string itself.
In above code you are calling permutation() method recursively .
Let's say we passed String str="xy" and prefix as "" to permutation() method first time.
As its length is more than 0 it will come to the else block.
In else block we are looping str with its length.
Here length i.e n is 2.
In first loop, i=0. So prefix + str.charAt(i) will give "" + "x" = "x" and str.substring(0,i)+str.substring(i+1,n)
will give str.substring(0,0)+str.substring(0+1,2)=""+"y"="y".
Now again we are passing these values to permutation() method; i.e. permutation("x","y").
So the time when you passed these value in method, at that time instantly string str became "y" and string prefix became "x"
but still you are in loop, and in second loop i=1 and prefix+str.charAt(1) i.e. "x"+"y".charAt(1) will throw exception.
Here you can see string str="y", length is 1 and we are trying to get char at position 1. This is why you got this exception.

Related

How can I read a file and store its objects into my custom linked list?

Basically, I am not using any of the Java API classes such as ArrayLists or LinkedLists, as I have created my own custom linked list class which in this case is named FoodList. I am trying to figure out a way to read each line from a file where each line is an object, and store it in FoodList.
I've looked at many examples of reading files online, but none of them were for a custom linked list.
package lab9;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Console {
FoodList x = new FoodList();
public Console(){
this.x = new FoodList();
}
public void Display() {
System.out.println("============================================================================");
System.out.println("Name Food Group Calories Daily percentage ");
System.out.println("============================================================================");
File f = new File("food.txt");
try {
Scanner scan = new Scanner(f); //What I tried to do to read in objects from file
while(scan.hasNextLine()){
String line = scan.nextLine();
String[] details = new String[4];
details = line.split(" ");
String name = details[0];
String group = details[1];
int calories = Integer.parseInt(details[2]);
double percentage = Double.parseDouble(details[3]);
x.add(new Food(name, group, calories, percentage));
}
System.out.println(x);
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("Not working");
}
}
}
The code below is also giving me an out of bounds exception at line 30. Should I try to read the objects differently or fix this?
NOTE: PLEASE do not mark this as a duplicate, I have already made my String[] details variable to hold more than 1 array.
This was originally closed as a dup of What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
This answered at least part of the problem. You were getting that exception, and the dup does explain what causes the exception, though it doesn't address the specifics of your particular code.
(Aside: there are a lot of people, including me, who believe that questions like this where the OP expects someone else to debug their code are best answered by pointing the OP at somewhere with the information they need to find the solution for themselves. Directly solving the problem for the OP deprives the OP of the learning exercise of finding the solution themselves, and leads to people getting qualifications without actually knowing how to solve programming problems for themselves.)
Then you say this:
NOTE: PLEASE do not mark this as a duplicate, I have already made my String[] details variable to hold more than 1 array.
(It is a duplicate ... according to that is normally meant here by duplicate!)
That is the wrong fix. 1) It means that you didn't use the clues provided to understand what the problem really was. 2) It also implies a significant misconception about what happens when you assign an array.
Circling back, here is the logic process for diagnosing and fixing the problem:
Q: What has happened?
A: Got an exception.
Q: What does the exception mean?
A: Read javadocs, google it.
Q: Where did you get the exception?
A: You can get that from the stack trace (line number) and looking at the code.
Q: Why did you get the exception?
A: There will be clues in the exception message and the line what the exception was thrown. In this case it would say that you attempted to access element zero of an array whose length is zero. I am assuming that you haven't added / removed lines and line 30 is this one:
String name = details[0];
Clearly you cannot access the zero'th element of an empty array. (Why? review your notes on arrays and how they are indexed!)
That gives you two things to look at:
Why was the array's length zero?
Why were you trying to access that element of a zero length (empty) array?
The first can be answered by reading through the javadoc for String::split, and thinking about it. The line you were trying to split must have been empty. (If there were any non-blank characters in it, the length of the array would have been > zero and you wouldn't have gotten an exception on line 30.)
If you look carefully at the input file you should be able to spot the empty line. (It could be at the end of the file.) And my guess is your problem's requirements mention the empty line. (They should.)
The second is simple. You didn't consider the possibility of an empty line in the input, and that would give you an empty array. Your code assumes that the array is non-empty.
Q: How do you fix it?
A: You need to know what you want to happen in each of those scenarios. Then you write code to implement that. Here are a couple of strategies:
Trim each line (to remove extraneous leading / trailing whitespace) and test if the resulting string has length zero. If it is, skip the line.
Split the line, and check how many elements there are in the array. If the number is NOT 4, do something appropriate. (Skip the line, report an error, whatever. You decide.)
Then test it.
Earlier I said this:
That is the wrong fix. ... 2) It also implies a significant misconception about what happens when you assign an array.
String line = scan.nextLine();
String[] details = new String[4]; // <<-- supposed fix
details = line.split(" ");
Array assignment is actually a reference assignment. So the line after your fix is going to replace the 4 element array that you created with a new array created by the split call. The array may well have a different length. It will definitely be a different array.
In short, that fix actually doesn't have any effect.

Why does this recursive Java method for counting two characters work?

Trying to learn Java at the moment. I was just solving a few recursion problems, and I came across one that asked me to count the occurrences the substring "hi" in another string. I was looking for recursive ways to do this, and I found a code that basically did what I wanted and I could paraphrase, but I didn't understand how/why it works. I had no issue with the other recursion problems, and I understand the concept of calling a function within its body, but the way this code works puzzles me. Stepping through it in a debugger just confused me.
public int countHi(String str) {
int n = str.length();
if(n <= 1) return 0;
if(str.substring(0, 2).equals("hi"))
return countHi(str.substring(1)) + 1;
return countHi(str.substring(1));
}
Typically all recursion breaks down to two main insights:
Base case (or terminating case): What is the simplest problem? Where do you not need to simplify?
Recursive case: How do you solve the current problem using a simpler problem's solution?
The base case here is when the string is too short - a string of less than two characters obviously can't contain "hi".
The recursive case here is that a string that starts with "hi" has one "hi" more than the rest of the string, but a string that doesn't has exactly as many "hi" when you chop off the start.
The code encodes these two insights.

Java two equal Strings are not equal

I have the following problem: I have a String that I read from a MySQL Database (with the JDBC driver) and have to compare it with another String that I receive over TCP with a BufferedReader. When I use String.equals, false is returned even if the Strings are exactly equal, I even printed both Strings to the console to make sure there aren't any typos or null objects. String.compareTo returns a negative number around -100.
I am really confused here and have no concrete idea how to fix that. Maybe it's related to the database's encoding (UTF-8)?
As requested, here is my code snippet:
public TeleportSign getTeleportSign(String target) {
// I used a HashMap, but I switched to an ArrayList in order to be able
// to compare the Strings directly.
//return signs.get(target);
for(TeleportSign s : signsList) {
// I am printing the Strings here. I even put stars to the left
// and the right of the String to make sure there are no
// spaces or new lines. s.getTarget() returns the String from the DB,
// target is the String sent over TCP.
System.out.println("*" + s.getTarget() + "* " +
String.valueOf(s.getTarget().compareTo(target))
+ " *" + target + "*");
if(s.getTarget().compareTo(target) == 0)
return s;
}
return null;
}
And the console output is:
*TDM1* -84 *TDM1*
Thanks in advance!
Captain
So I rebooted the entire system and retried. Everything works now as expected. I can't explain this to myself because I restarted the JVM multiple times and nothing happened, and a system reboot shouldn't affect a Java program like this.
I am sorry for everyone's time I wasted, but I really appreciate your quick help anyways.
EDIT: I use the trim method from String now. This method cuts off any leading null characters to prevent issues like this one. I hope this will be helpful for someone who has the same problem!

Java search a string for a substring UNLESS preceded by specific character

I'm attempting to write a Java program that searches for a specific substring (xyz) within a user-entered string, and keeping a running count, unless that substring is preceded by a period. At this point in the class, we've only used charAt and length, so if possible I need to stick to that. Additionally, we haven't used regular expressions at all, so that's out the window too.
I've managed to get the program working as desired, with one notable exception: if the String entered begins with a period, it fails to count any successive matches. This is what I've got so far:
System.out.println("Give me a String:");
String s1 = kb.nextLine();
int index = 0;
int count = 0;
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
System.out.println(count);
You can simply check the input string whether it starts with period. If so then you can use the following piece of code to handle the validation.
if(s1.charAt(0)!='.')
{
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
}
else
{
index=1;
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
}
System.out.println(count);
}
As this seems like a homework type of question I will attempt to guide you in the right direction first and provide a solution at a later time. I strongly encourage you to work through the problem on your own first to the best of your ability before you look at my solution (once I post it) and to read this page before going ANY further
First, consider the kinds of inputs you could receive. Since you didn't specify any limitations you could get things like:
"" (empty string)
"\n" (whitespace)
"x" (a single character)
"xx" (two characters string)
"abc" (string of correct length, but not containing your substring)
".xyz" (the substring to be ignored)
I could go on, but I'm sure you can come up with all the various combinations of weird things you might receive. These are just a few examples to get you started (along with those I posted in the comments already)
Next, think about what you need your algorithm to do. As I said in the comments it sounds like you want to count the occurrences of the substring "xyz" while ignoring the occurrences of the substring ".xyz". Now consider how you're going to look for these substrings - you're going to advance one character at a time from left to right across the String looking for a substring that matches one of these two possibilities. When you find one of them you'll either ignore it or count it.
Hopefully this helps and as I said, I will post a solution later after you've had some time to wrestle with the code. If you do solve it go ahead and post your solution (maybe edit your question to add the new code or add an answer) Finally I once again strongly urge you to read this page if you have not already.
EDIT #1:
I wanted to add a little more information and that is: you already have a pretty good idea of what you need to do in order to count your "xyz" substring at this point - despite the small flaw in the logic for inputs like "xaz", which is easily fixable. What you need to focus on is how to ignore the substring ".xyz" so think about how you could implement the ignore logic, what does it mean to ignore it? Once you answer that it should start coming together for you.
EDIT #2:
Below you will find my solution to the problem. Once again it's important to understand how the solution works not just copy and paste it. If you simply copy my code without understanding it you're cheating yourself out of the education that you're trying to gain. I don't have time at the moment to describe in detail why and how this code works, but I do plan to edit again later to add those details.
import java.util.Scanner;
public class Main {
private static Scanner scan = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("Give me a String:");
String s1 = scan.nextLine();
System.out.println(countSubstrings(s1));
}
public static int countSubstrings(String s1){
int index = 0;
int count = 0;
while (index < s1.length()-2) {
if(s1.charAt(index) == '.' && s1.charAt(index+1) != '.'){
index++;
}
else if (index+2 < s1.length() && s1.charAt(index) == 'x' && s1.charAt(index + 1) == 'y'
&& s1.charAt(index + 2) == 'z') {
count++;
index+=2;
}
index++;
}
return count;
}
}
EDIT #3:
Here is the nuts and bolts of why the above code does what it does. First, we think about the fact that we're looking for 3 items (a triple) in a specific order within an array and if we see a fourth item (a period) immediately preceding the first item of the triple then we need to ignore the triple.
Per my previous edit we need to define what it means to ignore. In this case what we mean is to simply not count it and move on with our search for valid substrings to count. The simplest way to do that is to advance the index without incrementing the count.
So, ask yourself the following:
When should my loop stop? Since we're looking for triples we know we can stop if the length of the input String is less than 3 or when there are less than 3 characters left in the String that we have not examined yet. For example if the input is "xyzab" by the time we get to index 3 we know there's no possible way to form a triple where "a" is the first character in the triple and that therefore our counting is done.
Is there ever a time when I would not want to skip the next 3 characters after a period? After all the goal is to look for triples so wouldn't I want to skip 3 characters not just 1? Yes there is a time when you do NOT want to skip 3 characters and that's when you have something like ".axyz" because a valid triple could start as soon as the 2nd character past the period. So in fact you want to skip only 1 character.
This, and the fact that index is always incremented by 1 at the end of the loop (more on this later), is why the first condition inside the while only advances the index by 1:
if(s1.charAt(index) == '.' && s1.charAt(index+1) != '.'){
index++;
}
Is there ever a time when I would see a period and not wish to ignore (skip) the next character? Yes, when the next character is another period because it could indicate that another triple needs to be skipped. Consider the input "..xyz" which would result in a wrong answer if you encounter the first period and skip the second period since your algorithm could see the next three characters as a valid triple but in fact it is invalid because of the second period.
This is why the second half of the above condition exists:
`&& s1.charAt(index+1) != '.'`
Now ask yourself how to identify a valid triple. I'm sure by now you can see how to do this - check the current character, the next character, and the character after that for the values you want. This logic is the latter portion of the second if condition within the while:
s1.charAt(index) == 'x' && s1.charAt(index + 1) == 'y'
&& s1.charAt(index + 2) == 'z'
Whenever you're using calculations like index +1 or index +2 inside of a loop that is incrementing the index until it reaches a boundary you have to consider the possibility that your calculation will exceed the boundary because you can't rely on the loop to check this for you as the loop will not perform that check until either the end or beginning of the loop (depending on which kind of loop it is)
Considering the above you must ask yourself: How do I prevent out of boundary scenarios when I use these index+1, index+2, etc types of calculations? The answer is to add another piece to your condition:
index+2 < s1.length()
You may be wondering - why not add two checks since we're using index+1 and index+2? We only need one check to see if the greatest index we use will exceed the boundary in this case. If index +2 is beyond the bounds we don't care if index+1 is or is not because it won't matter we can't possibly have a matching substring.
Next, inside of the second if inside the while you see there is code to increment the index by 2: index+=2; This is done for efficiency since once we have identified a triple we know there is no way to form another triple with characters that are already part of another triple. Therefore we want to skip over them and just like the first bullet point we take advantage of the loop incrementing the index so we only need to increment by 2 and let the loop add the extra 1 later.
Finally we reach the end of the logic within the loop. This part you're already familiar with and that's the index++; which simply increments the position within the String that we're currently examining. Note that this works in tandem with the first bullet point. Take the example from the first bullet point of ".axyz". There is a period in index 0 and the character in index 1 is not another period so the logic from the first bullet point will increment index by 1, making it 1. At the end of the loop index is incremented again making it 2 thereby skipping over the period - at the start of the next loop index is 2, it was never 1 at the start of the loop.
Well, I hope this helps to explain how it all works and illustrate how to think about these sorts of problems. The basic principle is to visualize where your current element is and how you can use that to achieve your goal. At the same time think about what kinds of properties the different elements of your program have and how you can take advantage of them - such as the fact that once you identify a triple it is safe to skip over those characters because they have the property of only being usable once. As with any program you always want to try to create as many test inputs as you can to test all the weird boundary cases that might occur to ensure the correctness of your code. I realize you probably are not familiar with JUnit but it is a very useful tool and you might try researching the basics of using it when you have a little spare time, and the bonus is that if you use the Eclipse IDE it has integrated JUnit functionality you can use.

Java: StringIndexOutOfBoundsException when using .charAt() in for-loop

thank you in advance for reading about my problem.
I am making a Hangman game where I want to print out a hidden version of the current word, but I would like to update it when a correct letter is guessed (on the right spot, too). I've been looking around StackOverflow but I just can't seem to find an explaination that I understand. If someone could help me, that would be great. :D
I'll post the for-loop that this is about. I can post more of the code if you might need it. The answerInput and guessInputString are both read from the console earlier in my code using a br.readLine() method.
for (int i = 0; i < inputAnswer.length(); i++) {
char inputAnswerChar = inputAnswer.charAt(i);
char guessInputChar =guessInputString.charAt(i);
if (inputAnswerChar == guessInputChar) {
replacementString.replace(replacementString.charAt(i), inputAnswerChar);
}
}
Thank you for any help that you can give me!
Your code is assuming that guessInputString and replacementString both have at least as many characters as inputAnswer, which is obviously wrong to assume, since your loop only guarantees that the i'th character exists for the inputAnswer String.
BTW, replacementString.replace(replacementString.charAt(i), inputAnswerChar) has no effect, since it cannot change the String it is executed for (since Strings are immutable). You must assign the new String returned by this method back to replacementString :
replacementString = replacementString.replace(replacementString.charAt(i), inputAnswerChar)

Categories

Resources