Logic Error: startWord substring - java

My task is to use substring to pull out the first few letters of a string if it matches another given string. Basically, given a string and a second "word" string, we'll say that the word matches the string if it appears at the front of the string, except its first char does not need to match exactly. On a match, return the front of the string, or otherwise return the empty string. So with the string "hippo" the word "hi" returns "hi" and "xip" returns "hip". The word will be at least length 1.
The problem with my method is when str is just one letter and word is something else that doesn't match str, I run into a
StringOutOfBound Exception
For example, if str is "h" and word is "ix", it should return nothing. Instead, my method crashes with the stringoutofbound exception. What can I do to fix my logic.
public String startWord(String str, String word) {
int length;
length = word.length();
if (str.substring(0, length).equals(word))
return str.substring(0, length);
else if (str.substring(1, length).equals(word.substring(1, word.length())))
return str.substring(0, length);
else
return "";
}

Correct your conditions this way:
if (str.substring(0, Math.min(length, str.length())).equals(word))
return str.substring(0, length);
else if (str.substring(1, Math.min(length, str.length())).equals(word.substring(1, word.length()))) {
return str.substring(0, length);
}
else
return "";

The reason for the error is that str length is smaller than word length. Please put a check before your logic: if(str.length()<=word.length()).
In the else part, always return "", as it will never satisfy your condition.
if(str.length()>=word.length())
{
if (str.substring(0, length).equals(word))
return str.substring(0, length);
else if (str.substring(1, length).equals(word.substring(1, word.length())))
return str.substring(0, length);
else
return "";
}
else{
return "";
}

Related

substring() Function of String Class

I am solving the following question: Given a string and a second "word" string, we'll say that the word matches the string if it appears at the front of the string, except its first char does not need to match exactly. On a match, return the front of the string, or otherwise return the empty string. So, so with the string "hippo" the word "hi" returns "hi" and "xip" returns "hip". The word will be at least length 1.
startWord("hippo", "hi") → "hi"
startWord("hippo", "xip") → "hip"
startWord("hippo", "i") → "h"
My code is as follows:
public String startWord(String str, String word) {
String front = "";
if (str.length()>=1 && word.length() == 1) {
front = Character.toString(str.charAt(0));
} else {
if (str.length() >= 1 && str.substring(1, word.length() - 1).equals(word.substring(1)))
front = str.substring(0, word.length());
}
return front;
}
front=str.substring(0,word.length()) is returning "" value. It is a logic question, not a coding question. Trying to work on my logic as an amateur programmer. Thanks for bearing me SO!
public String startWord(String str, String word) {
if (str.substring(1, word.length()).equals(word.substring(1, word.length()))) {
return str.substring(0, word.length);
} else {
return "";
}
}

Choice between less duplicate code or efficient but duplicate code

