JAVA - store letters and number of letters in string - java

I am supposed to ask the user to enter a string and I am supposed to parse the string and keep track of the number of the alphabet. So like if the user enter the string "abee"
it displays the output as :
a: 1
b: 1
c: 0
e: 2
So far I have been able to get the string and parse it and store the elements into an array. And I have been able to print out each letter at a time with a for loop. Now the problem I am facing is that when it prints out the letters along with how many of the letters exist in the phrase the numbers don't match up. For example if I enter the letters : "abccddee"
it prints out:
a: 1
b: 1
c: 1
c: 0
d: 0
d: 0
e: 0
e: 0
For testing purposes I am using my own string rather than using the scanner.
import java.util.Scanner;
public class CountLetters
{
public static void main(String[] args)
{
//create arrays
String[] upper = new String[25];
String[] lowerChar = new String[25];
int [] lowerCharNum = new int[25];
Scanner input = new Scanner(System.in);
System.out.println("Please enter a phrase");
//grab phrase from user
String phrase = "abccddee";
//create array with the size of the phrase entered from user
String[] letters = new String[phrase.length()];
System.out.println("letters length: " + letters.length);
//separate every letter in phrase and store it into array "letters"
letters = phrase.split("");
for(int i=0; i<letters.length; i++)
{
lowerChar[i] = letters[i];
switch(letters[i])
{
case "a":
lowerCharNum[0] += 1;
break;
case "b":
lowerCharNum[1] += 1;
break;
case "c":
lowerCharNum[2] += 1;
break;
case "d":
lowerCharNum[3] += 1;
break;
case "e":
lowerCharNum[4] += 1;
break;
case "f":
lowerCharNum[5] += 1;
break;
}//end of switch
System.out.println(lowerChar[i] + ": " + lowerCharNum[i]);
}
}//end of main method
}//end of class

Rather than working with simple array you can work with java's Collection's HashMap.
With HashMap the main working goes around with the for loop, will check if the Character is already present in the HashMap if it is then we will get the value associated with Character and will add 1 with the existing value and if the Character is not present then we will put a Character in HashMap and will store the initial count 1 with the associated character.
HashMap<Character, Integer> lettersCount = new HashMap<>();
String phrase = "abccddee";
int length = phrase.length();
int count = 1;
for (int i = 0; i < length; i++) {
int integer = 0;
char charAt = input.charAt(i);
if (!lettersCount.containsKey(charAt)) {
lettersCount.put(charAt, 0);
}
integer = lettersCount.get(charAt);
integer = initialCount + integer;
lettersCount.put(charAt, integer);
}
System.out.println(lettersCount);
You are using array which you will be needed to intialize first at time of declaration this will create a extra memory space which will be waste if all 26 letters are not being encountered and as per the code you have provided in the question you are allocating 3 arrays so it will take much more memory, So rather this solution will require only a HashMap (HashMap will allocate memory according to the key and value inserted in HashMap)and a for loop which will just compute the occurence of Charater and to use it again further in your program will be much more easier with it.

You are printing within the for loop. You should print the frequency outside that loop.
The method which you are using is not scalable. You will have to write 52 case statements in your switch given that the phrase consists only of uppercase and lowercase English alphabets.
A better way to do the same would be to use the ASCII encoding for your purpose. You can have something on the following lines:
int frequency[] = new int[128];
for (int i = 0; i < phrase.length(); i++) {
frequency[(int) phrase.charAt(i)]++;
}
In this method frequency array is used to count the occurrences of first 128 ASCII characters in phrase string. Operation (int) phrase.charAt(i) simply converts the character into corresponding ASCII code and we increase the counter for that character by 1. At the end of the processing, frequency array will contain the number of occurrences of first 128 ASCII characters in the given phrase string. Simply print this frequency to achieve desired output.

print statement must be outside the while for loop.
System.out.println(lowerChar[i] + ": " + lowerCharNum[i]);
updated:
you need to parse entire string first, then start printing.
import java.io.*;
import java.util.*;
class CountLetters {
public static void main(String[] args)
{
int i;
//create arrays
String[] upper = new String[25];
String[] lowerChar = new String[25];
int [] lowerCharNum = new int[25];
Scanner input = new Scanner(System.in);
System.out.println("Please enter a phrase");
//grab phrase from user
String phrase = "abccddee";
//create array with the size of the phrase entered from user
String[] letters = new String[phrase.length()];
System.out.println("letters length: " + letters.length);
//seperate every letter in phrase and store it into array "letters"
letters = phrase.split("");
for(i=0; i<letters.length; i++)
{
lowerChar[i] = letters[i];
switch(letters[i])
{
case "a":
lowerCharNum[0] += 1;
break;
case "b":
lowerCharNum[1] += 1;
break;
case "c":
lowerCharNum[2] += 1;
break;
case "d":
lowerCharNum[3] += 1;
break;
case "e":
lowerCharNum[4] += 1;
break;
case "f":
lowerCharNum[5] += 1;
break;
}//end of switch
}
for(i=0;i<5;i++)
System.out.println(lowerChar[i] + ": " + lowerCharNum[i]);
}//end of main method
}//end of class

