EDIT: Really sorry, I mean Java! As for what I think, I would say the first contains if statement is for s == null or length 0, but I'm confused as to what to put in the
return spaceCount(s.substring(1, ......)) + ......;
part.
I'm trying to use some if statements to write a function that takes a string as a parameter and recursively coutns the number of blanks spaces " " it has. So far I have
public static int spaceCount (string s) {
if ( ...... ) {
return 0;
}
char c = s.charAt(0);
if (....... ) {
return spaceCount (.....);
} else {
return spaceCount(s.substring(1, ......)) + ......;
}
}
So in the first if statement, should I write the case of the string having zero length? I'm pretty sure that won't cover the case of no spaces at all, so I'm not sure how to proceed.
For the second and third, I know I have to scan the string for spaces, but I am not really sure how to do that either. Any hints or direction would be appreciated!
public static int spaceCount(final String s) {
if(s == null || s.length() == 0) {
return 0;
}
char c = s.charAt(0);
if(' ' != c) {
return spaceCount(s.substring(1));
} else {
return spaceCount(s.substring(1)) + 1;
}
}
You don't have to "scan the string for spaces", that's what the recursion passing the remainder of the string does.
s.length() - s.replaceAll(" ", "").length() returns you number of spaces.
how to count the spaces in a java string? has the answer. Probably it may help. the above line is the simplest.
[You didn't specify a programming language] Here is a solution in Java:
public static int spaceCount(String s)
{ return scRecursive (s, s.length, 0, 0); }
public static int scRecursive (String s, int len, int dex, int count)
{ if (len == dex) return count;
else
return scRecursive (s, len, dex + 1,
(' ' == s.charAt(dex) ? count + 1 : count)); }
This is tail recursive (which might imply some efficiency) and, more importantly, this does not copy/allocate substrings
Here is one in Scheme:
(define (space-count string)
(let ((length (string-length string)))
(let stepping ((index 0) (count 0)
(if (= index length)
count
(let ((char (string-ref string index)))
(stepping (+ index 1)
(if (equal? #\space char)
(+ 1 count)
count)))))))
The recursion is in the call to stepping which has two arguments - the current index and the current count of spaces. The recursion terminates when the index equals the length. The count is incremented when the current char is a space.
public class CountSpaces {
public static void main(String[] args) {
String str = " A ";
System.out.println(spaceCount(str, 0));
System.out.println(spaceCount(str));
}
public static int spaceCount(String str, int count) {
if (str == null) {
return 0;
} else if (str.length() > 0) {
char c = str.charAt(0);
if (Character.isWhitespace(c)) {
count++;
}
return spaceCount(str.substring(1), count);
} else {
return count;
}
}
public static int spaceCount(String s) {
if (s.length() == 0 || s == null) {
return 0;
}
char c = s.charAt(0);
if (!Character.isWhitespace(c)) {
return spaceCount(s.substring(1));
} else {
return spaceCount(s.substring(1, s.length())) + 1;
}
}
}
Related
How would I go about making it reverse the string at a specific index for example, goodbye at i=1 would be ybdoog and i=2 is bdoog. Anything before that index is just ignored in the returning string. In Java
public static String revStr(String s, int i) {
if (s == null || s.length() <= 1)
return s;
else
return revStr(s.substring(1), i)+ s.charAt(0);
}
You need to return s.substring(i) instead of s because you want the reversed substring starting from i. Also, for this, the terminating condition should be if (s == null || s.length() <= i).
public class Main {
public static void main(String[] args) {
// Test
System.out.println(revStr("goodbye", 2));
System.out.println(revStr("goodbye", 1));
System.out.println(revStr("goodbye", 0));
}
public static String revStr(String s, int i) {
if (s.length() <= i)
return s.substring(i);
else
return revStr(s.substring(1), i) + s.charAt(0);
}
}
Output:
bdoog
ybdoog
eybdoog
I started learning Java, currently I'm playing around with recursion.
I wanted to try and make a substring method which will substring from both sides by 1 character until we get the desired string.
I managed to do the first part but I'm having problem figuring out how to substring from the back.
n and m should be the indexes between which we want to substring (inclusive).
In this example result of method should be "bstri"
Here is my code:
public static void main(String[] args) {
String s = "substringme";
System.out.println(rec(s,2,6));
}
public static String rec(String s, int n, int m) {
if(n == 0 /* && missing 2nd part of condition */){
return s;
} else {
if(n>0){
s = s.substring(1);
n--;
}
if(/* missing condition */){
s= s.substring(0, s.length()-1);
}
return rec(s,n,m);
}
}
I would appreciate any help I can get.
So fixing your recursive method is fairly easy. We just do exactly the same as you did for n:
public static String rec(String s, int n, int m) {
if (n == 0 && m == 0) {
return s;
}
else {
if(n > 0) {
s = s.substring(1);
n--;
}
if(m > 0) {
s = s.substring(0, s.length()-1);
m--;
}
return rec(s,n,m);
}
}
The issue now is that the value of m given as input is measured from the start of the String and it would be way more convenient for us if it were measured from the end of the String.
We can introduce a new method to do this for us which acts as our entry point to the recursive method:
public static String substr(String s, int n, int m) {
final int newM = s.length() - m - 1; //-1 to be inclusive of the char
return rec(s, n, newM);
}
You would then change your main method to call substr() instead:
public static void main(String[] args) {
String s = "substringme";
System.out.println(substr(s,2,6));
}
I often find myself writing these kind of "entry point" methods when I'm using recursive methods. If you were doing this properly, substr would be your public-facing method and rec would be private.
I propose that you do m-- in the first loop because the definition of m as an index changes when you shorten s from the front.
public static String rec(String s, int n, int m) {
if(n == 0 && m == s.length() - 1){
return s;
} else {
if (n > 0) {
s = s.substring(1);
n--;
m--;
}
if (m < s.length() - 1) {
s = s.substring(0, s.length() - 1);
}
return rec(s, n, m);
}
}
What you could do is look for the difference between m and the length of the string, and cut off characters from the end of the string until it is the correct length.
import java.util.*;
public class Test {
public static void main(String[] args) {
String s = "substringme";
System.out.println(rec(s,2,6));
}
public static String rec(String s, int n, int m) {
if(n == 0 && s.length()-m < 1){
return s;
} else {
if(s.length()-m > 1){
s= s.substring(0, s.length()-1);
}
else if(n>0){
s = s.substring(1);
n--;
}
return rec(s,n,m);
}
}
}
Also shouldn't substring from 2 to 6 be "bstr", not "bstri"?
System.out.println(s.substring(2, 6)); //equals bstr
I'm trying to code this one up,but I don't get an expected result:
Given a string, compute recursively (no loops) the number of lowercase 'x' chars in the string.
countX("xxhixx") → 4
countX("xhixhix") → 3
countX("hi") → 0
Here is my method:
public int countX(String str) {
int count = 0;
if(str.length() >= 1 ) {
if(str.substring(0, 1).equals("x")) {
str = str.substring(1, str.length());
count = count + 1 + countX(str);
}
}
else {
str = str.substring(1, str.length());
count = count + countX(str);
}
return count;
}
You had the right idea, but I think you over complicated things. Just check explicitly if the first character is x (as you have), and only increment count in that case. Regardless of whether it was or wasn't, continue recursing on:
public static int countX(String str) {
int count = 0;
if (str.length() > 0) {
if (str.substring(0, 1).equals("x")) {
++count;
}
str = str.substring(1, str.length());
count += countX(str);
}
return count;
}
Suppose you have a string "axbxcx". The code below looks only at the first character in the string and determines if it is an x. If so, then return 1 in addition to the number of x's found in the rest of the string. If the first character is not an x, then the number of x's in the string is equal to the number of x's in the string not including the first character, so that is what is returned.
int count(String s)
{
if (s.length() == 0) // base case
{
return 0;
}
if (s.charAt(0) == 'x')
{
return 1 + count(s.substring(1));
}
else
{
return count(s.substring(1));
}
}
How about this?
public static int countX(String str) {
if (str.length() == 0) {
return 0;
}
if (str.substring(0, 1).equals("x")) {
return 1 + countX(str.substring(1));
}
return countX(str.substring(1));
}
You should try this (it assumes you are testing outside the method that initial str value is not null and has a length greater than 0).
public int countX(String str) {
if ( str.length() == 1 ) {
return ("x".equalsTo(str) ? 1 : 0);
} else {
return (str.charAt(0) =='x' ? 1 : 0) + countX(str.substring(1,str.length())
}
}
Here is a simple way to do it.
First, check if the string is empty. This is the terminating condition of the recursion.
Then your result is simply the count for the first character (1 or 0), added to the count for the rest of the string (calculated by calling your function on substring(1)).
public static int countX(String str) {
if (str.isEmpty()) {
return 0;
}
return (str.charAt(0)=='x' ? 1 : 0) + countX(str.substring(1));
}
you can try this one:
public int countX(String str) {
int end = str.length(); //get length of the string
int counter = 0;
if(str.length()==0){
return counter; //recursion will stop here
}else{
if(str.charAt(end-1) == 'x'){
counter++;
}
end--;
str=str.substring(0,end); //your string will perform a decrease in length and the last char will be removed
}
return counter+countX(str);
}
Given a string and a non-empty substring sub, compute recursively the largest substring which starts and ends with sub and return its length.
strDist("catcowcat", "cat") → 9
strDist("catcowcat", "cow") → 3
strDist("cccatcowcatxx", "cat") → 9
my solution
public int strDist(String str, String sub) {
int i = sub.length();
int j = str.length();
int count = 0;
if (str.length() == 1 && str.equals(sub)) {
return 1;
} else if (str.length() < sub.length() || str.length() <= 1) {
return 0;
}
if (str.substring(0, i).equals(sub)) {
if (str.substring(str.length() - i, str.length()).equals(sub)) {
return str.length();
} else {
strDist(str.substring(0, str.length() - i), sub);
}
} else {
strDist(str.substring(1, str.length()), sub);
}
return 0;
}
tell me how to correct my code?
Why does this need to be done with recursion?
Edit: fixed code to handle case where sub is not present in str, or only present once.
public int strDist(String str, String sub) {
int last=str.lastIndexOf(sub);
if (last != -1) {
int first=str.indexOf(sub);
if (first != last)
return last - first + sub.length();
}
}
return 0;
}
Recursion is great, if it is suited to the problem. In this case, recursion doesn't add value, and writing it with recursion for the sake of recursion makes the code inefficient.
This will , "compute recursively the largest substring which starts and ends with sub and return its length" as you described.
public class PuzzlingRecursion {
static String substringFound = "";
public static void main(String[] args) {
String sentence = "catcowcat";
String substring = "cat";
int sizeString = findNumberOfStrings(sentence, substring, 0);
System.out.println("you are searching for: " + substring);
System.out.println("in: " + sentence);
System.out.println("substring which starts and ends with sub and return its length is:"+substringFound + ", " + sizeString);
}
private static int findNumberOfStrings(String subStringPassed,
String setenecePassed, int count) {
if (subStringPassed.length() == 0) {
return count + 0;
}
if (subStringPassed.length() < setenecePassed.length()) {
return count + 0;
}
count++;
String lastStringMiddle = subStringPassed.replaceAll("(.*?)" + "("
+ setenecePassed + ")" + "(.*?)" + "(" + setenecePassed + ")"
+ "(.*?.*)", "$3");
if (subStringPassed.contains(setenecePassed)
&& lastStringMiddle.length() != setenecePassed.length()) {
if (subStringPassed.contains(setenecePassed)
&& lastStringMiddle.contains(setenecePassed)) {
// only found one item no pattern but according to the example
// you posted it should return the length of one word/substring
count = setenecePassed.length();
substringFound = subStringPassed;
return count;
}
}
// makesure the lastSrtringMiddle has the key we are search
if (!lastStringMiddle.equals(subStringPassed)) {
subStringPassed = subStringPassed.replaceFirst(setenecePassed, "");
String lastString = subStringPassed.substring(0,
subStringPassed.lastIndexOf(setenecePassed));
if (null != lastString && !"".equals(lastString)) {
count = lastStringMiddle.length() + setenecePassed.length()
+ setenecePassed.length();
substringFound = setenecePassed + lastStringMiddle
+ setenecePassed;
subStringPassed = "";
}
return findNumberOfStrings(subStringPassed, setenecePassed, count);
}
return count;
}
}
I think this is much nicer recursive solution:
public int strDist(String str, String sub) {
if (str.length()==0) return 0;
if (!str.startsWith(sub))
return strDist(str.substring(1),sub);
if (!str.endsWith(sub))
return strDist(str.substring(0,str.length()-1),sub);
return str.length();
}
Here is what I have for method lastIndexOf , ch is the character to match, and str is the source string.
public static int lastIndexOf(char ch, String str) {
// check for null string or empty string
if (str.length() == 0 || str == null) {
return -1;
}
int indexInRest = lastIndexOf(ch, str.substring(1));
char first = str.charAt(0);
// recursive call to find the last matching character
if (first == ch) {
return 1 + indexInRest; // this might not work properly
} else
return indexInRest;
}
If in my class' main method I call:
System.out.println(lastIndexOf('r', "recurse"));
System.out.println(lastIndexOf('p', "recurse"));
I got:
1
-1
The desired result is:
4
-1
Suggestion, please.
How about taking the functional approach..
public static int lastIndexOf(char ch, String str) {
if (str.charAt(str.length() - 1) == ch) { return str.length() -1; }
if (str.length() <= 1) { return -1; }
return lastIndexOf(ch, str.substring(0, str.length() - 1));
}
This must be homework because there would be no point to writing this method since String.lastIndexOf() exists in the API, and using recursion to do this going to be slow and use a lot of memory.
Here a hint. Right now your algorithm is chopping characters off the front ( substring(1) ) and comparing them. lastIndexOf() should start by removing characters at the back of the String looking for a match then quit when it finds one.
why not use String.lastIndexOf like this:
str.lastIndexOf(ch)
Use the String#lastIndexOf(int ch) implementation as a general guideline,
public int lastIndexOf(int ch) {
return lastIndexOf(ch, value.length - 1);
}
public int lastIndexOf(int ch, int fromIndex) {
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
int i = Math.min(fromIndex, value.length - 1);
for (; i >= 0; i--) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return lastIndexOfSupplementary(ch, fromIndex);
}
}
private int lastIndexOfSupplementary(int ch, int fromIndex) {
if (Character.isValidCodePoint(ch)) {
final char[] value = this.value;
char hi = Character.highSurrogate(ch);
char lo = Character.lowSurrogate(ch);
int i = Math.min(fromIndex, value.length - 2);
for (; i >= 0; i--) {
if (value[i] == hi && value[i + 1] == lo) {
return i;
}
}
}
return -1;
}
And this,
lastIndexOf(ch, value.length - 1);
value is the target String as a character array.
First, you should change to:
if (str == null || str.length() == 0) {
Because a NPE could raise if str is null
Add a deep paramater to your code like this:
public static int lastIndexOf(char ch, String str, int deep) {
And increment its value every recursive call
int indexInRest = lastIndexOf(ch, str.substring(1), deep++);
then, in the return sentence, add deep to your returned value:
return 1 + indexInRest + deep; // this might not work properly
Call the function the first time with deep = 0, or better yet, make the two parameter method lastIndexOf call the 3 parameters version of lastIndexOf with the deep parameter set to 0
You can also use Matcher in order to anticipate evolution of string analysis asked by your homework:
public int getlastMatch(String searchPattern,String textString) {
int index = -1;
Pattern pattern = Pattern.compile(searchPattern);
Matcher matcher = pattern.matcher(textString);
while(matcher.find()) {
index = matcher.start();
}
return index;
}
where textString may be your concerned character.
Thus returning the last occurence of a part of string within a string.