Digit Frequency In A String - java

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.

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()));
}
}

There are few problems with sb.replace(sb.charAt(x),'*');:
replace replaces all characters, not just first one which is why your c can't be grater than 1.
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));

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
}
}

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)");
}
}
}

Related

Reducing and printing a string Array

I am trying to reduce the string array by using a for a loop. This is an example I tried to do
User string input: Calculus
User input:5
output: CalcuCalcCalCaC
I have turned the string to a char array but the issue presents itself when trying to print them out multiple times. It only prints once and has the right starting output.
input string: Oregon
input number: 4
output: Oreg
I notice my for loop says that it is not looping when I hover over it on the IDE that I downloaded from JetBrains.
I tried different combinations of decrementing and incrementing but could not get that "for statement is not looping". Other than that I have tried different ways to do something in the for loop but I don't think anything needs to be done for now if the for loop is not looping then, right?
So my question is, how to reduce a string or char array and print the decrement value over and over again?
Here is my code so far for it.
public String wordDown(String userString, int userNum)
{
String stringModded = userString.substring(0, userNum);
char[] charArray = stringModded.toCharArray();
char repeat = ' ';
for(int i = 0; i<userNum; ++i)
{
repeat = (char) (repeat +charArray[i]);
charArray[i] = repeat;
for(int j = 1; i > charArray.length; ++j)
{
String modWord = String.valueOf(charArray[i + 1]);
return modWord;
}
}
return null;
}
public static void main(String[] args)
{
int userNumber;
String userString;
RandomArrayFunctionalities ranMethod = new RandomArrayFunctionalities();
Scanner in = new Scanner(System.in);
System.out.println("\nEnter a word:");
userString = in.next();
System.out.println("\nEnter a number within the word scope that you just enter:");
userNumber = in.nextInt();
System.out.println(ranMethod.wordDown(userString, userNumber));
}
You do not need to modify the original array. Use a StringBuilder to concatenate the successive parts of the word. Use the String.substring(int,int) method to pull out those parts. The example that follows uses a decrementing index to generate the successively smaller substrings.
public String wordDown(String word, int userNum) {
StringBuilder sb = new StringBuilder();
for (int length = userNum ; length > 0 ; --length) {
sb.append(word.substring(0, length));
}
return sb.toString();
}
I think you are over complicating things, you don't need a char array at all and you only need a single loop, and a single return statement:
public String wordDown(String userString, int userNum) {
String finalString = "";
for (int i = 0; i < userNum; ++i) {
finalString = finalString + userString.substring(0, userNum - i);
}
return finalString;
}
Simply loop up to the inputted number and substring from 0 to inputtedNumber - loopCounter and append the result to the previously held String value.
Example Run:
Enter a word:
Calculus
Enter a number within the word scope that you just enter:
5
CalcuCalcCalCaC
Sidenote:
Technically you would want to use StringBuilder instead of appending String in a loop, but that is probably out of the scope of this question. Here is that version just for reference:
public String wordDown(String userString, int userNum) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < userNum; ++i) {
sb.append(userString.substring(0, userNum - i));
}
return sb.toString();
}

How to reverse the word after getting a Capital letter at the end of the word in JAVA?