Your solution with arrays is a bit complicated. By using a Map instead we can directly associate the encountered characters with the number of times they have been encountered, thus making it very straight-forward to increase the counter and to output the counter without having to look up indices in different arrays.
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class CountLetters
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("Please enter a phrase");
//grab phrase from user
String phrase = "abccddee";
//create array with the phrase entered from user
char[] letters = phrase.toCharArray();
System.out.println("letters length: " + letters.length);
// Map to keep track of all encountered characters and the
// number of times we've encountered them
Map<Character, Integer> characterCounts = new HashMap<>();
for(int i=0; i<letters.length; i++)
{
Character character = letters[i];
if(characterCounts.containsKey(character))
{
// We've encountered this character before, increase the counter
characterCounts.put(character, characterCounts.get(character) + 1);
}
else
{
// This is the first time we encounter this character
characterCounts.put(lowerChar, 1);
}
}
// Iterate over all character-counter pairs and print them
for(Map.Entry<Character, Integer> entry : characterCounts.entrySet())
{
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}//end of main method
}//end of class

HashMap - Stores keys and values in an unordered way and contains only unique keys.
TreeMap - Stores keys and values in a naturally ordered way and contains only unique keys.
LinkedHashMap - Stores keys and values in the order of keys insertions and contains only unique keys.
The appropriate data structure for such requirement will be a Map. If you want to maintain the order of letters in which they appeared in the String, you can use LinkedHashMap, if the order of letters in not a concern then you can you a HashMap. I am using LinkedHashMap for my example.
public class Test {
public static void main(String[] args) {
//Taking the input from the user
System.out.println("Enter the String"); //I am entering "abccddee" for your example
Scanner sc = new Scanner(System.in);
String input = sc.next();
//LinkedhashMap preserves the order in which input was supplied
LinkedHashMap<Character, Integer> lhm = new LinkedHashMap<Character, Integer>();
for(int i=0; i<input.length(); i++){
//method get will return null if the letter is not available at the given index else it will return the count
Integer j = lhm.get(input.charAt(i));
//If the chracter was not present in the String
if(j==null)
lhm.put(input.charAt(i),1);
//If the character was present in the String
else
lhm.put(input.charAt(i),j+1);
}
for(Character c : lhm.keySet())
System.out.println(c+": "+lhm.get(c)+" ");
}
}
The output will be:
a: 1
b: 1
c: 2
d: 2
e: 2

Related

How can I replace certain characters within a String in Java?

