Rayyan Merchant
Rayyan Merchant

Reputation: 157

Digit Frequency In A String

I am supposed to do this :

For an input number print frequency of each number in the order of its occurrence.For eg :
Input:56464
Output:
Number-Frequency
5 -1
6 -2
4 -2

I cannot use any other libraries except java.lang and Scanner to input
So I tried this :

package practice2;

import java.util.Scanner;

public class DigitFrequency2
{

    private static Scanner sc;

    public static void main(String[] args)
    {
        sc = new Scanner(System.in);
        System.out.println("Enter an integer number");
        String sb = sc.nextLine();
        System.out.println("Number\tFrequency");

        int i,x,c = 0;

        for(i=0;i<sb.length();i++)
        {
            c = 0;
            for(x = i+1;x<sb.length();x++)
            {
                if(sb.charAt(i) == sb.charAt(x) && sb.charAt(i) != '*' && sb.charAt(x) != '*')
                {
                    c++;
                    sb.replace(sb.charAt(x),'*');
                }
            }

            if(c>0)
            {
                System.out.println(sb.charAt(i)+"     \t"+c);
            }

        }
    }
}

Number  Frequency
6       1
4       1

Where am I going wrong please help.

Upvotes: 2

Views: 1209

Answers (4)

icza
icza

Reputation: 417432

Problem is that as mentioned, String is immutable, so String.replace() just returns a new string and it does not (cannot) modify the original. Either you should use StringBuilder, or store the returned value (e.g. sb = sb.replace(sb.charAt(x),'*');).

Going further, since you initialize c with 0, it will stay 0 if there is no other occurrence of the character in question (sb.charAt(i)), so your algorithm won't detect and print digits that occur only once (because later you only print if c > 0).

Counting occurrences (frequency) of characters or digits in a string is a simple operation, it does not require to create new strings and it can be done by looping over the characters only once.

Here is a more efficient solution (one of the fastest). Since digits are in the range '0'..'9', you can create an array in which you count the occurrences, and by looping over the characters only once. No need to replace anything. Order of occurrence is "remembered" in another order char array.

char[] order = new char[10];
int[] counts = new int[10];
for (int i = 0, j = 0; i < sb.length(); i++)
    if (counts[sb.charAt(i) - '0']++ == 0)
        order[j++] = sb.charAt(i); // First occurrence of the digit

And print in order, until the order array is filled:

System.out.println("Number\tFrequency");
for (int i = 0; order[i] != 0; i++)
    System.out.println(order[i] + "\t" + counts[order[i] - '0']);

Example output:

Enter an integer number
56464
Number  Frequency
5       1
6       2
4       2

For completeness here's the complete main() method:

public static void main(String[] args) {
    System.out.println("Enter an integer number");
    String sb = new Scanner(System.in).nextLine();

    char[] order = new char[10];
    int[] counts = new int[10];
    for (int i = 0, j = 0; i < sb.length(); i++)
        if (counts[sb.charAt(i) - '0']++ == 0)
            order[j++] = sb.charAt(i); // First occurrence of the digit

    System.out.println("Number\tFrequency");
    for (int i = 0; order[i] != 0; i++)
        System.out.println(order[i] + "\t" + counts[order[i] - '0']);
}

Note:

If you would want to make your code safe against invalid inputs (that may contain non-digits), you could use Character.isDigit(). Here is only the for loop which is safe against any input:

for (int i = 0, j = 0; i < sb.length(); i++) {
    char ch = sb.charAt(i);
    if (Character.isDigit(ch)) {
        if (counts[ch - '0']++ == 0)
            order[j++] = ch; // First occurrence of ch
    }
}

Upvotes: 0

Pshemo
Pshemo

Reputation: 124215

There are few problems with sb.replace(sb.charAt(x),'*');:

  1. replace replaces all characters, not just first one which is why your c can't be grater than 1.
  2. Strings are immutable so since replace can't edit original string, it returns new one with replaced characters which you can store back in sb reference.

Anyway if you would be able to use other Java resources beside java.lang.* or java.util.Scanner simple approach would be using Map which will map character with number of its occurrences. Very helpful here is merge method added in Java 8 allows us to pass key initialValue combination of old and new value

So your code can look like:

String sb = ...

Map<Character, Integer> map = new TreeMap<>();
for (char ch : sb.toCharArray()) {
    map.merge(ch, 1, Integer::sum);
}
map.forEach((k, v) -> System.out.println(k + "\t" + v));

Upvotes: 1

John E.
John E.

Reputation: 418

Simple way is this. Won't bother commenting as it is clear whats going on.

Scanner in = new Scanner(System.in);
while (true) {
    System.out.print("Input String: ");
    String line = in.nextLine();

    while (!line.isEmpty()) {
        char c = line.charAt(0);
        int length = line.length();
        line = line.replace(String.valueOf(c), "");
        System.out.println(c + " " + (length - line.length()));
    }
}

Upvotes: 3

user5613751
user5613751

Reputation:

This should be a good code to print frequency using user input:

public static void main(String args[])
    {
        System.out.println("Please enter numbers "); 
        String time = in.nextLine(); //USER INPUT
        time = time.replace(":", "");
        char digit[] = {time.charAt(0), time.charAt(1), time.charAt(2), time.charAt(3)};
        int[] count = new int[digit.length];
        Arrays.sort(digit);

        for (int i = 0; i < digit.length; i++)
        {
            count[i]++;
            if (i + 1 < digit.length)
            {
                if (digit[i] == digit[i + 1])
                {
                    count[i]++;
                    i++;
                }
            }
        }

        for (int i = 0; i < digit.length; i++)
        {
            if (count[i] > 0)
            {
                System.out.println(digit[i] + " appears " + count[i]+" time(s)");
            }
        }
    }

Upvotes: 0

Related Questions