How does this particular recursion works - java

How does this particular recursion works
return (X.charAt(m-1) == Y.charAt(n-1) ? count(X, Y, m-1, n-1) : 0) + count(X, Y, m-1, n) 
in the below code?
The below code will return the count of number of times the pattern appears in a given string as a subsequence.
class Subsequence {
public static int count(String X, String Y, int m, int n) {
if (m == 1 && n == 1)
return X.charAt(0) == Y.charAt(0) ? 1 : 0;
if (m == 0)
return 0;
if (n == 0)
return 1;
if (n > m)
return 0;
return (X.charAt(m - 1) == Y.charAt(n - 1) ? count(X, Y, m - 1, n - 1) : 0) + count(X, Y, m - 1, n);
}
public static void main(String[] args) {
String X = "subsequence";//input String
String Y = "sue";// pattern
System.out.print(count(X, Y, X.length(), Y.length()));
}
}

It works as below:
if(X.charAt(m-1) == Y.charAt(n-1))
return count(X, Y, m - 1, n - 1);
else
return 0; //since no match found here
Now, the above code is breakage of the first line of your return statement that uses ternary operator. Don't think that this is the complete break down of this code.
So, once you got this statement, the next step would be call this function again to find any matching characters starting from m- in first string and from n in the pattern string since we need to still match the whole pattern right from the start. However, if we find a match, we are just proceeding to match remaining available characters in both pattern and the string.
But to be honest, there are many better ways to code the pattern matching algorithm as compared to this approach.

You will often find that renaming your variables properly and adding some clarification comments works wonders.
public static int count(String string, String pattern, int stringLength, int patternLength) {
if (stringLength == 1 && patternLength == 1) {
// Two length=1 strings -> if they are equal then they match - obviously.
return (string.charAt(0) == pattern.charAt(0)) ? 1 : 0;
}
if (stringLength == 0) {
// No more string to search - no-match.
return 0;
}
if (patternLength == 0) {
// No more pattern to search - MATCH!
return 1;
}
if (patternLength > stringLength) {
// Can never find a pattern longer than the string.
return 0;
}
return ((string.charAt(stringLength - 1) == pattern.charAt(patternLength - 1)) ?
// Both end with same character - recurse to keep matching.
count(string, pattern, stringLength - 1, patternLength - 1)
// Not match.
: 0)
// ADD any matches further down the string.
+ count(string, pattern, stringLength - 1, patternLength);
}
Sadly the code is wrong somewhere - searching for sue in subsequence prints 7.

