I've been at this for a while, but as the title says, I'm trying to create a method that will compare each letter to the letter after it and see if the word is ascending. The method should then return a boolean value. But when it's implemented in my code, it will fail with:
java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.charAt(Unknown Source)
and multiple other lines of error code.
Here's my source code:
public static boolean ascending(String word){
int i = 0;
boolean ascend;
do {
if (word.charAt(i) <= word.charAt(i+1))
ascend = false;
else
ascend = true;
} while (i <= word.length());
i = 0;
return (ascend);
}
I can't see where I'm going wrong?
condition should be
i < word.length()-1
and the i = 0; at the end should be in side the loop as i++, else it will be infinite loop.
also, you have actually put the reverse check. once you fix ArrayIndexOutOfBoundsException you will return false for ascending string and true otherwise
public static boolean ascending(String word){
if(word == null || word.length <2) return false;
int i = 0;
boolean ascend = false;
while(i < word.length()-1){
if (word.charAt(i) <= word.charAt(i+1))
ascend = true;
else{
ascend = false;
break;
}
i++;
}
return (ascend);
}
In pseudo code:
take the first letter (F) => store it
take the next letter (N) => check against first => stop here if not OK
is there another next letter => stop here if not
update first letter (F) with next letter (N)
repeat starting from 2
Few things needs to be fixed here:
You need to increment "i" to traverse through the word.
Restrict your while loop till (i < word.length() )
You may break at any point when you find ascend is false. No need to continue with the looping.
I would not use a do while because there is an opportunity to run this on an empty string causing it to crash. I would instead use a regular while and at the beginning test for while (i < word.length()-1). You never want to test past the end of the string. You always want to check to see for a string length of n that charAt(n-1) < charAt(n). Also I don't see an incrementer to increase the value of i. Loop will never continue on to the next letter and will run forever.
public static boolean ascending(String word){
int i = 0;
boolean ascend;
while (i < word.length()-1)
{
if (word.charAt(i) <= word.charAt(i+1))
ascend = false;
else
ascend = true;
i++;
}
i = 0;
return (ascend);
}
Do not use do-while loop. Even if you do you need to run some checks beforehand to make sure your word has length more than 1 otherwise your code will raise an IndexOutOfBounds Exception. If you insist on using it, change your condition to i
Here is a working code example:
public boolean isAscending(String word){
if (word==null || word.length==0){
return false;
}
for (int i=1; i<word.length(); i++){
if (word.charAt(i) < word.charAt(i-1))
return false;
}
return true;
}
Related
I am using a while loop with a counter to find an element on an array. I will check that if the returned element is equal to the lenght of the array the element is not found. The loop is like this.
int i = 0;
int returned;
boolean found = false;
while(i < words.length && !found){
WordInText check = new WordInText(w);
if(check.equals(words[i])){
found = true;
}
else{
i++;
}
return i
What I am wondering if it would be better instead of doing an else on every condition to do the following
int i = 0;
int returned;
boolean found = false;
while(i < words.length && !found){
WordInText check = new WordInText(w);
if(check.equals(words[i])){
found = true;
}
i++;
}
if(!found)
i++;
return i-1
I feel that the second one is more efficient because it doesn't have to check the condition on every loop and in case that the array was really long it would have to be done a lot. But I'm not sure on when to decide each because the second looks realy ugly and not intuitive.
There are multiple possible refactoring that avoid the question, but I'll try to answer your question as is :
the else costs nothing : it's just a block that will be executed if and only if the if's condition evaluates to false.
it is easily understood by anyone
Even if it doesn't look the prettiest, I see no reason to avoid it. In your second code, not only do you introduce extra instructions, it is also harder to understand since you have to get why the index needs to be increased when the element isn't found.
extract the code in a method, like this
public int contains(....) {
int i = -1;
while(i < words.length){
WordInText check = new WordInText(w);
if(check.equals(words[i])){
return i;
}
i++;
}
return i;
}
no need for additional variables and clearer structure of the code
I don't think that you need to use an else part or another if condition to check whether its found or not cause you are already checking the condition in while loop.
int i = 0;
int returned;
boolean found = false;
while(i < words.length && !found){
WordInText check = new WordInText(w);
if(check.equals(words[i])){
found = true;
}
i++;
}
return i;
So here the loop will go on until the value of found becomes true (means that till the required element is found. Then in next iteration it will check whether the found value is false. As it's not false anymore the loop will not be executed and the i will be returned.
There you can check the value of i and decide whether the element is found or not.
I'm doing a problem on codingbat.com and am confused with why this solution to the problem does not give an index out of bounds error. Wouldn't the first for loop search for an index that is beyond the length of the passed array?
Here's the problem:
We'll say that a value is "everywhere" in an array if for every pair of adjacent elements in the array, at least one of the pair is that value. Return true if the given value is everywhere in the array.
Here's my working solution:
public boolean isEverywhere(int[] nums, int val) {
boolean flag1 = true;
boolean flag2 = true;
for (int i = 0; i < nums.length; i += 2) {
if (nums[i] != val) flag1 = false;
}
for (int i = 0; i < nums.length - 1; i += 2) {
if (nums[i + 1] != val) flag2 = false;
}
return flag1 || flag2;
}
Thanks!
No. The test happens after i is incremented. So, once i is not less than the length of the nums array the loop stops. The second loop uses i + 1 at if (nums[i + 1] != val) which is why it needs to test that i is less than the length minus one.
Also you can make the method static (since it uses no instance state).
It wouldn't because while i += 2 is written after i < nums.length, the loop still checks that i is less than the given length(nums.length) before going onto the body of the loop even after 2 has been added on.
For a class I am taking, I am to create a program that tests whether a string is a palindrome. We were supposed to just use an 8 character string every time and hard-code it that way, but I wanted to get above and beyond and make something to test any string. Unfortunately, this code seems to aways return true, and I'm honestly not sure why.
public static boolean palindromeTest(String input){
//This portion declares variables necessary for testing, and modifies them if necessary.
int inputLength=input.length();
char[] Chars=input.toCharArray();
for(int j=0; j<inputLength; j++){
Character.toLowerCase(Chars[j]); //makes all characters in input lower case
//This portion performs the palindrome test
}
if(inputLength%2>0){ //if length is odd
inputLength=(inputLength-1)/2;
for(int i=0; i>0; i++){
if(Chars[i]!=Chars[inputLength-i]) //tests equality first and last in pairs via for loop
return false; //break;
}
}else{ //if length is even
inputLength=(inputLength)/2;
for(int i=0; i>0; i++){
if(Chars[i]!=Chars[inputLength-i]) //tests equality first and last in pairs via for loop
return false; //break;
}
}
return true; //if all tests are passed, input is indeed a palindrome
}
it is because of
for(int i=0; i>0; i++){
the code inside the for loop will never be executed as i is never greater than 0
Edit:
Moreover
if(charArray[i]!=charArray[inputLength - i])
is kinda wrong, cuz lets say your string is madam, inputLength = inputLength-1 makes the above condition to check "m" and "d" which not how it should work
the correct solution would be
inputLength = inputLength / 2;
int j= input.length()-1;
for(int i =0; i< inputLength; i++, j--) {
if(charArray[i]!=charArray[j]) {
return false;
}
}
the palindrome test method using for loop and char array is as follows:
public static boolean palindromeTest(String input){
char[] Chars=input.toCharArray();
for(int i=0,j=Chars.length-1;i<j;i++,j--){
if(Chars[i]!=Chars[j]){
return false;
}
}
return true;
}
I'm currently working on a project for a class to create a TextLine class that represents the a line of text that must be represented as an array of characters. I am not allowed to represent the TextLine object by using the string class indirectly or directly in any way, however, I can use it to work with the parameters.
For one of the methods, I am supposed to take in a string as an argument of a parameter, which is also a fragment to the TextLine object, and then return the index position of the first occurrence of the fragment in this TextLine, or -1, if the fragment is not found.
Right now, I'm trying to figure out the indexOf method, but my problem is that my method only checks for a starting point once. So if the letter of the TextLine object doesn't match the letter of the fragment the first time, but there is another match somewhere else in the object, the method doesn't check for that starting point.
For example, lets say I enter penplay as the TextLine, then I enter play as the fragment. Clearly, there is an occurrence of play in the TextLine, but what my indexOf method does, is that it checks the first p from penplay at index 0, then continues to see if the following letters match for the length of play, and if it doesn't, it returns -1. Any idea how I could allow the algorithm to keep searching for another starting point?
This is what I have for my code:
public int indexOf(String fragment){
char[] temp = fragment.toCharArray();
int j = 0;
for(int i = 0; i < someText.length; i++){
while(someText[i] == temp[j]){
for(j = 1; j < temp.length; j++){
if(temp[j] != someText[i+j]){
return -1;
}
}
return i;
}
}
return -1;
}
You're special-casing the first character, when there's no need to. Basically you need to say:
For each potential starting character...
Does the whole of fragment match, starting at that candidate position?
So something like:
// Only deal with *viable* starting points
for (int i = 0; i < someText.length - temp.length; i++) {
boolean found = true;
for (int j = 0; j < temp.length && found; j++) {
if (temp[j] != someText[i + j]) {
found = false;
}
}
if (found) {
return i;
}
}
return -1;
This can be refactored by extracting the inner loop:
for (int i = 0; i < someText.length - temp.length; i++) {
if (textMatches(temp, i)) {
return i;
}
}
return -1;
...
// TODO: Javadoc to explain parameters :)
private boolean textMatches(char[] chars, int startingIndex) {
for (int i = 0; i < chars.length; i++) {
if (chars[i] != someText[i + startingIndex]) {
return false;
}
}
return true;
}
The way you have it set up seems suitable as a kind of doesStringExistAtIndex(j, fragment) function. Since that returns -1 if the string doesn't exist at the first index, you could do something like this:
//assuming that "this" is the subject that you are searching in
public int indexOf(String fragment){
for(int i=0; i<this.length; ++i){
if(doesStringExistAtIndex(i, fragment))
return i;
}
return -1;
}
Not sure if this is what you wanted, but I basically wrote up an indexOf method. I did some testing and it seemed to work just fine in some tests I did. Of course, its going to look different because I wanted to make testing easier, but it should be 30 seconds or less of converting if you decide to use it.
public int indexOf(String fragment, String source)
{
char[] temp = fragment.toCharArray();
char[] someText = source.toCharArray();
outer : for(int i = 0; i <= someText.length - temp.length;i++) //stops looping because why loop after the fragment is longer than the source we have left when its impossible to find
{
if(someText[i] == temp[0]) //if the first characters are the same
{
int q = 0;
while(q < temp.length) //loop through the fragment
{
if(someText[i+q] != temp[q]) //if the characters are not the same, stop, and go to the next character of the source. Don't return anything
{
continue outer; //continues the loop labeled 'outer' (e.g. outer : for(...) )
}
q++; //increment index since they both match
}
return i; //fragment and some part of the source matched since it reached here. Return the index of the first character
}
}
return -1; //reached here because nothing was found :( return -1
}
EDIT 0 Added line comments
So I've been practicing my Java programming skills on the CodingBat website, when I came across this problem. In it, you have to make a simple method that takes in an array of integers of dynamic length, check to see if the elements in the array are in increasing order (1, 2, 3, 15678, etc), and return "true" if true, or "false" if there is an integer out of order.
Firstly, I initialize a boolean variable named "result". Then, I iterate through the array of integers passed by the method. If the current index value is less than the next index value, I set "result" to "true", and repeat the loop. Else, I'll set "result" to "false", break out of the loop and set "result" to "false". After the FOR loop, I return "result".
However, I've been receiving an error message that "result" has not been initialized properly. I can kinda understand the confusing with the JVM, however I thought that setting the value for "result" inside of the IF/ELSE statements would solve that.
Here is a copy of the code that I have done so far:
public boolean scoresIncreasing(int[] scores) {
boolean result;
for (int i = 0; i < scores.length; i++) {
if (i < (i + 1)) {
result = true;
}
else {
result = false;
break;
}
}
return result;
}
First of all, i < i+1 will always be true, unless i = Integer.maxValue, in which case you'll wrap around to Integer.minValue.
What you want is scores[i] < scores[i+1] , and you'll need to adjust your loop values to avoid an index out of bounds on the last iteration.
So, your code fixed:
public boolean scoresIncreasing(int[] scores) {
boolean result;
for (int i = 0; i < scores.length-1; i++) // fix loop end
{
if (scores[i] < scores[(i + 1)]) {
result = true;
}
else {
result = false;
break;
}
} // missing brace
return result;
}
Try this as an alternative. It works on the principle that once you get a false, you can get out immediately.
public boolean scoresIncreasing(int[] scores) {
boolean result = true; // assume true
for (int i = 0; i < scores.length-1; i++) // fix loop end
{
if (scores[i] > scores[(i + 1)]) return false;
} // missing brace
return result;
}
Of course, you may want to introduce bounds checking at the beginning to ensure that there are at least two values.
You are simply missing a closing brace (}) before return result.
As a suggestion to simplify the code (and deal with arrays of 0 elements!), you may want to initialize result to true. Then, as you loop over the array, change result to false if and only if you find an element out of order.
One other word of caution. You use element i + 1 in your for loop. Think about what will happen when you get the last element in the array (i == scores.length - 1).
if (i < (i + 1)) will always evaluate to true. You need to compare the contents of the array at those indexes, not the indexes themselves.
Something like:
public boolean scoresIncreasing(int[] scores) {
for(int i = 0; i < scores.length-1; i++) {
if(scores[i] > scores[i+1]) return false;
}
return true;
}
What if scores has 0 elements? ;]
in your code, you are returning result inside the for loop (after the if-else statement).
Add another bracket before the return statement (to close the for loop)