Character counter in Java - java

So far this is what I tried:
public class CharacterCounter {
public static void main(String[] args){
String string = "sashimi";
int count = 0;
for(int i =0; i < string.length(); i++){
if(string.charAt(i) == 'i'){
count++;
}
}
System.out.println("The number of letter i is " + count);
}
}
Output:
The number of letter i is 2
But what I wanna do is, the program should count the most occurred characters.
For example here the string is SASHIMI, the output should be:
the number of letter S is 2
the number of letter I is 2
I'm stuck with this problem. I need your help. Thanks.

This would be the fastest way:
final int[] counts = new int[1<<16];
for (char c : <your_string>)
counts[c]++;
(i've just sketched out the part which iterates over all your chars, I believe that's the easy part, and not directly related to this question).
Benchmark results
I've pitted the HashMap approach against mine with three string lengths:
10
1,000
100,000
And these are the results:
Benchmark Mode Thr Cnt Sec Mean Mean error Units
testArray1 thrpt 1 5 5 6.870 0.083 ops/msec
testArray2 thrpt 1 5 5 6.720 0.374 ops/msec
testArray3 thrpt 1 5 5 3.770 0.019 ops/msec
testHashMap1 thrpt 1 5 5 1269.123 251.766 ops/msec
testHashMap2 thrpt 1 5 5 12.776 0.165 ops/msec
testHashMap3 thrpt 1 5 5 0.141 0.005 ops/msec
What do they mean? Yes, initializing a full 512K block of memory to zero is costly. But after that is paid, my array algorithm hardly even notices the thousands of characters whizzing by. The HashMap approach, on the other hand, is much faster for very short strings, but scales dramatically worse. I guess the crossover is at about 2k string length.
I suppose it is not disputed that such character-count statistics are usually run against massive text corpora, and not stuff like your name and surname.
Of course, the performance of the array approach can be improved substantially if you can assume that not the complete UTF-16 codepoint range will be used. For example, if you use an array that accomodates only the lowest 1024 codepoints, the performance rises to 470 ops/msec.

char[] chars = string.toCharArray();
HashMap<Character, Integer> countMap = new HashMap<Character, Integer>();
for (char aChar : chars) {
if (countMap.containsKey(aChar)) {
countMap.put(aChar, countMap.get(aChar) + 1);
} else {
countMap.put(aChar,1);
}
}
//determine max occurence
int max = 0;
for (Integer i: countMap.values()) {
if (max < i) {
max = i;
}
}
//print all satisfiying max occurrence
for (Map.Entry<Character, Integer> e: countMap.entrySet()) {
if (e.getValue() == max) {
System.out.println("The number of letter " + e.getKey() + " is " + max);
}
}

I believe that using primitives would be faster than using HashMap. This works:
public static void main(String[] args)
{
final String string = "sashimi";
final int counters[] = new int[256]; // assuming you would use only ASCII chars
for (final char c : string.toCharArray())
{
counters[c]++;
}
int maxCounter = 0;
for (final int counter : counters)
{
if (maxCounter < counter)
{
maxCounter = counter;
}
}
for (int i = 0; i < counters.length; i++)
{
if (counters[i] == maxCounter)
{
System.out.printf("%c has %d occurences.\n", i, counters[i]);
}
}
}
Output:
i has 2 occurences.
s has 2 occurences.

As mentioned in the comments, a HashMap seems ideal for this, although I won't give you the direct code, I'll give you a pseduo-code template.
for(each letter in a word)
{
if(this letter (l) exists in your hash map)
{
hashmap.put(l, hashmap.get(l) ++);
}
else
{
hashmap.put(l, 1);
}
}
This will give you a hashmap of all letters, mapped to the amount of times they appear in a word. Following your example:
S => 2
A => 1
H => 1
I => 2
M => 1

I suggest you create a TreeSet and then you can have a new class that will store the character and the number of ocurrences, then you can have that class have a compareTo that checks the occurrence and an equals that checks the char. Then whenever you insert them in the treeset they will always be in the order of whichever one appeared the most.
Please let me know if you need help with this or if you can figure it out with this information :)
EDIT: once you have filled the TreeSet with all of the letters, all you have to do is start getting them out 1 by 1 until the occcurence of the one that you took out is less than the one you took before (ie, if the top 3 letters appeared 3 times and the forth one 2, you only display the first 3).

you must take an HashMap to keep the most repeated chars with the repeat time and print it.

