-1

//Is there any other way of implementing than the below? Please Advice

package chapter1.arrays.strings;

public class CountsOfRepeatedChars {

    public static void main(String[] args) {

        String str = "aabcccccaaa";
        StringBuilder sb = new StringBuilder();

        char[] arr = str.toCharArray();
        char previous = ' ';
        int count = 0;
        int i = 0;
        for (char c : arr) {
            i += 1;
            if (c == previous) {
                count += 1;
            } else {
                if (count > 1) {
                    sb.append(count);
                    sb.append(c);
                    count = 1;
                } else {
                    count = 1;
                    if (previous != ' ' && previous != c) {
                        sb.append(1);
                    }
                    sb.append(c);
                }
            }
            if (arr.length == i) {
                sb.append(count);
            }
            previous = c;
        }
        System.out.println(sb.toString());
    }

}
// Output is a2b1c5a3
SatyaTNV
  • 4,137
  • 3
  • 15
  • 31
Venu
  • 17
  • 1
  • 4
  • [Duplicate of count number of chars in a string](http://stackoverflow.com/questions/275944/how-do-i-count-the-number-of-occurrences-of-a-char-in-a-string) – SatyaTNV Dec 12 '15 at 05:11

6 Answers6

0

You code has at least two defaults:

  • big one: you mix char, and nimbers. Then if you store, for example: x11, how do you distinguish it from xxxxxxxxxxx , ...

  • you dont have coded the decoding part. you will have problems with the preceding point

Advice: use some "escape" char to indicate count: like /11/ , and if you want to encode /, just use //

And it will be more easy to decode.

Hope it helps

0

There is a much better way of doing so. You can use the HashSet container from Java Collections. A HashSet is a container which uses Hashing and allows lookup and insertion of entries in amortized O(1) time.

In your scenario, you can insert each character, if it doesn't exist in the HashSet into the set and at the same time, append it to a StringBuilder object. Finally, convert the that to a String and you're done.

String a="aaaabbbbcccc";
StringBuilder sb=new StringBuilder();
HashSet<Character> hs=new HashSet<Character>(); //Stores a unique entry for each character
for(int i=0;i<a.length();i++)
    if(!hs.contains(a.charAt(i)))
    {
        sb.append(a.charAt(i));
        hs.add(a.charAt(i));
    }
String compStr=sb.toString();
System.out.println(compStr);
gabbar0x
  • 4,046
  • 5
  • 31
  • 51
0

This is very simple solution without using any collection in Java. In this approach compare character with the next position character and take a variable called count=1 for each character present in the string & in the case of repetition we will increase this count. After comparing we have two possibility : 1. IF MATCHES then keep increases count by one. 2. IF DOESN'T MATCHES then print the present character and the count. Here is the code.

class CompressionString {
public static void main(String[] args) {
    String str = "aabcccccaaa";
   // for each character present in the string
    int count = 1;
    for (int i = 0; i < str.length(); i++) {
        //comparing char to next position character
        if (i < str.length() - 1) {
            if (str.charAt(i) == str.charAt(i + 1)) {
                count++;
            }
            //if char doesn't match then print character and total count
            else {
                System.out.print(str.charAt(i) + "" + count);
                count = 1;
            }
        }
        //this condition for the last character
        else {
            System.out.println(str.charAt(i) + "" + count);
        }
    }

}

}

Rahul Jaiman
  • 41
  • 1
  • 10
0

I have used C# - We can use a StringBuilder class to append the character and their counts.

Use a for loop to traverse.

Write an IF condition to append the character and its corresponding count in a StringBuilder.

At the end check if length of the compressed string is less than the source string. If yes, return the compressed string as the output.

    public static string CompressedString(string source)
    {
        int countConsecutive = 0;
        string compressed = String.Empty;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < source.Length; i++)
        {
            countConsecutive++;
            if (i >= source.Length - 1 || source[i] != source[i + 1])
            {
                sb.Append(source[i]);
                sb.Append(countConsecutive);
                countConsecutive = 0;
            }
        }

        compressed = sb.ToString();
        Console.WriteLine($"Compressed String is {compressed}");
        return (compressed.Length < source.Length) ? compressed : source;
    }
VAT
  • 170
  • 2
  • 4
  • 20
  • hows your "source" variable changed from "string" input to an "array"? – OlaB Aug 28 '19 at 16:58
  • this works perfectly fine.... source is a string and i m enumerating it char by char... – VAT Aug 29 '19 at 03:17
  • Okay I was assuming this is not Java code, because if it is, the logic is right but all the syntax is totally wrong. its "String" not "string" in java. Length is for traversing arrays, and size for lists, and you have to use "length()" not "length" in for loop for String. So I assume once again its c++ or something you posted – OlaB Aug 29 '19 at 13:29
  • your input " string source" in this code is completely referenced with array method calls in java. Even accessing its index is array, because for string its "source.charAt(i)", unless you forgot to convert it to a char array. – OlaB Aug 29 '19 at 13:40
  • updated the answer so that there is no confusion about the coding language.. thnx :) – VAT Aug 29 '19 at 14:40
0

Below is Python implementation of same problem incase any one wants. It is more concise and clear.

Traverse required string (s) while keeping track of last visited char and increase count every time next char is equal to previous char. When next char is different then append current char and its count in a list (compressed_str) and reset counter.

As loop will end after reaching at end of string, so to handle last char compression, you have to save its count in list outside the body of loop.

List will be used to save character and its number of occurrences in string which will be ultimately concatenated to generate a final compressed string.

For example corresponding list of given string "aabbbcaa" will be [a,2,b,3,c,1,a,2]

s = 'aabbbcaa'
last_seen_char = ''
count = ''

if s:
    last_seen_char = s[0]
    count = 1

compressed_str = []

for i in range(1, len(s)):
    if s[i] == last_seen_char:
        count += 1
    else:
        compressed_str.extend([last_seen_char, str(count)])
        last_seen_char = s[i]
        count = 1

compressed_str.extend([last_seen_char, str(count)])

compressed_str = ''.join(compressed_str)

print(compressed_str)

# a2b3c1a2 is your compressed string
Omer Iftikhar
  • 51
  • 1
  • 6
0

python Implementation.

def stringComprehension(string):
    compressedString = ""
    consecutiveStringCount = 1

    if len(string) < 2:
        return string

    for i in range(len(string)-1):
        if string[i] == string[i + 1]:
            consecutiveStringCount += 1
        else:
            compressedString += string[i] + str(consecutiveStringCount)
            consecutiveStringCount = 1
    compressedString += string[i+1] + str(consecutiveStringCount)

    if len(compressedString) >= len(string):
        return string
    else:
        return compressedString


def test():
    input1 = "tTTttaAbBBBccDd"
    input2 = "aabcccccaaa"
    input3 = "abcd"
    input4 = "aaaaaabbccbcaabb"
    input5 = "aabcccccaa"
    input6 = "a"

    print(input1, "compressed string -->", stringComprehension(input1))
    print(input2, "compressed string -->", stringComprehension(input2))
    print(input3, "compressed string -->", stringComprehension(input3))
    print(input4, "compressed string -->", stringComprehension(input4))
    print(input5, "compressed string -->", stringComprehension(input5))
    print(input6, "compressed string -->", stringComprehension(input6))


test()
Mide
  • 1