I have a program that reads an input (a String) and prints that String reversed. Now, I need to read through the reversed String and replace all of the "A"s with "T"s, the "T"s with "A"s, the "G"s with "C"s and the "C"s to "G"s. So basically, the "complement". I tried to use multiple lines with a replace function but once the "A"s are turned into "T"s, it will replace all of those into "A"s so there are no "T"s at all. How can I replace the characters so that they do not override each other?
Here is my code if it helps! I don't have any functions to get the "complement" yet, but here is what I'm working with.
import java.util.*;
public class DNA {
public static void main(String[] args)
{
System.out.println("Please input a DNA sequence: ");
Scanner read;
read = new Scanner(System.in);
String input = read.next();
String reverse="";
for(int i = input.length() - 1; i >= 0; i--) {
reverse = reverse + input.charAt(i);
}
System.out.println("Here is the reversed sequence: ");
System.out.println(reverse);
}
}
You can convert your reverse string to a char array like this:
char[] charArr = reverse.toCharArray();
Then you can iterate through it and change the characters that you want:
for(int i = 0; i < charArr.length; i++){
if(charArr[i] == 'A'){
charArr[i] = 't';
}
}
At the end you can convert the char array back to a string like this:
String str = new String(charArr);
Here is a code sample that you can try:
import java.util.Scanner;
class DNA {
public static void main(String[] args)
{
System.out.println("Please input a DNA sequence: ");
Scanner read = new Scanner(System.in);
String input = read.next();
String reverse="";
StringBuilder sb = new StringBuilder();
for(int i = input.length() - 1; i >= 0; i--) {
reverse = reverse + input.charAt(i);
}
for (char c: input.toCharArray()) { // user 'reverse' to operate on reversed string
switch (c) {
case 'A' : sb.append('T'); break;
case 'T' : sb.append('A'); break;
case 'G' : sb.append('C'); break;
case 'C' : sb.append('G'); break;
default : sb.append(""); break; // handle you're exceptions here
}
}
System.out.println("x: " + sb);
System.out.println("Here is the reversed sequence: ");
System.out.println(reverse);
read.close();
}}
Well, switch-case is a kind of mapping technique which will map your case (as key) with it's values. In this case:
I am replacing 'A' with 'T' where the string contains 'A' by appending into the StringBuilder (to create a new string) and then break; which is a mandatory statement for single time execution only.
And the default keyword is for default case, which means if all of the cases are unsatisfied to be executed then the default case is called, you can do whatever you want to do by default if no case, condition matched.
Well, for your last question, You can make it generic if the problem states some pattern; if not you, unfortunately have to do it manually.
Use the replace method, but change your values to a "temporary" character. https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)
Replace T -> x
Replace A -> T
Replace x -> A
Repeat for all your pairs.

Creating array with unknown elements by Input them

I know this isn't something you are supposed to do yet but I'm still trying to figure out a way to run this loop, an letting the arr[i] inside it "know" about the rise of the number of elements in the array (which I declare outside of the loop because I don't want it to make a new one each time).
int counter=1, note=0;
System.out.println("Please enter characters, -1 to stop: ");
do {
char[] arr= new char[counter];
for (int i=0;i<=counter;i++){
arr[i] = s.next().charAt(0);
if (arr[i]==-1){
note = -1;
break;
}
++counter;
}
} while (note>=0);
From your much clearer comment, this is an example main method.
public static void main(String[] args) {
Scanner input = new Scanner(System.in); // Input
int amt = 0; // Amount of chars received
List<Character> chars = new ArrayList<>(); // ArrayList is easier for now
while (input.hasNext()) { // Grabs Strings separated by whitespaces
String token = input.next(); // Grab token
if (token.equals("-1")) {
break; // End if -1 is received
} else if (token.length() != 1) {
throw new IllegalArgumentException("Token not one char: " + token);
// It seems you want only chars - this handles wrong input
} else {
chars.add(token.charAt(0)); // Adds the character to the list
amt++; // Increment amt
}
}
char[] array = new char[amt]; // Converting to an array
for (int i = 0; i < amt; i++) {
array[i] = chars.get(i); // Copies chars into array
}
System.out.println(Arrays.toString(array)); // Handle data here
}
I hope that this is correct. An input of a b c d -1 leads to an output of [a, b, c, d].
If you use the Input String size check I think as you will be resolved.
int counter=0, note=0;
System.out.println("Please enter characters, -1 to stop: ");
String input=s.nextLine();
counter=input.length();
char[] arr= new char[counter];
for (int i=0;i<counter;i++){
arr[i] = input.charAt(i);
}
and If you are using the ArrayList rather than Array is no need to worry about the size.
ArrayList is effective flexable data
cause using add function.

Force a stringBuilder to an upper case

I was wondering if there is anyway to use something like the toUpperCase for StringBuilder? Below is my code, I am trying to take user input of a phrase and turn it into an acronym. Someone helped me out by suggesting StringBuilder but I can't figure out if there is a way to make the acronym upper case. Any help is greatly appreciated.
public class ThreeLetterAcronym {
public static void main(String[] args) {
String threeWords;
int count = 0;
int MAX = 3;
char c;
//create stringbuilder
StringBuilder acronym = new StringBuilder();
Scanner scan = new Scanner(System.in);
//get user input for phrase
System.out.println("Enter your three words: ");
threeWords = scan.nextLine();
//create an array to split phrase into seperate words.
String[] threeWordsArray = threeWords.split(" ");
//loop through user input and grab first char of each word.
for(String word : threeWordsArray) {
if(count < MAX) {
acronym.append(word.substring(0, 1));
++count;
}//end if
}//end for
System.out.println("The acronym of the three words you entered is: " + acronym);
}//end main
}//end class
Just append upper case Strings to it :
acronym.append(word.substring(0, 1).toUpperCase())
or turn the String to upper case when getting the String from the StringBuilder :
System.out.println("The acronym of the three words you entered is: " + acronym.toString().toUpperCase());
Just append upper case String to StringBuilder.
//loop through user input and grab first char of each word.
for(String word : threeWordsArray) {
if(count < MAX) {
acronym.append(word.substring(0, 1).toUpperCase());
++count;
}//end if
}//end for
Or upper case the String when getting it from StringBuilder.
System.out.println("The acronym of the three words you entered is: " + acronym.toString().toUpperCase());
If you need a library take a look at Apache Common Lang WordUtils, WordUtils.capitalize(str).

How to change the output to the count of words?

How can i change the output from "my name is" from {2=1 4=1} to >the number of words with the length of 2 is 1 and then on the next line the amount of word with the length of 4 is 1, like the output underneath:
//You have typed the sentence: my name is
//the number of words with the length of 2 is 1
//the amount of word with the length of 4 is 1
Basically how can I change '{2=2, 4=1}' to a sentence form?
This is my code:
public static void main(String args[]) {
System.out.println("Write your sentence please:");// prints out the first instruction.
Scanner scan = new Scanner(System.in); //object initialisation.
String line=" ";//declaration for letters(String) characters.
//int max = 20; //declaration for number(int) characters.
while((line=scan.nextLine())!=null) { //scanner instruction, get a line from the key board.
String[] tokens = line.split(" ");// splits the words
Map<Integer,Integer> tokensLength = new HashMap<Integer,Integer>();
for (int i = 0; i < tokens.length; i++) {// this line of code checks for what must be true to carry on.
int length = tokens[i].length();
if (tokensLength.containsKey(length))
tokensLength.put(length, tokensLength.get(length) + 1);
else
tokensLength.put(length, 1);
}
for (Integer length : new TreeSet<Integer>(tokensLength.keySet()))
System.out.println("You have typed the sentence: " + line);//prints out what you have typed.
System.out.println("The word length frequency of the sentence is " + tokensLength);//prints out the results
}//End of scanner instruction
}//End of main
Thank you! Any help would be much appreciated!
Use that to iterate over the map and write nice sentences :)
for (Entry<Integer, Integer> entry : tokensLength.entrySet()){
System.out.println("There are "+entry.getValue()+" words of length "+entry.getKey());
}

