The easiest way is to scroll through the characters of String
with a for
simple, but if you really want to do recursive, come on...
First of all, this function is not exactly recursive:
public static char funcao (String texto, int indice){
if (indice == 0){
return texto.charAt(indice);
} else {
funcao(texto, indice - 1);
return texto.charAt(indice);
}
}
I mean, you even call the function within itself, but you don’t use the result of this call for anything.
The line funcao(texto, indice - 1);
calls the function, but its return is not assigned to any variable, which makes this call useless. And in the end you call texto.charAt(indice)
, which is exactly the same as what is done inside the if (indice == 0)
. That is, this function always returns texto.charAt(indice)
.
There is no reason to take the character of the position X recursively, because the method charAt
already returns this character directly. We can then discard this function.
To recursively check the characters of a String
are lower case letters, we can consider the following:
- if the
String
is empty, the result is zero
- if the
String
is not empty, the result is the sum of two things:
1
or 0
(depending on whether the first character is lowercase or not)
- the total of lower case characters of the remainder of
String
(from the second character onwards)
An example: if the String
for Abc
and apply the above algorithm, as would be?
- to
String
is empty? No, then let’s go to the next step
- the first character (
A
) is it tiny? No, so the partial result is zero.
- now I check the rest of the
String
(bc
)
- the first character (
b
) is it tiny? Yes, so the partial result of this step (that is, of the piece bc
) is 1
- now I check the rest of the
String
(c
)
- the first character (
c
) is it tiny? Yes, so the partial result of this step (that is, of the piece c
) is 1
- now I check the rest of the
String
(to String
empty, because no more characters)
- as the
String
is empty, the partial result of this step is zero.
Adding up the partial results of each step, the result is 2.
The code would look like this:
public static int contaLetrasMinusculas(String texto) {
// se a String for vazia, retorna zero
if (texto.isEmpty()) {
return 0;
}
// verifica se o primeiro caractere da String é minúsculo
char primeiro = texto.charAt(0);
// se for minúsculo, "c" é igual a 1, senão é zero
int c = Character.isLowerCase(primeiro) ? 1 : 0;
// retorna "c" + a contagem do restante da string
return c + contaLetrasMinusculas(texto.substring(1));
}
Some examples of use:
System.out.println(contaLetrasMinusculas("")); // 0
System.out.println(contaLetrasMinusculas("A")); // 0
System.out.println(contaLetrasMinusculas("b")); // 1
System.out.println(contaLetrasMinusculas("aBcdEFGHiJ@1-")); // 4
Of course you can make it more succinct, but then you see if it becomes less readable/ more difficult to understand:
public static int contaLetrasMinusculas(String texto) {
if (texto.isEmpty()) {
return 0;
}
return (Character.isLowerCase(texto.charAt(0)) ? 1 : 0)
+ contaLetrasMinusculas(texto.substring(1));
}
Unicode
The above code works well for our alphabet. But to work with any Unicode characters, we must make some modifications. For more details on how Unicode works, I recommend oracle tutorial and this question.
In general, Unicode allows characters that do not fit in one char
(and are stored internally in two chars
- the so-called surrogate pair). So use this approach of charAt
does not work for these characters.
And instead use char
, we use codepoints (which is the numeric code that all characters have within Unicode).
If you want a more general solution that works with any Unicode characters, the code looks like this:
static int contaLetrasMinusculas(String texto) {
if (texto.isEmpty()) {
return 0;
}
// primeiro Unicode codepoint da String
int primeiro = texto.codePointAt(0);
int c = Character.isLowerCase(primeiro) ? 1 : 0;
// Character.charCount verifica se o codepoint ocupa um ou dois chars
return c + contaLetrasMinusculas(texto.substring(Character.charCount(primeiro)));
}
The code keeps working for the previous cases:
System.out.println(contaLetrasMinusculas("")); // 0
System.out.println(contaLetrasMinusculas("A")); // 0
System.out.println(contaLetrasMinusculas("b")); // 1
System.out.println(contaLetrasMinusculas("aBcdEFGHiJ@1-")); // 4
But now it also works for other Unicode characters, such as (DESERET SMALL LETTER LONG I), which corresponds to Unicode Codepoint 66600 and is considered lowercase:
// DESERET SMALL LETTER LONG I http://www.fileformat.info/info/unicode/char/10428/index.htm
String s = new String(Character.toChars(66600));
System.out.println(contaLetrasMinusculas("aA" + s + "Bb")); // 3
is not duplicate? https://answall.com/q/331602/28595
– user28595
Does it have to be recursive? Because it doesn’t seem to be such a problem.
– Gustavo Fragoso
@Gustavofragoso In exercise asks to use recursion but does not specify to what. I’m learning about recursion yet.
– water
@Article In my view it is not about duplicate because I am dealing with other different types of results.
– water