Suppose you have a String and a CAPITAL letter in that indicates ending of a word. For example, if you have wElovEcakE where E, E and K indicates end of the words wE, lovE and cakE respectively. You need to reverse each word (as you know where it ends). Don’t reverse the String as a whole. To illustrate, if we give wElovEcakE as input output should be EwEvolEkac. See wE became Ew, lovE became Evol and so on....
And the way i tried to approach with ..
import java.util.Scanner;
public class Alternative {
public static void main(String[]args) {
Scanner robo=new Scanner (System.in);
System.out.println("Enter a word ");
String word=robo.nextLine();
char[] array=word.toCharArray();
for(int i =0;i<array.length;i++){
int count =0;
for(int j=0;j<=("EMPTY");j++) // here i am trying to operate a loop where it will work up to the Capital letter.
count ++;
}
//Code incomplete
}
}
}
Above i have mentioned "EMPTY" in the condition part ... i want to operate a loop where my loop will work up to the capital letter , then i will count all the letter that i have counted up to capital letter then last step will be like i will make another loop where i will reverse all the letter where condition for the loop will <=count ;Example:lovE (counted 4 letters i will reverse four times back).
Can you guys help me to write the condition at "EMPTY" part if you think that my approach is correct ..
Can you guys help me to solve the problem in any other way ?
test if this works for you:
Scanner robo = new Scanner (System.in);
System.out.println("Enter a word ");
String word = robo.nextLine();
String textInvert = "";
int indexAnt = 0;
for (int i = 0; i < word.length(); i++) {
if (Character.isUpperCase(word.charAt(i))) {
String wordSplit = word.substring(indexAnt, i + 1);
for (int j = wordSplit.length() - 1; j >= 0; j--)
textInvert += wordSplit.charAt(j);
indexAnt = i + 1;
}
}
System.out.println(textInvert);
Here is my solution with Regex pattern
String[] in = "wElovEcakE".replaceAll("([A-z]+?[A-Z])","$1,").replaceAll(",$","").split(",");
String out = "";
for(String current: in){
StringBuilder temp = new StringBuilder();
temp.append(current);
out+=temp.reverse();
}
System.out.println(out);
Result:
EwEvolEkac
Here is a solution that makes use of the StringBuilder class to hold and reverse each found word.
Scanner robo = new Scanner (System.in);
System.out.println("Enter a word:");
String word = robo.nextLine();
robo.close();
String upperCase = word.toUpperCase(); //used to find uppercase letters
StringBuilder builder = new StringBuilder();
for (int i = 0; i < word.length(); i++) {
char nextChar = word.charAt(i);
builder.append(nextChar);
if (nextChar == upperCase.charAt(i)) {
String subWord = builder.reverse().toString();
System.out.print(subWord); //It's not clear what to do with the found words
builder = new StringBuilder();
}
}
System.out.println();
Example
Enter a word:
makEmorEpiE
EkamEromEip
You can try this solution:
String textInvert = "wElovEcakE";
String revertText = textInvert
.chars().mapToObj(c -> (char) c)
.reduce(new LinkedList<>(Arrays.asList(new StringBuilder())), (a, v) -> {
a.getLast().append(v);
if (Character.isUpperCase(v)) {
a.add(new StringBuilder());
}
return a;
}, (a1, a2) -> a1)
.stream()
.map(s -> s.reverse())
.reduce(StringBuilder::append)
.map(StringBuilder::toString)
.get();
System.out.println(revertText);
public class Alternative {
public static void main(String[] args) {
Scanner robo = new Scanner(System.in);
System.out.println("Enter a word ");
String word = robo.nextLine();
char[] array = word.toCharArray();
int count = -1;
for (int i = 0; i < array.length; i++) {
if (Character.isUpperCase(array[i])) { //find the upper case letters in the word
for (int j = i; j > count; j--) //loop through the letters until the last count variable value is encountered
System.out.print(array[j]); //print the reversed values
count = i; //assign the last encountered uppercase letter's index value to count variable
}
}
}
}

How to loop string in decrement order?

Write a program that takes a string input from the user and then outputs the first character, then the first two, then the first three, etc until it prints the entire word. After going down to one letter, print the opposite back up to the full word.
I've gotten the first part done.
Scanner word = new Scanner(System.in);
System.out.println("Enter a word.");
String thing = word.next();
String rest = "";
for(int i=0;i< thing.length();i++){
String w = thing.substring(i,i+1);
rest += w;
System.out.println(rest);
}
This is what it should look like.
C
Co
Com
Comp
Compu
Comput
Compute
Computer
Computer
Compute
Comput
Compu
Comp
Com
Co
C
Strings in Java are indexed starting from 0, so the last character is indexed at length-1.
To iterate from the last character down to the first, the for loop would be for(int i = thing.length () - 1; i >= 0; i--).
Alternatively, recursion would be a simpler solution considering you already obtained the strings that should be printed in reverse.
static void f (String str, int n) {
if (n > str.length ()) return;
String temp = str.substring (0, n); // obtain the string
System.out.println (temp); // print
f (str, n + 1); // go to next substring
System.out.println (temp); // print after returning from the last obtainable substring
}
The function can now be called via f(thing, n);
You can try to implement two arrays, in the first you must split the String entered from the Scanner and in the second you must store the generated aux variable in each iteration of the first array, To finish you must iterate the second array in reverse.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a word: ");
String word = sc.next();
String[] array = word.split("");
int length = array.length;
String[] auxArray = new String[length];
String aux = "";
for (int i = 0; i < length; i++) {
aux += array[i];
auxArray[i] = aux;
System.out.println(aux);
}
for (int i = length - 1; i >= 0; i--) {
System.out.println(auxArray[i]);
}
}

