(Java) Counting letters in a sentence? - java

The following is my code:
char[] array = new char[26] ;
int index = 0 ;
int letter = 0 ;
int countA = 0 ;
String sentence = "Once upon a time..." ;
if(sentence.contains("."))
{
String sentenceNoSpace = sentence.replace(" ", "").toLowerCase() ;
String sentenceFinal = sentenceNoSpace.substring(0, sentenceNoSpace.indexOf(".")) ;
char[] count = new char[sentenceFinal.length()] ;
for (char c = 'a'; c <= 'z'; c++)
{
array[index++] = c ;
for(int i = 0; i < sentenceFinal.length(); i++)
{
if(sentenceFinal.charAt(i) == c)
count[letter++] = c ;
//if(sentenceFinal.charAt(i) == 'a')
//countA++ ;
}
}
String result = new String(count) ; // Convert to a string.
System.out.println("\n" + result) ;
System.out.println("\nTotal number of letters is " + result.length()) ;
System.out.println(countA) ;
}
else
{
System.out.println("You forgot a period. Try again.") ;
}
I am having trouble counting how many a's, b's, c's, etc. are in a given sentence. There is one way I can do it and it is this part
//if(sentenceFinal.charAt(i) == 'a')
//countA++ ;
which I can just create all the way to z. Is there a more efficient way?
Note: No using Hashmap or any other advance techniques.

There is no need of eliminating spaces. This is just additional work you're doing.
int countOfLetters = 0 ;
String sentence = "Once upon a time..." ;
sentence = sentence.toLowerCase();
int[] countOfAlphabets = new int[26];
for (int i = 0; i < sentence.length(); i++) {
if (sentence.charAt(i) >= 'a' && sentence.charAt(i) <= 'z') {
countOfAlphabets[sentence.charAt(i) - 97]++;
countOfLetters++;
}
}
So, countOfLetters will give you the total count of letters.
If you want individual count, suppose for example, you want count of 'c',
You can get it by accessing countOfAlphabets array like countOfAlphabets['c' - 97] (97 being the ASCII value of 'a')

Use an int array letterCounts that will store the counts for each letter. Assuming the case of the letters can be ignored, the length of the letterCounts array will be 26.
Iterate over the string's characters and update the corresponding integer in the array. Use its ASCII value to find the corresponding index, as follows.
letterCounts[c - 97]++
97 is the ASCII value of 'a', whose count needs to be stored at index 0.
In this way, subtracting 97 from the character's ASCII value will give the corresponding index for that character.
Note: This is assuming that you want to store the counts for lowercase letters.

Pretty fiddly without using maps, but this will count all characters in a string.
You might want to modify to exclude things like spaces etc.
public class Main {
public static void main(String[] args) {
String sentence = "Once upon a time...";
// Create an array of size 256 ASCII_SIZE
int count[] = new int[256];
int length = sentence.length();
// Initialize count array index
for (int i = 0; i < length; i++)
count[sentence.charAt(i)]++;
// Create an array of given String size
char chars[] = new char[sentence.length()];
for (int i = 0; i < length; i++) {
chars[i] = sentence.charAt(i);
int find = 0;
for (int j = 0; j <= i; j++) {
// If any matches found
if (sentence.charAt(i) == chars[j])
find++;
}
if (find == 1) {
System.out.println("Occurrence of " + sentence.charAt(i) + " is:" + count[sentence.charAt(i)]);
}
}
}
}
Which outputs:
Occurrence of O is:1
Occurrence of n is:2
Occurrence of c is:1
Occurrence of e is:2
Occurrence of is:3
Occurrence of u is:1
Occurrence of p is:1
Occurrence of o is:1
Occurrence of a is:1
Occurrence of t is:1
Occurrence of i is:1
Occurrence of m is:1
Occurrence of . is:3

Check Below code You can have a 26 length array and index will increment according to the presence of the alphabet.
public void getResult(){
int [] charCount = new int [26];
int countA = 0 ;
String sentence = "Once upon a time..." ;
if(sentence.contains("."))
{
String sentenceNoSpace = sentence.replace(" ", "").toLowerCase() ;
String sentenceFinal = sentenceNoSpace.substring(0, sentenceNoSpace.indexOf(".")) ;
char[] sentenceCharArray = sentenceFinal.toCharArray();
//char a = 97;
for (int i = 0; i <sentenceCharArray.length ; i++) {
int index = sentenceCharArray[i] - 97 ;
if(index >= 0 && index <= 26) {
charCount[index] += 1;
}
}
System.out.print("Result : ");
for (int i = 0; i < charCount.length ; i++) {
System.out.print(charCount [i]+" , ");
}
System.out.println("\nTotal number of letters is " + sentenceCharArray.length) ;
}
else
{
System.out.println("You forgot a period. Try again.") ;
}
}