I'm trying the exercises in CodingBat.
Java > String-1 > seeColor:
Given a string, if the string begins with "red" or "blue" return that color string, otherwise return the empty string.
My running code is:
public String seeColor(String str) {
int len = str.length();
if (len >= 3 && str.substring(0, 3).equals("red")) {
return str.substring(0, 3);
} else if (len >= 4 && str.substring(0, 4).equals("blue")) {
return str.substring(0, 4);
}
return "";
}
But I found this other answer all over the web:
public String seeColor(String str) {
int len = str.length();
if(len >= 4) {
if(str.substring(0, 4).equals("blue"))
return "blue";
else if(str.substring(0, 3).equals("red"))
return "red";
else
return "";
}
else if(len == 3) {
if(str.substring(0, 3).equals("red"))
return "red";
else
return "";
}
else
return "";
}
My solution has less duplicate code (or it's what I think).
But the other solution looks more efficient. It starts from large Strings, and evaluating only the strings with length of 3 characters at the end. Probably this last solution is more able to make easy changes in the future.
I would like to read someone's opinion. Thanks.
Edited: I add an apologize, I haven't formatted my code appropriately at first as suggested by #MikeDunlavey.
I wouldn't do either. I wouldn't assume the second one is more efficient, though it is more complicated. Both create objects needlessly.
public String seeColor(String str) {
return str.startsWith("red") ? "red" :
str.startsWith("blue")? "blue" : "";
}
Every time you call substring this creates two objects which is really expensive for what this function is doing.

Switching last two char in a string

Learning java as my first language and I found a solution for the problem at codingbat but I don't understand why my solution doesn't work and would love your help.
Given a string of any length, return a new string where the last 2
chars, if present, are swapped, so "coding" yields "codign".
lastTwo("coding") → "codign" lastTwo("cat") → "cta"
lastTwo("ab") → "ba"
This is my not working code:
public String lastTwo(String str) {
int strLength = str.length();
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
if(strLength<2)
return str;
return str.substring(0, strLength-2)+last+bLast;
}
This are the errors and I cant figure out why:
lastTwo("a")
→"Exception:java.lang.StringIndexOutOfBoundsException: String
index out of range: -1 (line number:5)" lastTwo("")
→"Exception:java.lang.StringIndexOutOfBoundsException: String
index out of range: -1 (line number:4)"
It seems there is a problem when input is less than 2 chars but I can't figure out why. To me, the if logic looks okay.
You need to move if condition up in the method as:
public static void main(String[] args) {
System.out.println(lastTwo("coding"));
System.out.println(lastTwo("cat"));
System.out.println(lastTwo("ab"));
System.out.println(lastTwo("a"));
}
public static String lastTwo(String str) {
int strLength = str.length();
if(strLength<2)
return str;
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
return str.substring(0, strLength-2)+last+bLast;
}
This will print:
codign
cta
ba
a
In the method if length of str is less than 2 (e.g. 1) in that case it will be returned else it will compute last and blast and then perform the operation.
When the input is is 1 char, strLength-2 is -1. The methodsubstring throws the error because such index doesn't exist. (The same applies to 0 char and strLength-1)
You have to put this verification on top
if(strLength<2)
return str;
When you have this code, if the string is "", it is trying to get the substring between positions -1,0 and -2,-1. You can't get the substring in a position lower than 0.
int strLength = str.length();
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
One of the overloads for substring can take the starting index , it figures out the last index. So the following should give you the last two chars:
str.substring(java.lang.Math.max(0,str.length()-2))
public String lastTwo(String str) {
if(str != null ) {
int strLength = str.length();
if (strLength < 2)
return str;
String last = str.substring(strLength-1,strLength);
String bLast = str.substring(strLength-2,strLength-1);
return str.substring(0, strLength-2)+last+bLast;
}
return null;
}
Problem in your code is String bLast = str.substring(strLength-2,strLength-1);
when strLength = 1 and you subtract by 2 and your index will be -1, hence IndexOutOfboundException occure.
Use above code your problem solved.
Simpler solution is to take the start-of-string and
append the last-char and then
append the before-last-char:
public static String lastTwo(String str) {
if (str.length()<2){
return str;
} else{
return str.substring(0, str.length() - 2) +
str.charAt(str.length() - 1) +
str.charAt(str.length() - 2);
}
}

String-1 > startWord

I was going through practice questions on CodingBat and I came across this one. It said:
"Given a string and a second "word" string, we'll say that the word matches the string if it appears at the front of the string, except its first char does not need to match exactly. On a match, return the front of the string, or otherwise return the empty string. So, so with the string "hippo" the word "hi" returns "hi" and "xip" returns "hip". The word will be at least length 1. "
So far this is the solution I came up with. It works for the most part, however I get one error shown below:
Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: -1 (line number:3)
This occurs for the case -->> startWord("", "i"). How could this error be fixed?
public String startWord(String str, String word) {
String first = str.substring(1, str.length());
String second = word.substring(1, word.length());
if (str.length() == 0) {
return "";
}
if (str.startsWith(word)) {
return str.substring(0, word.length());
}
else if (first.startsWith(second)) {
return str.substring(0, word.length());
}
return "";
}
You should place your
if (str.length() == 0) {
return "";
}
as a first statement your function, so that the zero length string don't throw the exception.

Find longest word in a sentence recursively

So I need to find the longest word recursively, I've written the code, but it's not working, and I have no idea what to fix.
public static String longestWord(String sentence)
{
int i = sentence.indexOf(" ");
if (i==-1){
return sentence;
}
else{
String first = sentence.substring(0,i);
String rest = sentence.substring(i+1);
if(first.length()>=rest.length()){
return longestWord(first);
}
else{
return longestWord(rest);
}
}
}
The line:
if(first.length() >= rest.length())
should read like:
String res = longestWord(rest);
if(first.length() >= res.length())
The reason it does not work is that you are ignoring the length of the longestWord(rest): instead of comparing the length of the initial word and the rest of the sentence, you should compare the length of the initial word to the length of the longest word found in the rest of the sentence.
String first = sentence.substring(0,i);
String rest = longestWord(sentence.substring(i+1));
return first.length()>=rest.length() ? first : rest;
Your basic approach is sane: you're breaking the input into two: the first word, and the rest of the string. But then the logic is bungled a little bit.
If the first word is longer than the entire rest of the string, you should just return first, not longestWord(first) (although, you do handle that case: longestWord will notice that the word cannot be split and just return it. It's pointless though).
Secondly, if that is not the case, you cannot assume that the first word is not the longest word. You must capture the return value of longestWord(rest), and then compare that word's length to the length of first. If that word is longer, then return it. Otherwise return first.
The essence of "divide and conquer" by recursion is that you solve some smaller versions of the problem, and then integrate those results. Don't forget this second part. This is not a binary search tree search where the data is organized such that you can just recurse to one half of the space or the other to find the answer. You don't know where the longest word might be.
This is another approach to solve the question:
public static String longestWord(String sentence) {
return longest(sentence.split("\\s+"), 0, 0);
}
private static String longest(String[] words, int idx, int longest) {
if (idx == words.length)
return words[longest];
return longest(words, idx+1,
words[idx].length() > words[longest].length() ? idx : longest);
}
First, in longestWord() the sentence gets split by its spaces, producing an array of words. From that point on, the method longest() recursively iterates over all the words passing the index of the longest one found so far in the longest parameter, until there are no more words. This is an efficient answer, as it doesn't create substrings at each step.
package com.kota.java;
import java.util.*;
class LongestWord{
String str = "Ram is intelligent boy";
String stringArray[] = str.split("\\s");
public String compare(String st1, String st2) {
if (st1.length() > st2.length()) {
return st1;
} else {
return st2;
}
}
LongestWord() {
String word = "";
for (int i = 0; i < stringArray.length; i++) {
if (i == 0) {
word = stringArray[0];
}
word = compare(word, stringArray[i]);
}
System.out.println("Longest word = " + word);
}
public static void main(String[] args) {
new LongestWord();
}
}
/**
* Out put : Longest word = intelligent
*
* */

Categories