How to find all consecutive letters with count from string provided by user?

I am trying to write a code in Java which will find all the consecutive letters in string provided by user and also provide its count.
For example:
User has provided string: "aaastt rr".
I am expecting the result as below:
a - 3
t - 2
r - 2
I have written below code as per my understanding but not getting the result as expected.
import java.util.Scanner;
public class ConsecutiveCharacters {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter string: ");
char s[] = sc.nextLine().toCharArray();
int count = 1;
for(int i =0;i<s.length-1;i++){
if(s[i]==s[i+1]){
count++;
System.out.println(s[i] + "-" + count);
}
}
}
}
I am getting result:
a-2
a-3
t-4
r-5
which is not I am expecting.
Please have a look, and let me know where I am missing.
Many Thanks in advance.
You are never resetting your counter when you run into a new character within the array.
Use the starting character and increment as you go and change the character whenever a new one is found and only print the previous char and count if the count is greater than 1. Note the edge case where the last of the characters are consecutive.
Scanner sc = new Scanner(System.in);
System.out.println("Enter string: ");
char s[] = sc.nextLine().toCharArray();
HashMap<Character, Integer> charsFound = new HashMap<>();
int count = 1;
char c = s[0];
for(int i = 1;i < s.length; i++)
{
//check the edge case where the last of the array is consecutive chars
if(c==s[i] && count >= 1 && s.length - 1 == i)
{
if(!charsFound.containsKey(c))
charsFound.put(c, ++count);
else if(charsFound.get(c) < ++count)
charsFound.put(c, count);
}
//increment the count if the character is the same one
else if(c==s[i])
{
count++;
}
//consecutive chain is broken, reset the count and our current character
else
{
if(count > 1)
{
if(!charsFound.containsKey(c))
charsFound.put(c, count);
else if(charsFound.get(c) < count)
charsFound.put(c, count);
}
//reset your variables for a new character
c = s[i];
count = 1;
}
}
for (char knownCharacters : charsFound.keySet())
if (charsFound.get(knownCharacters) > 1)
System.out.println(knownCharacters + "-" + charsFound.get(knownCharacters));
Output
Enter string:
aabbbt s.r r rr
a-2
b-3
r-2
Enter string:
aaastt rr
a-3
t-2
r-2
Enter string:
aayy t t t.t ty ll fffff
a-2
y-2
l-2
f-5
Enter string:
aa b aa c aaaaa
a-5

Split Numbers within parenthesis in Java

