[SOLVED] Java: Most frequent numbers in a string

Issue

I am trying to write a program that receives some command line arguments, saves them as a string and finds the most frequent number in that string (it has to ignore letters and other symbols and just check the numbers). Then it should print the string, the most frequent number and how many times it comes up in that string. If two or more numbers come up in a string the same amount of times, it should write both of them in an ascending order.

I saw some solutions for similar programs using libraries and maps, but being a complete beginner I am still quite far from covering that, so I tried to solve the problem with the following code:

import java.util.*;

public class trying5 {
    public static void main(String[] args) {

        //string of arguments

        String s = "";
        if (args.length != 0) {
            for (int i = 0; i < args.length; i++) {
                s = s + args[i] + " ";

            }
        }

        //I tried using an array

        /*char[] c = new char[s.length()];
        for (int i = 0; i < s.length(); i++) {
            c[i] = s.charAt(i);
        }*/

        //Decided to use an arraylist

        ArrayList<Character> maxTimesNum = new ArrayList<Character>();
        //char[] maxTimesNum = new char[s.length()];

        int maxTimesNumRepeats = 0; //the  repeats of the most frequent number
        int index = 0;


        for (int i = 0; i < s.length(); i++) {

            if (Character.isDigit(s.charAt(i))) {

                //variables for the possible number
                char x = s.charAt(i);
                int xRepeats = 0;

                for (int k = 0; k < s.length(); k++) {
                    if (s.charAt(k) == x) {
                        xRepeats = xRepeats + 1;
                    }
                }
                if (maxTimesNumRepeats < xRepeats) {
                    maxTimesNum.add(index, x);
                    maxTimesNumRepeats = xRepeats;

                } else if (maxTimesNumRepeats == xRepeats) {
                    if (!maxTimesNum.contains(x)){               
                    /*here I wanted it to check if we already have that number in the ArrayList so it doesn't print it multiple times*/
                            index = index + 1;
                            maxTimesNum.add(index, x);
                    }
                }
            }
        }
        if (maxTimesNumRepeats > 0) {
            System.out.print("'" + s.trim() + "'" + " -> ");
            for (int p = 0; p < maxTimesNum.size(); p++) {

                System.out.printf("%c ",maxTimesNum.get(p));

            }
            System.out.printf("(%d)\n", maxTimesNumRepeats);
        } else {
            System.out.println("The string " + "'" + s + "'" + " has no numbers.");
        }
    }
}

Unfortunately my code is not correct as it does not write the numbers in an ascending order, and I also can not seem to figure out why it works in some cases but not in the others. To describe the problem better, these are few of the inputs I tried:

Input: +386 40 253 987

Desired output: ‘+386 40 253 987’ -> 3 8 (2)

My output: ‘+386 40 253 987’ -> 3 8 (2)

Input: hdch44 fg1t525 j6s99

Desired output: ‘hdch44 fg1t525 j6s99’ -> 4 5 9 (2)

My output: ‘hdch44 fg1t525 j6s99’ -> 4 5 9 (2)

So these work. So did the inputs (Has no numbers) and (1234321). But it all goes downhill if the most frequent numbers do not occur in the string from the smallest to the largest:

Input: d8d 82 a1810y51

Desired output: ‘d8d 82 a1810y51’ -> 1 8 (3)

My output: ‘d8d 82 a1810y51’ -> 8 1 (3)

Or in this case, where I do not even understand why it wrote the number 4 as well as 2, as they do not show up the same amount of times:

Input: This(4) cat(3) and(3) friend(6), in(2) thought(7) seem(7) to(3), be(2), present(5) instead(5) they(4), roam(6) around(2) not(5) consciously(2) knowing(7), that(2) they(5) are(5) there(2) like(4), they(2) are(4), day(2) dreaming(5) together(2) today(5)!

Desired output: ‘This(4) cat(3) and(3) friend(6), in(2) thought(7) seem(7) to(3), be(2), present(5) instead(5) they(4), roam(6) around(2) not(5) consciously(2) knowing(7), that(2) they(5) are(5) there(2) like(4), they(2) are(4), day(2) dreaming(5) together(2) today(5)!’ -> 2 (9)

