Roozilla
Roozilla

Reputation: 83

Java specific characters in for loop

I have written a code to reverse the order of vowels in a given string, but I also need to maintain the original positioning of the vowel capitalization in the string. For example, input : Java Is Fun output: Juvi As Fan rather than, JuvI as Fan.

Here is my Code so far which currently outputs JuvI as Fan:

static boolean isVowel(char c)
  {
      return (c == 'a' || c == 'A' || c == 'e'
                || c == 'E' || c == 'i' || c == 'I'
                || c == 'o' || c == 'O' || c == 'u'
                || c == 'U');
public static String reverseVowels(String text)
  {
      int index = 0;
      char[] str = text.toCharArray();
      String vowel = "";
      for (int i = 0; i < str.length; i++)
      {
          if (isVowel(str[i]))
          {
              index++;
              vowel += str[i];
          }
      } 
      for (int i = 0; i < str.length; i++)
      {
          if (isVowel(str[i]))
          {
              str[i] = vowel.charAt(--index);
          }
      }
      return String.valueOf(str);

Upvotes: 0

Views: 242

Answers (2)

Jan Held
Jan Held

Reputation: 654

I would search the String from left and right, looking for the next vowel character, then swap the two, while preserving the original case. It's a bit verbose but I like to build solutions, that are more generic, to be reusable for different scenarios.

Maybe it's of some value to you.

public class ReverseVowels {

    private static final char[] VOWELS = new char[] { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };

    public static void main(String[] args) {
        final String input = "Java Is Fun";
        final String expected = "Juvi As Fan";
        final String actual = reverseVowels(input);
        if (actual.equals(expected)) {
            System.out.println("Awesome! It worked!");
        }
    }

    /**
     * Reverses the vowels within the given string. Keeps the original character's case.
     *
     * @param s the string to reverse the vowels in
     * @return the manipulated string
     */
    private static String reverseVowels(String s) {
        char[] chars = s.toCharArray();
        int l = -1;
        int r = chars.length;
        do {
            l = indexOfAny(s, VOWELS, l + 1);
            r = lastIndexOfAny(s, VOWELS, r - 1);

            if (l <= r && l > -1) {
                char charLeft = chars[l];
                char charRight = chars[r];
                chars[l] = Character.isUpperCase(charLeft) ? Character.toUpperCase(charRight) : Character.toLowerCase(charRight);
                chars[r] = Character.isUpperCase(charRight) ? Character.toUpperCase(charLeft) : Character.toLowerCase(charLeft);
            }

        } while (l > -1 && r > -1 && r > l);

        return new String(chars);
    }

    /**
     * Finds the next position of any given char in the string, starting at the given position.
     *
     * @param s the string to search
     * @param chars the chars to find
     * @param startPos the start position
     * @return the index of the next char or -1 if char could not be found
     */
    public static int indexOfAny(String s, char[] chars, int startPos) {
        startPos = Math.max(0, startPos);
        for (int i = startPos; i < s.length(); i++) {
            char c = s.charAt(i);
            if (containsChar(chars, c)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Finds the next position of any given char in the string, looking backwards, starting at the given position.
     *
     * @param s the string to search
     * @param chars the chars to find
     * @param startPos the start position
     * @return the index of the next char or -1 if char could not be found
     */
    public static int lastIndexOfAny(String s, char[] chars, int startPos) {
        startPos = Math.min(s.length() - 1, startPos);
        for (int i = startPos; i >= 0; i--) {
            char c = s.charAt(i);
            if (containsChar(chars, c)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns true, if the char array chars contains the given char c.
     *
     * @param chars the char array to search in
     * @param c the char to search for
     * @return true if found, false otherwise
     */
    public static boolean containsChar(char[] chars, char c) {
        for (char c2 : chars) {
            if (c == c2) {
                return true;
            }
        }
        return false;
    }
}

Upvotes: 0

tyhdefu
tyhdefu

Reputation: 90

I would record all capital letters (or lowercase if theres more capitals than lowercase in the string) eg.

List<Integer> capitalLetters = new ArrayList<>(); // Positions of capital letters.

for (int i = 0; i < text.length(); i++) {
    if (Character.isUpperCase(text.charAt(i))) {
         capitalLetters.add(i);
    }
}
text = text.toLowerCase();

int index = 0;
char[] str = text.toCharArray();
String vowel = "";
for (int i = 0; i < str.length; i++) {
    if (isVowel(str[i])) {
        index++;
        vowel += str[i];
    }
}
for (int i = 0; i < str.length; i++) {
    if (isVowel(str[i])) {
        str[i] = vowel.charAt(--index);
    }
}

// Recapitalise.
for (int pos : capitalLetters) {
    str[pos] = Character.toUpperCase(str[pos]);
}
return str;

I would also change your vowel checking function to:

c = Character.toLowerCase(c);
return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');

To avoid checking for uppercase letters

Upvotes: 1

Related Questions