Since there are 26 letters in the US alphabet, you can use an int[] with a size of 26
int[] letterCount = new int[26];
to hold the count of each letter where index 0 represents 'a', 1 represents 'b', etc...
As you traverse through the sentence, check if the character you're on is a letter, Character.isLetter(), then increment the element in the array that represents the letter.
letterCount[letter - 'a']++;
We subtract 'a' from the letter to give us the correct index.
Code Sample
package stackoverflow;
public class Question {
public static void main(String[] args) {
String sentence = "The quick brown fox jumps over the lazy dog.";
int[] letterCount = new int[26];
if (sentence.contains(".")) {
// toLowerCase() the sentence since we count upper and lowercase as the same
for (char letter : sentence.toLowerCase().toCharArray()) {
if (Character.isLetter(letter)) {
letterCount[letter - 'a']++;
}
}
// Display the count of each letter that was found
int sumOfLetters = 0;
for (int i = 0; i < letterCount.length; i++) {
int count = letterCount[i];
if (count > 0) {
System.out.println((char)(i + 'a') + " occurs " + count + " times");
sumOfLetters += count;
}
}
System.out.println("Total number of letters is " + sumOfLetters);
} else {
System.out.println("You forgot a period. Try again.");
}
}
}
Result
a occurs 1 times
b occurs 1 times
c occurs 1 times
d occurs 1 times
e occurs 3 times
f occurs 1 times
g occurs 1 times
h occurs 2 times
i occurs 1 times
j occurs 1 times
k occurs 1 times
l occurs 1 times
m occurs 1 times
n occurs 1 times
o occurs 4 times
p occurs 1 times
q occurs 1 times
r occurs 2 times
s occurs 1 times
t occurs 2 times
u occurs 2 times
v occurs 1 times
w occurs 1 times
x occurs 1 times
y occurs 1 times
z occurs 1 times
Total number of letters is 35
Rebuttal Question
What is wrong with using Java 8 and using the chars() of a String? With it, you can accomplish the same thing with less code. For the total number of letters, we just use String.replaceAll() and remove all non-letters from the String with the pattern [^A-Za-z]and use the length() of the result.
package stackoverflow;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Question {
public static void main(String[] args) {
String sentence = "The quick brown fox jumps over the lazy dog.";
System.out.println(sentence.toLowerCase().chars()
// Change the IntStream to a stream of Characters
.mapToObj(c -> (char)c)
// Filter out non lower case letters
.filter(c -> 'a' <= c && c <= 'z')
// Collect up the letters and count them
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())));
System.out.println("Total letter count is " + sentence.replaceAll("[^A-Za-z]", "").length());
}
}
Result
{a=1, b=1, c=1, d=1, e=3, f=1, g=1, h=2, i=1, j=1, k=1, l=1, m=1, n=1, o=4, p=1, q=1, r=2, s=1, t=2, u=2, v=1, w=1, x=1, y=1, z=1}
Total letter count is 35

You can solve it with Regex If Regex wont be considered as High-tech 🙂
Idea is simple: Remove all letters and subtract output from original string length to get counter
String sentence = "Once upon a time...";
String noLetterString = sentence.replaceAll("[a-zA-Z]", "");
int counterLetter = sentence.length() - noLetterString.length();
System.out.println("counter:" + counterLetter);
By old school programming 🙂
Idea here is in reverse, appending only letters
String sentence = "Once upon a time...";
String lowerCase = sentence.toLowerCase(); // to avoid comparison to UpperCase letters
StringBuilder counterStr = new StringBuilder();
for (char l : lowerCase.toCharArray()) {
if (l >= 'a' && l <= 'z') {
counterStr.append(l);
}
}
System.out.println("counterStr:" + counterStr);
System.out.println("counter:" + counterStr.length());

