Home > front end >  Code that takes a string and recognizes the number of consecutive letters
Code that takes a string and recognizes the number of consecutive letters

Time:03-27

To do my job, I need a code that takes a word from the user, then recognizes the number of consecutive letters and outputs it in such a way that it prints the letter and the number of times it is repeated.

Example input: hhhttrew output: h3t2rew

input: uuuuuuhhhaaajqqq output: u6h3a3jq3

I know it is very incomplete (:

String text = sc.nextLine();
            int len = text.length();

            int repeat = 0;

            char[] chars = new char[len];

            // To convert string to char
            for (int h = 0; h < len; h  )
            {
                chars[h] = text.charAt(h);
            }

            String finaly = "";

            for (char ignored : chars)
            {
                for (int j = 0 ; j <len ; j   )
                {
                    if (chars[j] == chars[j 1])
                    {
                        finaly = String.valueOf(chars[j]);

                        repeat  ;

                        finaly = String.valueOf(repeat);
                    }
                    else
                    {
                        j  ;
                    }
                }
            }
            System.out.println(finaly);

CodePudding user response:

Here is one way. You only need a single loop. The inner loop does the work. The outer loop simply supplies test cases.

  • assign the first character
  • and set count to 1 for that character
  • then iterate until adjacent characters are different
  • append count if > 1 and append the different character
  • set count to 0 for next run.
String[] data = { "uuuuuuhhhaaajqqq", 
        "hhhttrew","abbcccddddeeeeeffffffggggggg" };

for (String s : data) {
    String result = ""   s.charAt(0);
    int count = 1;
    for (int i = 1; i < s.length(); i  ) {
        if (s.charAt(i - 1) != s.charAt(i)) {
            result  = count <= 1 ? "" : count;
            result  = s.charAt(i);
            count = 0;
        }
        count  ;
        if (i == s.length() - 1) {
            result  = count <= 1 ? "" : count;
        }
    }
    System.out.printf("%-15s <-- %s%n", result, s);
}

prints

u6h3a3jq3       <-- uuuuuuhhhaaajqqq
h3t2rew         <-- hhhttrew
ab2c3d4e5f6g7   <-- abbcccddddeeeeeffffffggggggg

            

CodePudding user response:

Your solution can be greatly improved by just having one loop. Also, this does not use any complex data structures, so it is very efficient.

public static String consecutiveLetters(String text) {
        if (text == null || text.length() == 0) return "";

        // We start with he first letter
        char currentChar = text.charAt(0);
        int position = 1;
        int letterCount = 1;
        StringBuilder outputBuilder = new StringBuilder();

        do {
            // get the letter at the current position
            char charAtCurrentPos = text.charAt(position);

            // if it is different than what we had previously, we store the letter and the number of times it appeared. Reset the counter for the new letter
            if (charAtCurrentPos != currentChar) {
                outputBuilder.append(currentChar);
                currentChar = charAtCurrentPos;
                if (letterCount > 1) {
                    outputBuilder.append(letterCount);
                }
                letterCount = 1;
            } else {
                letterCount  ;
            }
            position  ;
        } while (position < text.length());

        // Add the last character as well
        outputBuilder.append(currentChar);
        if (letterCount > 1) {
            outputBuilder.append(letterCount);
        }

        return outputBuilder.toString();
    }

CodePudding user response:

I would take a different approach. The following algorithm will run in O(n) and thus be asymptotically (!!!) optimal. To make this clear as this seems to have caused some confusion. There are more efficient solutions with smaller constants.

Essentially the idea is to loop over all characters and store the number of occurrences in a Map. If an value that is not yet in the Map is encountered, we add it to the Map giving it a count of 1. If we have already encountered the value before we get that value and increase it by one. In the end we only need to iterate through the map once in order of insertion and get the key and value.

IMPORTANT: It is crucial for this implementation to use a LinkedHashMap as the insertion order MUST be preserved. A HashMap of TreeMap will give you a String which has the values in undefined order. See this thread for more details on this.

The runtime for this algorithm will be O(n) as all operations on the LinkedHashMap take O(1) and the rest of the time we are just looping over the n characters.

import java.util.*;

public class Application {
    public static void main(String[] args) {
        var result1 = compress("hhhttrew");
        var result2 = compress("uuuuuuhhhaaajqqq");
        System.out.println(result1);
        System.out.println(result2);
    }

    public static String compress(String uncompressed) {
        var charArr = uncompressed.toCharArray();
        // LinkedHashMap is required here to preserve the order of insertion
        var occurrences = new LinkedHashMap<Character, Integer>();
        // iterate over all characters and count all occurrences 
        for (var character : charArr) {
            if (occurrences.containsKey(character)) occurrences.put(character, occurrences.get(character)   1);
            else occurrences.put(character, 1);
        }
        // Create the target String by iterating over the map in order of insertion and concatenate key and value. Don't add the number of occurrence when the character occurs only once
        var sb = new StringBuilder();
        for (var entry : occurrences.entrySet()) {
            sb.append(entry.getKey());
            if(entry.getValue() != 1) sb.append(entry.getValue());
        }
        return sb.toString();
    }

}

Expected output:

h3t2rew
u6h3a3jq3
  • Related