I believe it is called a "Ternary Operator", it is another way to do IF statements in a more compact way (ie if you do a load of them at the same time for readability). It has to have somewhere to give the return value (a variable or return statement for example)
As an example it can look like this
boolean test = (condition) ? true : false;
Which is the same as writing
boolean test;
if (condition) {
test = true;
} else {
test = false;
}
CodeHunter's answer is a good example of how the sample code you gave is turned back into an if statement.
What it is doing is:
(Psuedo)
function recursiveCount(stringStart, stringEnd, startLocation, endLocation) {
/* pre-checks */
// Total will be how many times it loops (1 + 1 + 1 + 1 + 1 basically what it is doing)
// If there is no more occurances of that string it adds 0 instead of 1, and the recursion breaks.
return (total + recursiveCount(stringStart, stringEnd, nextStartLocation, nextEndLocation)
}

Related

Codingbat challenge: mirrorEnds using Stream API

Given the task mirrorEnds from CodingBat:
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 beginning 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".
Examples:
mirrorEnds("abXYZba") → "ab"
mirrorEnds("abca") → "a"
mirrorEnds("aba") → "aba"
My solution for this task is the following:
public String mirrorEnds(String str) {
String result = "";
if (str.length() % 2 != 0) {
for (int i = 0; i < str.length() / 2; i++) {
if (str.charAt(i) == str.charAt(str.length() - i - 1)) {
result += "" + str.charAt(i);
} else {
break;
}
}
if (result.length() == str.length() / 2) {
String strEnd = new StringBuilder(result).reverse().toString();
result += "" + str.charAt(str.length() / 2) + strEnd;
}
}
if (str.length() % 2 == 0) {
for (int i = 0; i < str.length() / 2; i++) {
if (str.charAt(i) == str.charAt(str.length() - i - 1)) {
result += "" + str.charAt(i);
} else {
break;
}
}
if (result.length() == str.length() / 2) {
String strEnd = new StringBuilder(result).reverse().toString();
result += strEnd;
}
}
return result;
}
Is it possible to solve this problem using Stream API ?
I think Stream API wouldn't give you any advantage. however, you can optimize your code like this
public String mirrorEnds(String string) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == string.charAt(string.length() - i - 1)) {
result.append(string.charAt(i));
} else {
break;
}
}
return result.toString();
}
It's doable with IntStream.range() in a single stream-statement.
In order to create a one-liner we will need'll a help of takeWhile(), which was introduced with Java 9. takeWhile() is a so-called short-cercuit operation, i.e. it will break after the first element that doesn't match the given predicate.
public static String mirrorEnds(String str) {
return IntStream.range(0, str.length())
.takeWhile(i -> str.charAt(i) == str.charAt(str.length() - 1 - i))
.map(str::codePointAt)
.collect(StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append)
.toString();
}
Since CodingBat is still on Java 8, its compiler will complain at the code above.
A very nice, a simple Java 8 compliant solution proposed by #Holger.
It looks for the index of the first mismatch between characters at the beginning and at the end, and generates a substring starting from the very beginning 0 up to themismatch index.
In case if findFirst() returns an empty optional, i.e. the given string is a palindrome and there's no mismatch, the length of the given string will be provided via orElse().
The code below passes all tests on CodingBat.
public String mirrorEnds(String str) {
int mismatch = IntStream.range(0, str.length() / 2)
.filter(i -> str.charAt(i) != str.charAt(str.length() - 1 - i))
.findFirst()
.orElse(str.length());
return str.substring(0, mismatch);
}
Note since CodingBat disallows imports, in order to run the code above on this site you need to use a so-called fully-qualified name of the class java.util.stream.IntStream.
Since you're purposely asking for a stream-solution to this problem, this could be to look for the greatest index i where the first i characters match the last i characters reversed, with i starting from length() / 2 and proceeding by decrementing i until it reaches 0.
The previous algorithm makes sense to be applied only if the given string isn't a palindrome. In fact, in that case, the string itself could be returned immediately.
public static String mirrorEnds(String str) {
if (str.equals(new StringBuilder(str).reverse().toString())) {
return str;
}
OptionalInt maxLen = IntStream.iterate(str.length() / 2, i -> i >= 0, i -> i - 1)
.filter(i -> str.substring(0, i).equals((new StringBuilder(str.substring(str.length() - i))).reverse().toString()))
.max();
return maxLen.isPresent() ? str.substring(0, maxLen.getAsInt()) : null;
}
Output
ab
a
aba
Here is a link to test the code:
https://www.jdoodle.com/iembed/v0/rUL

A recursive method to check pattern in an array