Here is the Update Code :
int[] array = new int[26] ;
String sentence = "Once upon a time..." ;
if(sentence.contains("."))
{
String sentenceNoSpace = sentence.replace(" ", "").toLowerCase() ;
String sentenceFinal = sentenceNoSpace.substring(0, sentenceNoSpace.indexOf(".")) ;
for (char c : sentenceFinal.toCharArray())
{
System.out.println(c+" "+(c-97));
array[c-97] += 1;
}
// System.out.println("\n" + Arrays.toString(array)) ;
for(int i=0; i< array.length;i++) {
if(array[i] != 0) {
char c = (char)(i+97);
System.out.println(c+" occured "+ array[i]+" times");
}
}
}
else
{
System.out.println("You forgot a period. Try again.") ;
}

Related

How to get the maximum occurring character and its occurrences from a user inputted String sentence?

I have a program that asks the user for a String sentence and output its maximum occuring character and its occurences.
My issue here is that the function that counts the max character and its occurrences only counts that maximum character and its occurrences only for a single word(that is all lowercase) and not a full sentence or a word that starts with an uppercase.
If the user inputs a sentence, the program keeps having an index out of bounds in the freqLetter array (frequent letter array) in which I have no idea why it undergoes an out of bounds, does it have something to do with the whitespaces of the sentence? Should I create another loop in iterating the array or should I make another array?? (I am sometimes confused in manipulating indexes of arrays).
Code:
static void maxOccuringChar(char str[]) { // function that counts that max character and its occurences
char maxChar = ' ';
int freqLetter[] = new int[26];
int lengthString = str.length;
int maximum = -1;
for (int i = 0; i < lengthString; i++)
freqLetter[str[i] - 'a']++; // I'm not sure why it becomes out of bounds for some reason
for (int i = 0; i < 26; i++)
if (maximum < freqLetter[i]) {
maximum = freqLetter[i];
maxChar = (char)(i + 'a');
}
System.out.print(maxChar + " = " + maximum); // returns result
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
char[] StringInput = in.nextLine().toCharArray(); // user inputs the given String sentence and puts into character array
maxOccuringChar(StringInput); // calls function and returns the maximum character and and its occurences
}
Output 1:
Elephant
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -28 out of bounds
for length 26
Output 2:
I am confused
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -24 out of bounds
for length 26
Output 3: // works fine here
hello
l = 2
Process finished with exit code 0
Your response would be highly appreciated and would indeed help me on this one!
Thank you very much everyone!!!
The problem occurs because the space code is 32. Change your loop to skip spaces
for (int i = 0; i < lengthString; i++) {
if(str[i] == ' ') {
continue;
}
freqLetter[str[i] - 'a']++;
}
ASCII Table
Also you can solve this using streams
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String input = in.nextLine();
System.out.println(input.chars()
.mapToObj(x -> (char) x)
.collect(Collectors.groupingBy(x -> x, Collectors.counting()))
.entrySet()
.stream()
.max(Comparator.comparingLong(Map.Entry::getValue))
.get());
}
Output:
123333
3=4
But it would count spaces as well. If you don't want to, then add this line after mapToObj(...)
.filter(c -> c != ' ')

Need a help figuring out some nested iteration things in Java