What you need to do is to take the literal (string). And look over each char of it and put it to proper bucket. In other words you need to group them.
You could create a bucket for each letter of alphabet. Then you could place the char in proper bucket and at the end count the items in it to have the answer.
See Marko answer, that do this.
Another option is that you sort your literal AHIIMSS, then using simple loop you will be able to write the results.
The method you pick depends the result you need to get. If you need to find how many of each letter ware using in word then sort options is more tide, if you need to pick only the maximum letters then solution with buckets is more useful.

import java.util.*;
public class CharacterCounter {
public static void main(String[] args){
String string = "sashimi";
int count = 0;
ArrayList<Character> c = new ArrayList<Character>();
for(int i =0; i <string.length(); i++)
{
count=0;
if(c.contains(string.charAt(i)))
{
continue;
}
c.add(string.charAt(i));
for(int j = 0;j<string.length();j++)
{
if(string.charAt(j) == string.charAt(i))
{
count++;
}
}
System.out.println("The number of letter "+string.charAt(i)+" is " + count);
}
}
}

String str = "sashimi";
Map<Character,Integer> countMap=new HashMap<Character,Integer>();
Set<Character> maxcSet=new HashSet<Character>();
Character maxC=null;
Integer maxCount=null;
for (int i = 0; i < str.length(); i++) {
char c=str.charAt(i);
Integer tempCount=countMap.get(c);
if(tempCount==null){
tempCount=0;
}
++tempCount;
if(i==0){
maxCount=tempCount;
maxC=c;
}else if(tempCount!=null){
if(maxCount<tempCount){
maxC=c;
maxCount=tempCount;
maxcSet.clear();
maxcSet.add(maxC);
}else if(maxCount==tempCount){
maxcSet.add(c);
}
}
countMap.put(c, tempCount);
}
System.out.println("The number of letter i is " + maxcSet);

import java.util.Scanner;
public class CountingCharecter {
public static void main(String[] args) throws Exception {
///Reading Data String from keyboard
int count=0;
System.out.println("Enter Your String:");
Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
//// Reading `Character` Data from Keyboard
System.out.println("Enter an character:");
//Here we read the character from console type cast the character because the read() return type is int
char ch =(char)System.in.read();
for(int i=0;i<s1.length();i++){
char c = s1.charAt(i);
if(c==ch){
count++;
}//if
}//for
System.out.println("The Number of character which you want to search is having: "+count+" Times");
}
}//CharecterCount
/*
input:-
Enter Your String: Manash
Enter an character: a
output:- 2
*/

public static int numberOfOccurence(String yourString, char needle) {
int nb = 0;
for (int i=0; i < yourString.length(); i++)
{
if (yourString.charAt(i) == needle)
nb++;
}
return nb;
}
You can also use Pattern and Matcher :
Pattern pattern = Pattern.compile("i");
Matcher matcher = pattern.matcher("saigigd");
int count = 0;
while (matcher.find())
count++;
System.out.println(count);

Related

Increasing numbers in string based on leading word

I have large text files and they each contain strings of words and numbers.
I need to increase those numbers by a fixed value and write them right back to where they were before within that string.
The value that I want to add depends on the word that came before the number, and every number that has none of these keywords must not be increased.
My approach would be to split at space characters, check for the words and handle the digit after, whenever I find the keyword. However, this leaves me with the requirement of having space characters between word and number and that is not ensured.
Furthermore, when reassembling the string from the split array, this might break the layout from before.
An example could be
"Mark is quite large, 189cm, and was born in the year 1978. However, he has only 1 question concerning parsing, that he really can't get his head around."
After large, the height should be increased by 5 and after year, the number subtracted by 19. The number 1 should stay untouched, as only is not a keyword.
I can work with both, java or python, as these are the languages I know.
I think i got something:
public class Start {
public static void main(String[] args){
//Test String
String s = "not4inc6desc3inc14";
StringBuffer sb = new StringBuffer(s);
//keep track where new word begins
int newWord = 0;
for(int i = 0; i < sb.length(); i++){
//chekc if the new Character is a number
if(checkNumber(sb.substring(i, i+1))){
//if the old word ends with "inc"
//maybe try out .contains()
if(sb.substring(newWord, i).endsWith("inc")){
//replace number
StringBuffer temp = new StringBuffer();
int j = 0;
//get full number
for(j = i; j < sb.length() && checkNumber(sb.substring(j, j+1)); j++){
temp.append(sb.substring(j, j+1));
}
//modify number
int number = Integer.parseInt(temp.toString()) + 1;
//replace number
sb.replace(i, i + temp.length(), Integer.toString(number));
//number no longer needs to be checked for being a word
i=j;
}
}
}
//print test String
System.out.println(sb.toString());
}
// Check if String is numeric
private static boolean checkNumber(String s){
try{
Integer.parseInt(s);
}catch(NumberFormatException e ){
return false;
}
return true;
}
}
I'm sorry it's a bit hard to understand... feel free to ask...