I would like to split this input: 12132002(177) 012(207.5) 014(184) into two arrays, like this:
num[500] = 12132002,012,014, etc.
and
mark[500] = 177,207.5,184, etc.
The Fact is that I'm accepting values from user like this, where i don't know the total number which he/she will input.
How can I code in Java that kind of splitting? Is it like this?
int number[500];
for(int i=0;i<500;i++) {
number=num.split("//(");
}
To code "that kind of splitting", you will have to:
Declare your variables: String[] number, String[] mark, String num, and String[] numSplit.
Split num by " " (spaces). Assign this to numSplit.
Loop through numSplit from 0 to numSplit.length with i.
Set number[i] to numSplit[i] from the beginning to the first occurrence of a "(".
Set mark[i] to numSplit[i] from one character after the first occurrence of "(" to one character before the end.
Output number and mark
The full code:
String[] number = new String[500]; //1
String[] mark = new String[500];
String num = "12132002(177) 012(207.5) 014(184)";
String[] numSplit = num.split(" "); //2
for(int i = 0; i < numSplit.length; i++) { //3
number[i] = numSplit[i].substring(0, numSplit[i].indexOf("(")); //4
mark[i] = numSplit[i].substring(numSplit[i].indexOf("(") + 1, numSplit[i].length() - 1); //5
}
for(int i = 0; i < number.length; i++) System.out.println(number[i]); //6
for(int i = 0; i < mark.length; i++) System.out.println(mark[i]);
Which outputs:
12132002
012
014
null (x497)
177
207.5
184
null (x497)
Notice that number, mark, and numSplit are String arrays because the leading zeros would be cut off in not otherwise. If you don't mind the leading zeros being cut off then you can change num to an int array and mark to a double array (Because of the decimal in 207.5).
Ok buddy, this could be a solution for your problem. I chose to use the methods I have already created for some other project, but I think those can fit for this purpose as well, instead of using some complex REGEX expression. The output is good, though you have to figure out the way you want to store num and mark variables (I suggest arrays). Hope I helped.
public class Example {
public static void main(String[] args) {
String s = "12132002(177)012(207.5)014(184)";
// output 12132002,012,014 && 177,207.5,184
// it works good with this string as well -> s = "12132002(177)012(207.5)014(184)111(024)";
int numOfParanthesis = numOfParanthesis(s, '(');
String num = "";
String mark = "";
// array which contains positions of (
int[] indexesOpening = indexes(s, '(');
// array which contains positions of )
int[] indexesClosing = indexes(s, ')');
// logic
for(int i = 0; i < numOfParanthesis; i++){
if(i == 0){
num = s.substring(i, indexesOpening[i])+",";
mark = s.substring(indexesOpening[i]+1,indexesClosing[i])+",";
}else if(i!=numOfParanthesis-1){
num += s.substring(indexesClosing[i-1]+1, indexesOpening[i])+",";
mark += s.substring(indexesOpening[i]+1, indexesClosing[i])+",";
}else{
num += s.substring(indexesClosing[i-1]+1, indexesOpening[i]);
mark += s.substring(indexesOpening[i]+1, indexesClosing[i]);
}
}
System.out.println(num);
System.out.println(mark);
}
// returns array of positions for the given character
public static int[] indexes(String s, char c){
int numOfParanthesis = numOfParanthesis(s, c);
int[] indexes = new int[numOfParanthesis];
int delimetar = s.indexOf(c);
for(int i = 0; i < numOfParanthesis; i++){
if(i != -1){
indexes[i] = delimetar;
}
delimetar = s.indexOf(c, delimetar+1);
}
return indexes;
}
// returns how many times a character repeats in a string
public static int numOfParanthesis(String s, char c){
int number = s.indexOf(c);
int i = 0;
while (number >= 0){
number = s.indexOf(c, number+1);
i++;
}
return i;
}
}
Try this:
public class Test {
public static void main(String[] args) {
// Guess this is a string since it is a mix of integers
// and non-integers, characters like '(', ')' and space.
String str = "12132002(177) 012(207.5) 014(184)";
System.out.println("Your string:");
System.out.println("str=\"" + str + "\"");
System.out.println();
// remove all ')' since they will not be used
// using space as a delimiter is enough
String str2 = str.replaceAll("\\)", "");
System.out.println("Your string after removing ')' character:");
System.out.println("str2=\"" + str2 + "\"");
System.out.println();
// Since your input has spaces, we split on spaces
String[] strings = str2.split("\\s+");
System.out.println("Result after splitting str2 by spaces:");
for (String s : strings) {
System.out.println(s);
}
System.out.println();
// Lets make two array
String[] num = new String[500];
String[] mark= new String[500];
// loop strings
int cnt = 0;
for (String s : strings) {
String[] a = s.split("\\("); // a[0]="012", a[1]="207.5"
num[cnt] = a[0];
mark[cnt] = a[1];
cnt++;
}
System.out.println("Result num: ");
System.out.print("num[500] = ");
for(String s : num) {
if(s==null) {break;}
System.out.print(s + ",");
}
System.out.println(" etc.\n");
System.out.println("Result mark: ");
System.out.print("mark[500] = ");
for(String s : mark) {
if(s==null) {break;}
System.out.print(s + ",");
}
System.out.println(" etc.\n");
}
}
Output:
Your string:
str="12132002(177) 012(207.5) 014(184)"
Your string after removing ')' character:
str2="12132002(177 012(207.5 014(184"
Result after splitting str2 by spaces:
12132002(177
012(207.5
014(184
Result num:
num[500] = 12132002,012,014, etc.
Result mark:
mark[500] = 177,207.5,184, etc.

Categories