I'm pretty new to programming and just started not to long ago doing some CS, currently my assignment is to is to write a program that prints each letter of the alphabet and the number of times that letter occurs in the phrase. It needs to include:
-Loop to iterate through the alphabet (the outer loop)
-Loop to iterate through all the letters of a phrase (the inner loop)
-Counter variable to count the number of times a letter is in the phrase
-Print statement to display the frequencies
I'm a little behind on this and having a hard time finding time to put into doing this assignment and just need some guidance on how to complete this simply, without complex things like Arrays and stuff.
As I said I haven't had much time to work on this, but here is the general layout/my plan of what I think it should look like:
public class LetterFrequencies
{
public static void main(String[] args)
{
int counter = 0;
String letters = "abcdefghijklmnopqrstuvwxyz";
String phrase = "This is a phrase";
System.out.println("The following shows the letter frequencies for the phrase");
//for (int i = _; i < _; i++) ??
{
//Print out statement like :System.out.println(letters.substing());
}
//possible while loop or for loop?
}
}
Feel free to correct me and anyway necessary since I need all the knowledge I can get to improve in the near future, thanks!
Try this solution without using Arrays or List, maybe it will help you:
public static void main(String[] args) {
int counter = 0;
String letters = "abcdefghijklmnopqrstuvwxyz";
String phrase = "This is a phrase".toLowerCase();
for (int i = 0; i < letters.length(); i++) {
int count = 0;
char a = letters.charAt(i);
for (int j = 0; j < phrase.length(); j++) {
if (a == phrase.charAt(j)) {
count++;
}
}
System.out.println("The letter " + letters.charAt(i) + " " + count);
}
}
For each letter you will have how much time it's used in you phrase.
Result :
The letter a 2
The letter b 0
The letter c 0
The letter d 0
The letter e 1
The letter f 0
The letter g 0
The letter h 2
The letter i 2
The letter j 0
The letter k 0
The letter l 0
The letter m 0
The letter n 0
The letter o 0
The letter p 1
The letter q 0
The letter r 1
The letter s 3
The letter t 1
The letter u 0
The letter v 0
The letter w 0
The letter x 0
The letter y 0
The letter z 0
This is one way:
String lettersString = "abcdefghijqlmnñopqrstuvwxyz";
char[] letters = lettersString.toCharArray();
int[] counts = new int[letters.length];
Arrays.fill(counts, 0);
String textBoxValue = "This is the message";
for (int i = 0; i < textBoxValue.length(); i++) {
char currentLetter = textBoxValue.charAt(i);
for (int j = 0; j < letters.length; j++) {
char letter = letters[j];
if (currentLetter == letter ||
currentLetter == Character.toUpperCase(letter)){
counts[j]++;
}
}
}
for (int i = 0; i < letters.length; i++) {
//Print it your own way
String message = letters[i] + " : " + counts[i];
Log.d(TAG, message);
System.out.println(message);
}
Probably this would help, just try to do a frequency Map.
public static Map<Character, Integer> frequencies(String yourPrhase){
Map<Character, Integer> frequency = new HashMap<>();
for(final char c : str.toCharArray()){
frequency.compute(c, (k, v) -> v == null ? 1: v++);
}
return frequency;
}
Then you can just do what you need with the frequency Map, probably print it out.
Also can try this one a little bit more functional.
public static Map<String, Long> frequencies2(String yourPrhase){
return str.chars()
.mapToObj(c -> String.valueOf((char) c))
.collect(Collectors.groupingBy(String::valueOf, Collectors.counting()));
}

Why does Java give runtime error when depositing data into an array using a "for" loop?

I wanted to write code that reads a word stored as a String variable. The program should loop through each character in the word and update an array that contains the frequency with which each letter occurs.
The letters in the alphabet (A to Z) can be referenced by "freq[1]" to "freq[26]".
However, when I try to run my program, I get an error that says:
java.lang.ArrayIndexOutOfBoundsException: -64
at ReadWords.main(ReadWords.java:17)
Here is the code I used:
public class ReadWords
{
public static void main (String[] args)
{
String line = "This is a line of text. That's not exciting";
line = line.toLowerCase();
int[] freq = new int[27];
for (int i = 0; i < line.length(); i++)
{
int letter = line.charAt(i) - 96;
freq[letter]++;
}
for (int i = 0; i < freq.length - 1; i++)
{
System.out.println(freq[i]); //prints all elements in the array
}
}
}
Because you are reading space characters (ASCII 32) with your letters. Its value is 32, and when you subtract 96, you get -64, obviously not a valid array index.
I don't think you want to count spaces, so skip them; don't process them.
You'll want to skip other punctuation characters as well, with ' being ASCII value 39, and . being ASCII value 46.
Your error
Like rgettman said, you're including the spaces in your analysis of the frequence. Simply add an if-statement.
for (int i = 0; i < line.length(); i++)
{
int letter = line.charAt(i) - 96;
if (letter > 0 && letter < 27) freq[letter]++;
}
if (letter > 0 && letter < 27) makes sure that the char that you're at in your String is in fact a letter from a - z
Helpful points
Also, in your second for-loop, it won't display the frequency of 'z', and it will display the frequency as position 0 in the array, which holds nothing (position 1 is 'a').
You need to change this:
for (int i = 0; i < freq.length - 1; i++)
to this:
for (int i = 1; i < freq.length; i++)
This way it includes element 27, which is freq[26], which is where the 'z' frequency is. It also will ignore element 1, which is freq[0]. Try it. Or you could change the size of your freq array to 26, and subtract 97 from the line.charAt(i) and then change the if-statement I gave you in your first for-loop to
if (letter > -1 && letter < 26). And then use for (int i = 0; i < freq.length; i++).
Display the letter with the frequency
Use this line of code to display the char corresponding to the frequency as well:
System.out.println((char)(i + 96) + ": " + freq[i]);
Or if you did what I said where you changed the size of the freq array and made the frequency of 'a' at position 0, use this line:
System.out.println((char)(i + 97) + ": " + freq[i]);
I guess the easiest way to do this would be to only check for lower case alphabets (97-122 ASCII values).
Below is the modified version of your code.
public static void main(String[] args) {
String line = "This is a line of text. That's not exciting";
line = line.toLowerCase();
int[] freq = new int[27];
for (int i = 0; i < line.length(); i++) {
/*Only use lower case alphabets ranging from 97 to 122.
The below if should omit all other unwanted characters from your string.*/
if (line.charAt(i) > 96
&& line.charAt(i) < 123) {
/* Subtract by 97 to start your array from 0 for a(value 97)*/
int letter = line.charAt(i) - 97;
freq[letter]++;
}
}
for (int i = 0; i < freq.length - 1; i++) {
System.out.println((char)(i+97) + " : " + freq[i]); // prints all elements in the array
}
}