My output: ‘This(4) cat(3) and(3) friend(6), in(2) thought(7) seem(7) to(3), be(2), present(5) instead(5) they(4), roam(6) around(2) not(5) consciously(2) knowing(7), that(2) they(5) are(5) there(2) like(4), they(2) are(4), day(2) dreaming(5) together(2) today(5)!’ -> 2 4 (9)

I’ve updated my code so that I checked the repetitions of each number from a string and saved them to an ArrayList numRepeats. I proceed by trying to type out a result using multidimensional array. My new code:

import java.util.*;
public class trying7 {
    public static void main(String[] args) {
        //string of arguments
        String s = "";
        if (args.length != 0) {
            for (int i = 0; i < args.length; i++) {
                s = s + args[i] + " ";

            }
        }

        //preĊĦtevanje ponovitev
        ArrayList<Integer> numRepeats = new ArrayList<Integer>(); // to save repeats of each number

        //int index = 0;
        int indexInt = 0;

        //Counting and saving repetitions of numbers
        for (int i = 0; i < s.length(); i++) {

            if (Character.isDigit(s.charAt(i))) {
                char x = s.charAt(i);
                int xRepeats = 0;
                for (int k = 0; k < s.length(); k++) {
                    if (s.charAt(k) == x) {
                        xRepeats = xRepeats + 1;
                    }
                }
                numRepeats.add(indexInt, xRepeats);
                indexInt++;
            }
        }

        //2d array
        int [][] tab = new int[2][numRepeats.size()];
        //saving number of repetitions under column with index 0 and rows j
        for (int j = 0; j < numRepeats.size(); j++){
            tab [0][j] = numRepeats.get(j);
        }
        //saving numbers in a string under column with index 1
        for (int p = 0; p < s.length();p++){
            tab [1][p]= s.charAt(p);
        }

        for (int d = 0; d < tab[0].length; d++){
            int max = 0;
            for (int f= 0; f < tab.length; f++){
                //here I am attempting to print the numbers with most repetitions 
            }
        }


        }//main
    }//class

Solution

What is the problem?

From my understanding the algorithm is meant to take in a String and return the character (or characters if it is a tie) that appears the most. The issue in the code provided is how the characters are actually determined to be the most common character.
Specifically in this (slightly reformatted) code:

    int maxTimesNumRepeats = 0; //the  repeats of the most frequent number
    int index = 0;

    for (int i = 0; i < s.length(); i++) {
        if (Character.isDigit(s.charAt(i))) {
            //variables for the possible number
            char x = s.charAt(i);
            int xRepeats = 0;

            for (int k = 0; k < s.length(); k++) {
                if (s.charAt(k) == x) {
                    xRepeats++;
                }
            }
            if (maxTimesNumRepeats < xRepeats) {
                maxTimesNum.add(index, x);
                maxTimesNumRepeats = xRepeats;
            } 
            else if (maxTimesNumRepeats == xRepeats) {
                if (!maxTimesNum.contains(x)){               
                /*here I wanted it to check if we already have that number in the ArrayList so it doesn't print it multiple times*/
                    index = index + 1;
                    maxTimesNum.add(index, x);
                }
            }
        }
    }

If we think about it from the program’s perspective, the first time it runs through the outer for-loop, for (int i = 0; i < s.length(); i++), it does not know how many times the most frequent character appears. It just checks if the current character it is looking at is more than or equal to the maxTimesNumRepeats, which starts off at 0. This means the first character will always be counted (correctly or incorrectly) as a maxTimesNum, since it will appear more than 0 times! This explains why your output always includes the first digit that appears.

Now keep in mind that this problem will cause more issues than accidently counting the first digit. For example, if the current program gets given the input: "122333" it will incorrectly output the 1, the 2, and the 3. Because each number appeared more times than any number it had looked at so far.

Note: I use the terms character and number interchangeably due to the nature of this algorithm, hopefully this note clears up any confusion.

Answered By – MorganS42

Answer Checked By – Dawn Plyler (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *