liran
liran

Reputation: 105

Recursion - boolean condition and array of char

I have a problem in this recursion exercise.

The exercise is to test whether the array of characters has only uppercase or lowercase and only then return true; otherwise if there are both lowercase and uppercase letters, return false.

The code below always returns true.

I try to put a variable to count every time there is a large or small signal and then if the amount is equal to the array so it is true otherwise it is not true; but it does not give me that. It is a Boolean function and call recursion is not giving me the amount of the variable.

The code:

public static boolean Arr(char[] arr, int length) {
    if (length == -1)
        return true;
    boolean flag = Character.isUpperCase(arr[length]);

    if (flag)
        return true;

    return Arr(arr, length - 1);
}

Upvotes: 1

Views: 372

Answers (4)

Spotted
Spotted

Reputation: 4091

When dealing with boolean algebra, it's always worth it to write some unit to help us verify our work:

import static org.junit.Assert.*;

import org.junit.Test;

public class CharactersSpec {

    @Test
    public void itShouldBeTrueWhenAllCharsAreUppercase() {
        String input = "HELLO";

        assertEquals(true, Characters.isSameCase(input.toCharArray()));
    }

    @Test
    public void itShouldBeTrueWhenAllCharsAreLowercase() {
        String input = "hello";

        assertEquals(true, Characters.isSameCase(input.toCharArray()));
    }

    @Test
    public void itShouldBeFalseWhenOneCharIsLowercase() {
        String input = "HeLLO";

        assertEquals(false, Characters.isSameCase(input.toCharArray()));
    }

    @Test
    public void itShouldBeFalseWhenOneCharIsUppercase() {
        String input = "hEllo";

        assertEquals(false, Characters.isSameCase(input.toCharArray()));
    }
}

Then one can implement the method. I wouldn't implement it with recursion but it seems to be a requirement from your assignment:

import java.util.Arrays;

public final class Characters {
    public static boolean isSameCase(char[] chars) {
        return isSameCase(chars, false, false);
    }

    private static boolean isSameCase(char[] chars, boolean uppercaseFound, boolean lowercaseFound) {       
        if(chars.length == 0) {
            return true;
        }
        lowercaseFound |= Character.isLowerCase(chars[0]);
        uppercaseFound |= Character.isUpperCase(chars[0]);
        return !(lowercaseFound && uppercaseFound) && isSameCase(Arrays.copyOfRange(chars, 1, chars.length), 
                                                                uppercaseFound, 
                                                                lowercaseFound);
    }
}

Note a few things:

  • The only public method only takes a char[] as parameter, so that the caller don't have to bother with recursion details
  • I have decided to subarray instead of passing an index so that the method signature keeps 3 parameters (I always foster readability over performance, first)

Without the assignment's constraints I would implement this method as follow

public static boolean isSameCase(String input) {
    return input.equals(input.toLowerCase()) || input.equals(input.toUpperCase());
}

Note that:

  • I prefer to manipulate String over char[] in Java (it is more convenient)
  • I would avoid recursion as possible since I believe this practice is not well-suited in Java (most programmers are not familiar with and the language provides other ways to loop)

Upvotes: 0

yash sachdeva
yash sachdeva

Reputation: 636

See if this works

public static boolean Arr(char[] arr, int length) {
    if (length == -1)
        return true;
    boolean flag = Character.isUpperCase(arr[length]);

    if (flag)
        return Arr(arr, length - 1);
    else 
        return false;
}

Upvotes: 1

pjs
pjs

Reputation: 19855

Does this meet your needs?

The public front end just takes a character array, and invokes the private back end with starting values for the parameters that end users shouldn't have to worry about.

public static boolean sameCase(char[] ary) {
    return sameCase(ary, 0, ary.length - 1);
}

The back end seeks to split the current segment of the array into two subsegments—halving the problem keeps the rate of growth of the stack as O(log #chars) rather than O(#chars). If the current segment has fewer than two characters, then trivially all characters have the same case. Otherwise, check that each subsegment has characters that are all of the same case, and if so, check that the cases of the two subsegments are the same using XOR and a trick.

private static boolean sameCase(char [] ary, int first, int last) {
    int len = last - first + 1;
    int mid = first + len / 2;
    return len < 2 ||
      (sameCase(ary, first, mid - 1) && sameCase(ary, mid, last) &&
      (Character.isUpperCase(ary[first]) ^ Character.isLowerCase(ary[last])));
}

Note that by ANDing the recursive calls, logical short-circuiting speeds things up on average here.

Upvotes: 0

Davide Lorenzo MARINO
Davide Lorenzo MARINO

Reputation: 26926

You need an additional parameter in the function and an additional exit condition:

  • Additional parameter: Last character read was lower or uppercase
  • Additional test to exit: if current char has not the same case of last char exits with false

A second approach is to start not from the first char, but from the second and check for same case between current and prior character.

Upvotes: 1

Related Questions