Letter frequency array, converting int to char

My code below prints out a letter frequency table (number of letter occurances in a string) that is inputted from a scanner class. I Have everything working correctly except the last bit. When executed, the table displays letters a-z and the number of occurrences except for the last method LargestLength() method. Since my array 'score' uses int[26], instead of using a-z it uses ints 0-25. (0=A, 1=B, etc.) As of now my LargestLength method only displays the number (instead of the letter) which comes up the most but does not count the number of occurrences.
For example, If my string were to be "Hello", l shows up most frequently so i would like it to display, "Most Frequent: l 2" but with my code it displays "Most Frequent: 11" (11 = L). How would I go about fixing this?
Profile Class.
public class LetterProfile {
int score[] = new int [26];
public void countChars (String s) {
s = s.toLowerCase();
char a = 'a';
for (int i = 0; i < s.length(); i++) {
int next = (int)s.charAt(i) - (int) a;
if ( next< 26 && next >= 0)
score[next]++;
}
}
public int largestLength() {
int largest = 0;
int largestindex = 0;
for(int a = 0; a<26; a++) {
if(score[a] > largest) {
largest = score[a];
largestindex = a ;
}
}
return (char) largestindex;
}
public void printResults() {
largestLength();
for (int i = 0; i < score.length; i++) {
System.out.println( (char)(i+97) + ": " + score[i]);
}
System.out.println(("Most Frequent") + (": ") + largestLength());
}
}
A bit of a confusing explanation but any help would be appreciated.
If my string were to be "Hello", l shows up most frequently so i would like it to display, "Most Frequent: l 2" but with my code it displays "Most Frequent: 11" (11 = L). How would I go about fixing this?
Simple: String.valueOf((char)(number + 'A'));

String index out of range in Java

I'm trying to make this program to count the number of consecutive characters
and I'm getting the error that says:
"String index out of range."
import javax.swing.*;
public class Project0 {
public static void main(String[] args){
String sentence;
sentence = JOptionPane.showInputDialog(null, "Enter a sentence:"); /*Asks the user to
enter a sentence*/
int pairs = 0;
for (int i = 0; i < sentence.length(); i++){ //counts the pairs of consecutive characters
if ( sentence.charAt(i) == sentence.charAt(i+1)) pairs++;
}
JOptionPane.showMessageDialog(null, "There were " + pairs + " pairs of consecutive characters");
}//main
}// Project0
The last element in your loop is 100% guaranteed to cause a problem. Perhaps only go to the length - 1 in your loop?
Consider the code:
for (int i = 0; i < sentence.length(); i++){
if ( sentence.charAt(i) == sentence.charAt(i+1)) pairs++;
}
String s = "AABBCC";
first loop, i = 0 : compare s[0] to s[1]
first loop, i = 1 : compare s[1] to s[2]
first loop, i = 2 : compare s[2] to s[3]
first loop, i = 3 : compare s[3] to s[4]
first loop, i = 4 : compare s[4] to s[5]
first loop, i = 5 : compare s[5] to s[6] // WOAH, you can't do that! there is no s[6]!!
sentence.charAt(i+1) will cause this as i + 1 > sentence.length() at the last step of the for-loop
You need to change the upper limit of your for loop to not go all the way to the end because the way you look for consecutive characters is "look at the ith character, and then look at the next
one". Once you get to the end, there is no "next one", so just stop at the next to last one.
for (int i = 0; i < sentence.length()-1; i++)

Categories