I'm trying to write a recursive method in Java that will take two arrays of int and return true/false if the first array represent a pattern of the second array, in that way - (the pattern array accept 0, 1 or 2. 0 represent one or two digits number, 1 represent one digit numbers and 2 represent two digits numbers. so if I send {2, 3, 57} and {1, 0, 2} it will return true. if i put {2, 555, 57} and {1, 0, 2} it will return false. also, if i put {2,3,573**,4,34,35}** and {1, 0, 2} i still need to get true, since part of the array represnt the pattern.
i came up with this:
private static boolean match(int [] a, int [] pattern, int i, int j, int c, int subArr)
{
if(a.length < pattern.length)
return false;
else if(pattern.length == 0)
return true;
else if(pattern.length == a.length && check(a, pattern, i, j))
return true;
else if(check(a, pattern, i++, j++))
{
return check(a, pattern, i, j);
}
else return false;
}
private static boolean check(int [] a, int [] pattern, int i, int j)
{
if(pattern[j] == 1 && (checkDigits(a[i]) == 1))
{
return true;
}
else if(pattern[j] == 2 && checkDigits(a[i]) == 2)
{
return true;
}
else if(pattern[j] == 0 &&(checkDigits(a[i]) == 1 || checkDigits(a[i]) == 2 )){
return true;
}
else return false;
}
private static int checkDigits(int k){
int length = (int)(Math.log10(k)+1);
return length;
}
the match method is doing all the checks. the check methode is checking the pattern and checkDigits the number of digits.
My problem is with 3 digits numbers. if i put for exemple { 2, 123, 54 } and {1, 0, 2} I get true and not false. I belive the problem is in the check method but I can't locate the problem.
Check this code I wrote right now, I added comments to the code, and if you run it. I wrote some text on the console to explain to you how it's working. So at the end when you want to use it, just remove the system.out.print
public class ArrayPattern {
static int numbers[] = {1,10,20,3,30};
static int pattern[] = {0,0,2,2};
public static void main(String[] args) {
System.out.println(isPattern(0, 0));
}
/**
* Recursive method that checks for the pattern. If it fails to match pattern starting from index i, it
* tries starting from index i+1
* */
public static boolean isPattern(int index, int consec){
// If all pattern values where matched consecutively
if(consec == pattern.length)
return true;
// If the numbers ended and the pattern wasn't found
if(index == numbers.length)
return false;
// If the current number matches the pattern, check the next number at index + 1
if(checkPattern(pattern[consec], numbers[index])){
System.out.println(pattern[consec] +" => "+ numbers[index]);
return isPattern(index+1, consec+1);
}
// If the pattern was not found, starting from a specific index. Start from the next index to check if the pattern can be found
System.out.println(String.format("\nFailed to match pattern, try starting from index: %d\n", (index - consec + 1)));
return isPattern(index - consec + 1, 0);
}
/**
* Just chesk the pattern:
* 0 => 1 or 2 digits.
* 1 => 1 digit.
* 2 => 2 digits
*/
public static boolean checkPattern(int pattern, int value){
String sValue = String.format("%d", value);
switch (pattern) {
case 0:
return sValue.length() <= 2;
default:
return sValue.length() == pattern;
}
}
}
A truly recursive solution might be the following:
import java.util.Arrays;
public class Checker {
//0 represent one or two digits number,
//1 represent one digit numbers and
//2 represent two digits numbers
public boolean match(int [] a, int [] pattern, int i, int j)
{
if(pattern.length == 0) return true;
if(pattern.length == a.length) {
return check(a, pattern);
} else {
return false;
}
}
//recursive function
private boolean check(int [] a, int [] pattern) {
boolean firstDigitCheck = false;
switch (pattern[0]) {
case 0: firstDigitCheck = checkDigits(a[0]) <3;break; // 1 or 2
case 1: firstDigitCheck = checkDigits(a[0]) <2;break; // 1
case 2: firstDigitCheck = checkDigits(a[0]) ==2;break// 2
default:break;//not important (we trust the pattern format)
}
if (a.length==1) {//base step (array of dimension 1)
return firstDigitCheck;
} else {//recursive step on the left-truncated arrays
return firstDigitCheck && check(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(pattern, 1, pattern.length));
}
}
public int checkDigits(int k){
int length = (int)(Math.log10(k)+1);
return length;
}
}
If I understand your question, then the element in array, "a", at index 'j' can have a certain number of digits based on the number at the element at index 'j' in pattern.
You could accomplish this with a for loop;
boolean result = true;
int [...] a = ...
int [...] pattern = ...
for (int j = 0; j < a.length(); j++) {
if (result) {
if (pattern[j] = 0) {
if (a[j].toString().length() > 2) {
result = false;
}
} else if (pattern[j] = 1) {
if (a[j].toString().length() != 1) {
result = false;
}
} else if (pattern[j] = 2) {
if (a[j].toString().length() != 2) {
result = false;
}
}
}
}
That should get the job done, or something similar.
I am a little unclear with your code. But it can be done in a simpler way using a for loop.
The basic algorithm you need to follow would be:
j=0
for(i = 0 to a.length){
if number of digits(a[i]) == pattern[j] {
j++
}
}
if j == pattern.length
print its a match
else
it is not.
This small piece of code will work for every case.
Instead of the for loop, just call it every time.

Given a string, does "xyz" appear in the middle of the string?