Java - Histogram program

I have a program which takes a string and gives a histogram. The problem is i need the histogram to be in order... like...
letter count
a 0
b 1
c 0
.... etc. My program will just give back the letters in the string, it will not display the letters which are not in the string. here is my main program.
import java.util.*;
public class CharacterHistogram {
//scanner and method decleration
Scanner keyboard = new Scanner (System.in);
public static void generateHistogram( String input) {
// make input lower case
input=input.toLowerCase();
int lengthOfInput= input.length();
char[] Array = input.toCharArray();
//Arrays.sort(Array);
int count = 0;
// colum creation
System.out.println();
System.out.println(" Character Count");
for (int i = 0; i < lengthOfInput; i++) {
// reset count every new letter
count = 1;
for (int x = i + 1; x < lengthOfInput; x++) {
if (Array[i] == ' ') {
break;
}
if (Array[i] == Array[x]) {
count++;
Array[x] = ' ';
}
}
// check for empty char
if (Array[i] != ' ') {
System.out.println();
//row creation
System.out.println(" "+Array[i]+" "+count);
System.out.println();
}
}
}
}
here is the tester:
public class CharacterHistogramTester{
public static void main(String [] args){
String input = "4axaaafgaa5";
System.out.println("Generate Histogram for: " + input);
CharacterHistogram.generateHistogram(input);
input = " OSU won 34-10 and now have 7 wins";
System.out.println("Generate Histogram for: " + input);
CharacterHistogram.generateHistogram(input);
}
}
i would like to know if there are any ways to show all letters (even ones not used in string) alphabetically. Thank you.
P.S. i have tried the sort(Array) method and it screws up the whole program...
Create an int array of length 26, contaning the number of occurrences of each letter (0, initially).
Loop through each char of your input, and increment the integer at the appropriate index (0 for a, 1 for b, etc.).
Then print every element of the int array.
Oh, and respect the Java naming conventios: variables start with a lowercase letter.
Use a single loop to traverse the string & count letter/character occurrences, not the unnecessary & inefficient "loop within a loop" structure which you have currently.
Initialization, counting & printing the output should be separate blocks of code -- not mangled into the same block.

Categories

Resources