Rearranging numbers using variable.charAt(). Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range:

I have looked on other such answers with this error and I can't seem to figure out my code specifically. I am using Java, and I am trying to make a program where I enter a number as an input, and as an output I should get:
example input: 1234
The original number is 1234
The number in reverse is 4 3 2 1
I have this code written:
import java.util.Scanner; //Needed for Scanner class
public class CoeQuiz3
{
public static void main(String[] args)
{
//establish variables
String ogNumber;
int ogNumberInt;
Scanner keyboard = new Scanner(System.in); //establish scanner
System.out.println("Enter a positive integer greater than 0.");
ogNumber = keyboard.nextLine();
ogNumber = checknumber(ogNumber);
ogNumberInt = Integer.parseInt(ogNumber);
//print the original number
System.out.println("The original number is " + ogNumber);
//print the reverse number
int ogNumberLength = ogNumber.length();
int digitposition, ogDigit;
String reverseStatement = "The number reversed is ";
for (digitposition = ogNumberLength; digitposition >= 0;
digitposition--)
{
ogDigit = ogNumber.charAt(digitposition);
reverseStatement += ogDigit + " ";
}
System.out.println(reverseStatement);
it compiles and runs, but every time it gives me the error:
The original number is 1234
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of
range: 4
at java.lang.String.charAt(String.java:658)
at CoeQuiz3.main(CoeQuiz3.java:30)
It should work logically - what is the problem? This problem still occurs if I replace >= with >.
You are trying to access one past the highest available character index in your string. Try this loop instead:
for (int i=ogNumber.length()-1; i >=0; i--) {
char chr = ogNumber.charAt(i);
reverseStatement += chr;
}
System.out.println(reverseStatement);
But a nicer way to do this is to use the StringBuffer.reverse() method:
String ogNumberReversed = new StringBuffer(ogNumber).reverse();
for (int i=0; i < ogNumberReversed.length(); ++i) {
char chr = ogNumberReversed.charAt(i);
reverseStatement += chr;
}
System.out.println(reverseStatement);
Alternative solution:
int number = 1234;
String strReversed = new StringBuilder(String.valueOf(number)).reverse().toString().replace("", " ").trim();
System.out.println(strReversed); // 4 3 2 1
Ideone example
See this piece of code
for (digitposition = ogNumberLength; digitposition >= 0;
digitposition--)
{
ogDigit = ogNumber.charAt(digitposition);
reverseStatement += ogDigit + " ";
}
The first parameter of the loop digitposition = ogNumberLength
specifies that the loop should access the char at the position equal to length of the string, and in case of string, the length is equal to the number of characters (for e.g. length of string "HAPPY" would be 5 not 4). But the index of the last element of the String array is one less than the length of the string (as arrays are zero indexed).
So in practice if you have entered the number "1234":
length of string is = 4
position of last element array = 3
So your code is trying to access the element number 4 in an array of last index 3, hence the exception.
You should instead write the following (notice the -1 in the 1st parameter)
for (digitposition = ogNumberLength - 1; digitposition >= 0;
digitposition--)
{
ogDigit = ogNumber.charAt(digitposition);
reverseStatement += ogDigit + " ";
}
This would solve your problem, however if reversing only numbers is your sole objective then I would suggest use the following method as using strings is much more resource intensive
import java.util.Scanner;
class ReverseNumber
{
public static void main(String args[])
{
int n, reverse = 0;
System.out.println("Enter the number to reverse");
Scanner in = new Scanner(System.in);
n = in.nextInt();
while( n != 0 )
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
System.out.println("Reverse of entered number is "+reverse);
}
}
Cheers!!!
Please change your for-loop as follows:
for (digitposition = ogNumberLength-1; digitposition >= 0; digitposition--){
ogDigit = Character.getNumericValue(ogNumber.charAt(digitposition));
reverseStatement += ogDigit + " ";
}
and see the results.
There are two things which have been added:
The for loop counter should start from ogNumberLength-1 not
ogNumberLength. This was the reason for
java.lang.StringIndexOutOfBoundsException
There is a need to convert the ASCII value of char to number. That is why
Character.getNumericValue() has been used.
Hope, it helps!

Stuck on Mean word length

The goal of this code was to create a program using main method java to analysis a piece text which has been entered from a user.
They do this by entering the text into a scanner which is then analysed by the program. The analysis is to produce word frequency, for example " This is a test" produces this results:
This is a test
1 letter words: 1
2 letter words: 1
3 letter words: 0
4 letter words: 2
5 letter words: 0
The bit that I'm stuck on is producing a mean/average, My guts telling to divide
counts.length by str.length but I'm not the Best at java and I've tried to implement this but all I get are errors. I'm not expecting anyone to just hand me code, but if someone could give me a hint in what I should do or just point me the right direction it would be greatly appreciated.
Code:
import java.util.Scanner;
public class Text_AD {
public static void main (String[] args) {
while(true){
Scanner input = new Scanner(System.in);
System.out.println("Enter text: ");
String s;
s = input.nextLine();
System.out.println("" + s);
String[] strings = s.split(" ");
int[] counts = new int[6];
for(String str : strings)
if(str.length() < counts.length) counts[str.length()] += 1;
for(int i = 1; i < counts.length; i++)
System.out.println(i + " letter words: " + counts[i]);
}}}
By average, I am assuming that you mean the mean length. I am also assuming you want to get a floating point mean. In which case you just need to divide the total of all the lengths in strings by the length of the array itself.
You could do something like the following;
int total = 0;
for(String s : strings) total += s.length();
System.out.println((double)total/strings.length);
I hope this helps.
Without breaking up your code much, you could run a for loop through your counts[] array, adding up all the values, and then dividing by counts.length to get the average.
Be aware of type casting though. You may want to do Double division instead of integer.
It this what you are looking for?
import java.util.Scanner;
public class While_Loop {
public static void main (String[] args) {
int lengthSum, wordCount;
lengthSum = wordCount = 0;
while(true){
Scanner input = new Scanner(System.in);
System.out.println("Enter text: ");
String s;
s = input.nextLine();
System.out.println("" + s);
String[] strings = s.split(" ");
int[] counts = new int[6];
for(String str : strings)
if(str.length() < counts.length) counts[str.length()] += 1;
wordCount++;
lengthSum += str.length();
for(int i = 1; i < counts.length; i++)
System.out.println(i + " letter words: " + counts[i]);
System.out.println("Average: " + lengthSum/wordCount);
}}}
NOTE: I only added stuff to your code. The way it is written is pretty messy. I'd clean up some of the for loops and the brackets at the end for practice making the code more readable.
When I understand you correct you should have one variable int totalCount = 0; where you add
totalCount += i*counts[i]; in your last for loop.
After the loop you can simply divide through the size-1 (because 0 does not count)
double average = totalCount/(counts.length-1);
Alternative way
You take the inputstring length without the spaces and divide it by the number of spaces + 1 (which is equal to the number of words)
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
System.out.println("Enter text: ");
String s = "This is a sample text";
System.out.println("" + s);
String[] strings = s.split(" ");
for(String str : strings) {
Integer counter = map.get(str.length())==null?0:map.get(str.length());
map.put(str.length(),counter++);
}
Integer sum=0;
Integer counter=0;
for(Integer len : map.keySet()) {
sum+=len*map.get(len);
counter+=map.get(len);
}
Double average = Double.valueOf(sum/counter);
Or you can combine the loops
Few suggestions which might help you (not related to the specific question).
Choose a meaningful class name rather than While_Loop .
Do, Scanner input = new Scanner(System.in); before the start of the loop.
As soon as you read each line, do the following.
Split the line using "\\s+" .
Create a HashMap with Key as Count (Integer) and Value as a list of Words with that count. Create this outside the loop.
For each split word,,get the length . and check if the map already contains the count, get the list (value), add he current word to it. else, add a new entry with the word as the single entry in the list.
Get the keySet of the map, add values of all keys i.e, *count * number of elements in the list*. then divide by total number of elements.
And yes, I know this is a very big change (something you might as well ignore..). But this is the right way to go.

Java program to calculate the number of times each character appears in a string [duplicate]

This question already has answers here:
How to count frequency of characters in a string?
(27 answers)
Closed 9 years ago.
I typed out this program to count the number of times each character appears in a String.
import java.util.Scanner;
public class fre {
public static void main(String[] args) {
Scanner s=new Scanner (System.in);
System.out.println("Enter a string");
String sent = s.nextLine();
String str=sent.toUpperCase();
int len=str.length();
char save[]=new char[len];
for (int i=0;i<len;i++){
save[i]=str.charAt(i);
}
char a=0;
int count=0;
for(int i=0;i<len;i++){
a=save[i];
for(int j=0;j<len;j++){
if(save[j]==a)
count ++;
}
}
for(int i=0;i<len;i++)
System.out.println(save[i]+" appears "+count+" number of times");
}
}
The code is horribly wrong, can someone please guide me as to how to go about the program using simple functions and tell me what I've done wrong here?
You can do it simply by
Declaring an array of 26 integers (1st index refers to A, second to B and so on)
Just traverse the input string once and for each character you traverse in string, increment corresponding index, you can do it simply like int index=inputString[i]-65; and increment this index.
Now traverse your array for the counts of each character and you are done, Hope it helps
How about
int[] count = new int[256];
for(int ch; (ch = System.in.read()) >= ' ';)
count[ch]++;
for(char ch = 0; ch < count.length; ch++)
if (count[ch] > 0)
System.out.println(ch + " appears " + count[ch] + " times");
You need a separate count for each character. Right now you are incrementing the same count.
You have one global count while you need one counter for each character.
Try using a Map<Character, Integer> to store the number of occurences of each character in your string.
If i understand what you want is something like this:
int count = StringUtils.countMatches("Auto-generated method stub", "e");
System.out.println(count);
StringUtils is a api from apache http://commons.apache.org/proper/commons-lang/
You can also use Collections.frequency(Collection<?> c, Object o) method to get count of an element in a collection, So below code snippet will give you the character count in a string.
String str=s.nextLine().toUpperCase();
char[] letters=str.toCharArray();
List<Character> cList = new ArrayList<Character>();
for(char c : letters) {
cList.add(c);
}
Set<Character> chSet=new HashSet<Character>(cList); //to get unique characters in the list
for(Character ch:chSet) {
System.out.println(ch+" "+Collections.frequency(cList, ch));
}

Input sentence and print out number of words that are above min length requirement in java

My goal is to create a code that accepts a string, and the minimum number of characters allowed for each word. The output will be an int that tells the users the number of words in their sentence that was above or equal to the min they entered.
Now, my approach to this was to break the sentence up into individual word in the main method, then send each of those words into another method that will count the number of characters.
I am having difficulties in my main method, specifically splitting the sentence into individual words. I want to achieve this without using an array, only loops, substring and indexOf, etc. I commented the section of code that I am having issues with. I tested the rest of my code using a string with only one word, and my letterCounter method seems to be working fine. I know the answer is probably simple, but I am still having trouble figuring it out.
Any help would be wonderful! Thank you!
Here is my code:
public class Counter
{
public static void main(String [] args)
{
int finalcount = 0;
System.out.print("Enter your string: ");
String userSentence = IO.readString();
System.out.print("Enter the minimum word length: ");
int min = IO.readInt();
//Error checking for a min less than 1
while(min < 0)
{
IO.reportBadInput();
System.out.print("Enter the minimum word length: ");
min = IO.readInt();
}
int length = userSentence.length(); // this will get the length of the string
for(int i = 0; i < length; i ++)
{
if (userSentence.charAt(i) == ' ')
{
/* I dont know what to put here to split the words!
once I split the userSentence and store the split word into
a variable called word, i would continue with this code: */
if((letterCounter(word)) >= min)
finalcount++;
else
finalcount = finalcount;
}
}
IO.outputIntAnswer(finalcount);
}
//this method counts the number of letters in each word
public static int letterCounter (String n)
int length = n.length();
int lettercount= 0;
for(int i = 0; i < length; i ++)
{
boolean isLetter = Character.isLetter(n.charAt(i));
if (isLetter)
{
if ((n.length()) >= length)
{
lettercount++;
}
}
}
return lettercount;
}
}
Have a a look at String.split()
You could use string.split() like this to accomplish this:
String [] splittedString = inputString.split(" ");
for(int i = 0;i< splittedString.length; i++){
String currentWord = splittedString[i];
if(currentWord.length() >= min){
finalcount++;
}
}

Categories