Given a string, does "xyz" appear in the middle of the string? To
define middle, we'll say that the number of chars to the left and
right of the "xyz" must differ by at most one. This problem is harder
than it looks.
My solution works without the second last line except for one condition: if str="xyx"
Is it possible to modify the for loop to take this into account...I'm struggling with understanding why it doesn't.
My solution does work I'm just trying to get a better understanding of what I'm doing. I know I could add it into the first if statement but I want to know why it doesn't work without it.
public boolean xyzMiddle(String str) {
for (int i=0;i<str.length()-3;i++) {
if (str.substring(i,i+3).equals("xyz")) {
String front =str.substring(0,i);
String end = str.substring(i+3);
int a =Math.abs(front.length() -end.length());
if (a<=1) return true;
}
}
if (str.equals("xyz")) return true;
return false;
I think i remember this question - it's this question from Codingbat, I believe. Excellent web site, learned a lot from that site back when I started programming. There's absolutely no reason to use a loop, though.
public boolean xyzMiddle(String str) {
boolean result = false;
int i = str.length()/2 -1;
if (str.length() >= 3 && (str.substring(i, i+3).equals("xyz") || (str.length()%2 == 0 && str.substring(i-1, i+2).equals("xyz")) )) {
result = true;
}
return result;
}
So, let's walk through this and why it works. Firstly, str.length() >= 3, because if the string isn't at least as long as "xyz", there's no way it can contain "xyz".
There are two main cases to this problem, we need to think of. The string can have an even or an uneven length. In the uneven case, it's easy:
The Uneven case
AAAxyzAAA // length = 9
012345678 // the indexes
^ // that's the middle, which can be calculated by length/2
// (since this is an integer divison, we disregard whatever comes after the decimal point)
So to get the start of the xyz-substring, we simply subtract one from this number - which is exactly what i is doing:
AAAxyzAAA // length = 9
012345678 // the indexes
i // i = length/2-1 = 3
So if str.substring(i, i+3) is xyz, we can return true!
The Even Case
Now, this can be a bit more tricky, since there is no true "middle" of the string. In fact, two indexes could be called the middle, so we have two sub-cases:
AAAAAAAA // length = 8
01234567 // the indexes
^^ // Which one is the true middle character?
In fact, the middle would be between index 3 and 4. However, we are performing integer divisions, length/2 is always the largest (rightmost) of the two possible "middles". And since we calculate i using the middle, the same as in the uneven case applies - str.substring(i, i+3) could be considered the middle part of the string.
AAAxyzAA
01234567
^^^ // str.substring(i, i+3)
i
But suppose our string was AAxyzAAA - that could also be considered the middle part of the string. So we need to move our substring check "to the left" - so we subtract 1 from it.
AAxyzAAA
01234567
^^^ // str.substring(i-1, i+2)
i // i is still at "the old" location
So is it even or not?
To check whether the string is even or uneven, we use the modulo operator, %. The easiest way to think of what it does is "what would be left over after i divided with this number?". So 3 % 2 would be 1. In our case, we want to make sure that the number is divisible by 2 with nothing left over - because that means it was an even number. Therefore, we need to check whether str.length() % 2 == 0 before we make our "move-to-the-left" check. If not, we could risk going out of bounds on the string. If the string was 3 characters long, and we moved one to the left... we would check the substring starting at index -1, and that doesn't make a lot of sense.
Put it all together, and there you go!
I'd say something as simple as:
public void test() {
test("Hello", "ll");
test("Hello", "He");
test("Hello", "el");
test("Hello", "lo");
test("Hello", "Hell");
test("Hello", "ello");
test("Hello", "Hello");
test("Hell", "He");
test("Hell", "el");
test("Hell", "ll");
}
private void test(String s, String p) {
System.out.println(p + (inMiddle(s, p) ? " in " : " not in ") + s);
}
// Is the pattern in the middle of the string.
public static boolean inMiddle(String s, String p) {
int d = s.length() - p.length();
return at(s, p, d / 2) || ((d & 1) == 1 && at(s, p, (d / 2) + 1));
}
private static boolean at(String s, String p, int i) {
return i >= 0 && i < s.length() && s.substring(i).startsWith(p);
}
Results look correct to me:
ll in Hello
He not in Hello
el in Hello
lo not in Hello
Hell in Hello
ello in Hello
Hello in Hello
He not in Hell
el in Hell
ll not in Hell
I have confirmed that this matches Tobias' solution exactly when p = "xyz".
public boolean xyzMiddle(String str) {
int len = str.length();
if (len < 3){ return false; }
int even = (len+1)%2;
int mid = len/2;
return str.substring(mid-1-even, mid+2).contains("xyz");
}
The simplest I could come up with:
public boolean xyzMiddle(String str) {
str = " " + str + " ";
int even = (str.length()+1)%2;
int mid = (str.length())/2;
str = str.substring(mid-1-even, mid+2);
return str.contains("xyz");
}
public boolean xyzMiddle(String str) {
int len = str.length();
if(len < 3) {return false;}
if(len==3 && str.equals("xyz")) {return true;}
int index = middleIndex(str);
String left = str.substring(0,index) ;
String right= str.substring(index+3) ;
//Return based on the difference by at most 1
return (Math.abs(left.length()-right.length()) <=1);
}
public int middleIndex(String str) {
int middleLen = (str.length())/2;
int index= 0;
//Find an index that could be in the middle of the string with
// "xyz"
for(int i=middleLen-2; i < middleLen; i++ ) {
if(str.substring(i, i+3).equals("xyz") ) {
index= i;
}
}
return index;
}
public boolean xyzMiddle(String str) {
if (str.length() >= 3)
{
// if odd
if (str.length() % 2 == 1)
{
//axyzb
//01234
//length = 5; 5 is odd.
//length / 2 = 2;
//2 minus 1 = 1
//1 is where xyz starts
//aaxyzbb
//0123456
//length = 7; 7 is odd.
//length / 2 = 3;
//3 minus 1 = 2
//2 is where xyz starts.
//....
//This pattern works with all odd numbers.
if (str.substring((str.length() / 2) - 1, ((str.length() / 2) - 1) + 3).equals("xyz"))
{
return true;
}
else
{
return false;
}
}
//if even
else
{
//for evens that occur with a larger amount before "xyz" than after
//axyz
//0123
//length = 4; 4 is even;
//4 - 1 = 3;
//3 / 2 = 1
//1 is where xyz starts.
//aaxyzb
//012345
//length = 6; 6 is even;
//6 - 1 = 5;
//5 / 2 = 2
//2 is where xyz starts.
//...
//This pattern works for all even numbers where there is a larger amount of characters before the xyz.
if (str.substring((str.length() - 1) / 2, ((str.length() - 1) / 2) + 3).equals("xyz"))
{
return true;
}
//For the cases where there are more characters after "xyz" than before.
//xyzb
//0123
//length = 4; 4 is even;
//4 - 1 = 3;
//3 / 2 = 1
//1 - 1 = 0;
//xyz starts at 0;
//axyzbb
//012345
//length = 6; 6 is even;
//6 - 1 = 5;
//5 / 2 = 3;
//2 - 1 = 1;
//xyz starts at 1;
//...
//The pattern continues onwards for all cases where there are more characters after xyz than before.
else if (str.substring((((str.length() - 1) / 2) - 1), (((str.length() - 1) / 2) -1) + 3).equals("xyz"))
{
return true;
}
//If there is no instance of xyz in these areas.
else
{
return false;
}
}
}
// If our string is less than 3 in length.
else
{
return false;
}
}
public boolean xyzMiddle(String str) {
return str.length()>2 && str.length()%2==1 && str.substring((str.length()-1)/2-1,(str.length()/2+1)+1).contains("xyz") || str.length()>2 && str.length()%2==0 && (str.substring(str.length()/2-2,str.length()/2+1).contains("xyz") || str.substring(str.length()/2-1,str.length()/2+2).contains("xyz"));
}
public boolean xyzMiddle(String str) {
int index = str.indexOf("x");
if(index < 0)
return false;
while(index >=0 && (index+3 <= str.length()) ){
if(str.substring(index,index+3).equals("xyz") && Math.abs(str.substring(0,index).length() - str.substring(index+3).length()) <=1)
return true;
index = str.indexOf("x",index+1);
}
return false;
}

How do I make a boolean method using a string?

This is what I have so far, I managed to reach here with several hours of work. The problem with my code is that if i give it a string "abcefg" it will verify the first two characters and returns it as true. I want the code to do it for all of my characters. I thought that putting the limit as x.length() would do the thing, but for some reason, it won't work.
public static boolean ConsecutiveCheckerAscending(String x) {
x = x.toLowerCase();
for (int i = 0; i < x.length() - 1; i++) {
if ((int)x.charAt(i) + 1 != ((int)x.charAt(i + 1)))
{
return false;
}
}
return true;
}
public static boolean ConsecutiveCheckerDescending(String x) {
x = x.toLowerCase();
for (int i = 0; i < x.length() - 1; i++) {
if((int)x.charAt(i) - 1 != ((int)x.charAt(i + 1)))
{
return false;
}
}
return true;
}
You have a variety of issues here.
Firstly, you can eventually go out of bounds with the charAt(i + 1) calls (check your loop condition).
Secondly, how can you possibly return true in the body of the for-loop? You haven't checked all of the characters yet!
I think you're making this overly complicated, though. All you need to do in order to check that two contiguous (i.e. next to each other in the string) characters are consecutive is
Math.abs(s.charAt(i) - s.charAt(i + 1)) == 1
You actually don't even need a cast. What we're doing is checking that the "distance" between the two characters is 1.
Just apply that to every contiguous pair of characters in the string, and return false if it isn't satisfied somewhere along the line. If you exit the loop without ever returning false, you can return true.
You cannot know for sure if the string is consecutive until the end of the method, so you cannot return true in the middle. At most you can return false when you find that string is not consecutive.
To give more advice, what do you mean by "consecutive"? Is adgkm consecutive? Looking at the current code it would look like it; all you check is the order of the characters. Is abcdcbcd consecutive? Usually "consecutive" means there are no gaps.
In both if and else statements you having return statement, So the method will return after first check. You have to give return only for the exit condition. don't give for both if and else
Wrote it in a rush, but it'd look something like this.-
public static boolean ConsecutiveChecker(String x) {
boolean consecutive = true;
x = x.toLowerCase();
for (int i = 0; i < x.length() - 1; i ++) {
if ((int) x.charAt(i) + 1 != ((int) x.charAt(i + 1))) {
consecutive = false;
break;
}
}
return consecutive;
}

count uppercase chars in string recursively

I have to solve an exercise, counting all the uppercase chars in a String - recursively - Anyhow I thought I might have found a solution - but it won't work…
Probably you might help me? Thanks!
public static int CountCapitals(String s) {
int counter = 0;
// if (Character.isUpperCase(s.charAt(0)))counter+=1;
if (s.length() == 0)
return counter;
if (s.length() == 1 && s.charAt(0) < 65 && s.charAt(0) > 90)
return 0;
if (s.charAt(0) < 'A' && s.charAt(0) > 'Z') {
return CountCapitals(s.substring(1));
}
if (s.charAt(0) >= 'A' && s.charAt(0) <= 'Z')
counter++;
return CountCapitals(s.substring(1));
}
The problem with your code is the use of counter: each level of invocation has its own counter, initially set to zero. The ++ operator at the bottom has no effect.
You need to compute the result of this invocation based on the result of the previous invocation. Your base case (i.e. s.length() == 0) is fine; the rest of your code needs to change so that it returns whatever CountCapitals(s.substring(1)) when the first letter is non-capital; when the first letter is capital, your function should return 1 + CountCapitals(s.substring(1)).
You need to consider the case when the length of string is 1 and the only character is uppercase (in this case, you should return 1).
Also you need to pass in the counter as a parameter rather than expecting it to "carry over" into other function calls.
This recursion should do just what you want:
public static int countCapitals(String s) {
if (s.length() == 0) return 0;
int cap = Character.isUpperCase(s.charAt(0)) ? 1 : 0;
return countCapitals(s.substring(1)) + cap;
}
If this wasn't a home assignment, you could try an iterative approach which is about 5-10 times faster:
public static int countCapitals(String s) {
int count = 0;
for (int idx = 0; idx < s.length(); idx++) {
if (Character.isUpperCase(s.charAt(idx))) {
count++;
}
}
return count;
}
You don't really need to use a counter variable to keep track of the number of capitals. Instead, you can just the recursive calls, themselves, to keep track of the total:
public static int CountCapitals(String s)
{
if (s.length() == 1)
return (Character.isUpperCase(s.charAt(0)) ? 1 : 0);
else
return CountCapitals(s.substring(1)) +
(Character.isUpperCase(s.charAt(0)) ? 1 : 0);
}
If this is for an assignment and you have to use ASCII values, then fine, but if not, you really should just Character.isUpperCase(char c). In case you're not familiar with the conditional operator, it's defined as follows:
if(someExpression == true)
{
//output 1
}
else
{
//output 0
}
is represented succinctly as:
(someExpression == true) ? 1 : 0
NB:
In your example, counter is set to 0 at the beginning of each method call, so that's why it's not working. If you really want to use a counter, pass it as a parameter to the method instead, and update the parameter with each method call. When you get to the end of the String, simply return the parameter.
You try this
public class HelloWorld{
public static int isUpperCase(String str){
if(str.length()==0) return 0;
boolean check =Character.isUpperCase(str.charAt(0));
if(check){
return isUpperCase(str.substring(1))+1;
}
return isUpperCase(str.substring(1));
}
public static void main(String []args){
String n= "FSAsdsadASdcCa";
System.out.println(isUpperCase("FSAsdsadASdcCa"));
}
}

Categories

Resources