So I have a program in java that takes a string from user input, sorts it, finds the frequencies, and prints it in alphabetical order. My only issue is that it also prints duplicates. So, if the letter d appeared three times in a string, it would print like this:
d freq: 3
d freq: 3
d freq: 3
For this project, I am not allowed to use any built-in java sorting functions (hashmaps included). Any suggestions on how to stop this? Here's my code. Thank you!
char[] charArray = userSort.toCharArray();
char tempChar;
for (int i = 0; i < charArray.length; i++) {
for (int j = 0; j < charArray.length; j++) {
if (charArray[i] < charArray[j]) {
tempChar = charArray[i];
charArray[i] = charArray[j];
charArray[j] = tempChar;
}
}
}
String sortedString = "";
for (int i = 0; i < charArray.length; i++) {
userSort += charArray[i];
}
System.out.println(sortedString + "\n");
int counter;
sortedString = "";
for (int i = 0; i < charArray.length; i++) {
counter = 0;
for (int j = 0; j < charArray.length; j++) {
if (charArray[i] == charArray[j]) {
counter++;
}
}
if (!sortedString.contains("Char: " + charArray[i])) {
if (sortedString.equals("")) {
sortedString += " " + charArray[i] + " freq: " + counter + "\n";
} else {
sortedString += " " + charArray[i] + " freq: " + counter + "\n";
}
}
}
System.out.println(sortedString);
Make sure that i != 0.
Compare charArray [i] to charArray [i-1].
If they're not equal, then print out the result.
You can use a TreeMap<Character, Integer> to keep sorted character order and for counting letter frequencies.
Map<Character, Integer> freqs = new TreeMap<>();
for (char c : charArray.length) {
freqs.put(c, 1+freqs.getOrDefault(c, 0));
}
You also don't need to sort the input string. (Especially not using bubble sort). Iterating the characters and adding/updating to the map will create the order.
What you need to do is a Bucket Sort
In brief, create a int array of length 26, which represent 26 characters (Let's call this the "counter array"
Loop through your string. For each character encountered, increment the corresponding int in the counter array.
After looping through the input string, the counter array will contains the number of occurrence for each of 26 characters
The rest should be straight-forward I believe, which you just need to loop thru the counter array and print corresponding output
Spoiler ahead: sample code. Don't read if you haven't tried to write your code
String input = "The quick brown fox jumps over a lazy dog";
int[] counter = new int[26];
for (char c : input.toLowerCase().toCharArray()) {
if (c >= 'a' && c <= 'z') {
counter[c-'a']++;
}
}
for (int i = 0; i < counter.length; ++i) {
System.out.println("" + (char)('a' + i) + " occurs " + counter[i] + " times");
}
Solution: updated without hashmap and sorting:
Algo:
1.Create temp array of 26 alphabet and put frequency count ..i.e
0-> a,
1-> b....
2.Iterate array to print the result
public static void countFrequency(){
String user = "Harshal";
user = user.toLowerCase();
char ch[]= user.toCharArray();
int arr[] = new int[26];
for(char c : ch){
arr[c-97]++;
}
for(int k=0;k<26;k++){
if(arr[k]!=0){
int val = k+97;
System.out.println((char)val + " freq: " + arr[k]);
}
}
}
Related
I'm making a program which receives a string as input and returns the "sum" of the values for each letter of each word.
For example, my input of "Take advantage, do your best, don't stress.", would return:
do(19) take(37) dont(43) best(46) advantage(75) your(79) stress(100)
"do" would have a value of 19 because the letter "d" has a value of 4 (it is the fourth letter of the alphabet), and "o" has a value of 15, so the total is 19.
Now to store these values I have two arrays, one string array for each word, and one int array for the point value that they have. However, I only have this so far:
take(37) advantage(75) do(19) your(79) best(46) dont(53) stress(100)
As you can see, it is not sorted in ascending order as I am trying to do. I display these values like this:
System.out.print(words[j] + "(" + points[j] + ")" + " ");
where words is the String array and points is the int array. How can I sort them?
My current code:
public static void main (String[] args)
{
String input = "Take advantage, do your best, don't stress.";
String output = "";
//Get rid of all punctuation
for(int i = 0; i < input.length(); i++){
if( ( (int)input.charAt(i) >= 65 && (int)input.charAt(i) <= 90) || (int)input.charAt(i) == 32 || ( (int)input.charAt(i) >= 97 && (int)input.charAt(i) <= 122)){
//Handles Uppercase
if(input.charAt(i) >= 65 && input.charAt(i) <= 90){
int temp = (int)input.charAt(i) + 32;
char c = (char)temp;
output += c;
}
//Handles all other characters
else{
output += input.charAt(i);
}
}
}
//Done punctuation
String[] words = output.split(" ");
int[] points = new int[words.length];
//Points assignment
for(int j = 0; j < words.length; j++){
for(int k = 0; k < words[j].length(); k++){
points[j] += (int)words[j].charAt(k) - 96;
}
System.out.print(words[j] + "(" + points[j] + ")" + " ");
}
}
How about storing your results in a Map<String,Integer> instead of two lists:
Map myMap = new HashMap<String,Integer>;
From there you can sort the Map by its values: Sort a Map<Key, Value> by values (Java)
Next you can iterate through the sorted map:
for(String s : myMap.keySet()){
System.out.println(s+"("+myMap.get(s)+")");
}
If that is an option, your code can be made much simpler with Java 8.
First of all, removing punctuation can be done with a simple regular expression: you only want to keep letters, so we can just remove everything that is neither a letter nor a space. This is done by calling replaceAll("[^a-zA-Z\\s]", ""). After that, we can get a hold of all the words by splitting around "\\s+" (i.e. all whitespace characters).
Then, let's create a helper method returning the value of a String. As you have in your question, this would just be:
private static int value(String str) {
return str.chars().map(c -> c - 'a' + 1).sum();
}
Finally, we need to sort the words array with a comparator comparing the value of each word. The comparator is created with the help of Comparator.comparingInt(keyExtractor) where the key extraction would be a function returning the value of a word. In this case, it could be expressed a lambda expression: word -> value(word).
To have the final output, we need to transform the words array into a String where each word is concatenated with its value in parentheses. This is done by creating a Stream<String> of the words (Arrays.stream(array)), sorting it according the comparator above (sorted(comparator)), mapping each word to the result of concatenating its value to it and finally collecting that into a String delimited by a space (Collectors.joining(delimiter)).
Whole code would be:
public static void main(String[] args) {
String str = "Take advantage, do your best, don't stress.";
String[] words = str.toLowerCase().replaceAll("[^a-zA-Z\\s]", "").split("\\s+");
String output =
Arrays.stream(words)
.sorted(Comparator.comparingInt(w -> value(w)))
.map(w -> w + "(" + value(w) + ")")
.collect(Collectors.joining(" "));
System.out.println(output);
}
private static int value(String str) {
return str.chars().map(c -> c - 'a' + 1).sum();
}
Use any of sorting algorithm and do sorting for both arrays. For example:
public static void bubbleSort(int[] numArray, String[] words) {
int n = numArray.length;
int temp = 0;
String tt;
for (int i = 0; i < n; i++) {
for (int j = 1; j < (n - i); j++) {
if (numArray[j - 1] > numArray[j]) {
temp = numArray[j - 1];
tt=words[j-1];
numArray[j - 1] = numArray[j];
words[j-1]=words[j];
numArray[j] = temp;
words[j]=tt;
}
Then change last part of your main function to look like this:
String[] words = output.split(" ");
int[] points = new int[words.length];
//Points assignment
for(int j = 0; j < words.length; j++){
for(int k = 0; k < words[j].length(); k++){
points[j] += (int)words[j].charAt(k) - 96;
}
}
bubbleSort(points,words);
for(int j = 0; j < words.length; j++){
System.out.print(words[j] + "(" + points[j] + ")" + " ");
}
If you are not allowed to use Java 8 (else use #Tunaki's approach), create a Comparable object that keeps two values, a String (word) and an int (sum). Then, just add each word to a list and sort it using Collections.sort(yourList).
public class Word implements Comparable<Word>{
private String word;
private int sum;
public Word(String word) {
this.word = word;
setSum();
}
private void setSum() {
//your sum function, I just copy and paste it from your post
for(int k = 0; k < word.length(); k++)
sum += (int)word.charAt(k) - 96;
}
public String getWord() {
return word;
}
public int getSum() {
return sum;
}
#Override
public int compareTo(Word o) {
return this.sum > o.sum ? 1 : -1;
}
}
I have to write a program to accept a String as input, and as output I'll have to print each and every alphabetical letter, and how many times each occurred in the user input. There are some constraints:
I cannot use built-in functions and collection
The printed result should be sorted by occurrence-value.
For example, with this input:
abbbccccdddddzz
I would expect this output:
a-1,z-2,b-3,c-4,d-5
This is what I have so far:
public static void isCountChar(String s) {
char c1[] = s.toCharArray();
int c3[] = new int[26];
for (int i = 0; i < c1.length; i++) {
char c = s.charAt(i);
c3[c - 'a']++;
}
for (int j = 0; j < c3.length; j++) {
if (c3[j] != 0) {
char c = (char) (j + 'a');
System.out.println("character is:" + c + " " + "count is: " + c3[j]);
}
}
}
But I don't know how to sort.
First of all a tip for your next question: The things you've stated in your comments would fit better as an edit to your question. Try to clearly state what the current result is, and what the expected result should be.
That being said, it was an interesting problem, because of the two constraints.
First of all you weren't allowed to use libraries or collections. If this wasn't a constraint I would have suggested a HashMap with character as keys, and int as values, and then the sorting would be easy.
Second constraint was to order by value. Most people here suggested a sorting like BubbleSort which I agree with, but it wouldn't work with your current code because it would sort by alphabetic character instead of output value.
With these two constraints it is probably best to fake key-value pairing yourself by making both an keys-array and values-array, and sort them both at the same time (with something like a BubbleSort-algorithm). Here is the code:
private static final int ALPHABET_SIZE = 26;
public static void isCountChar(String s)
{
// Convert input String to char-array (and uppercase to lowercase)
char[] array = s.toLowerCase().toCharArray();
// Fill the keys-array with the alphabet
char[] keys = new char[ALPHABET_SIZE];
for (int i = 0; i < ALPHABET_SIZE; i++)
{
keys[i] = (char)('a' + i);
}
// Count how much each char occurs in the input String
int[] values = new int[ALPHABET_SIZE];
for (char c : array)
{
values[c - 'a']++;
}
// Sort both the keys and values so the indexes stay the same
bubbleSort(keys, values);
// Print the output:
for (int j = 0; j < ALPHABET_SIZE; j++)
{
if (values[j] != 0)
{
System.out.println("character is: " + keys[j] + "; count is: " + values[j]);
}
}
}
private static void bubbleSort(char[] keys, int[] values)
{
// BUBBLESORT (copied from http://www.java-examples.com/java-bubble-sort-example and modified)
int n = values.length;
for(int i = 0; i < n; i++){
for(int j = 1; j < (n - i); j++){
if(values[j-1] > values[j]){
// Swap the elements:
int tempValue = values[j - 1];
values[j - 1] = values[j];
values[j] = tempValue;
char tempKey = keys[j - 1];
keys[j - 1] = keys[j];
keys[j] = tempKey;
}
}
}
}
Example usage:
public static void main (String[] args) throws java.lang.Exception
{
isCountChar("TestString");
}
Output:
character is: e; count is: 1
character is: g; count is: 1
character is: i; count is: 1
character is: n; count is: 1
character is: r; count is: 1
character is: s; count is: 2
character is: t; count is: 3
Here is a working ideone to see the input and output.
some sort: easy if not easiest to understand an coding
You loop from the first element to the end -1 : element K
compare element K and element K+1: if element K>element K+1, invert them
continue loop
if you made one change redo that !
I use simple method to change string values without changing original length of string.then back convert change the text back into pure string(into Original text).
My code :
String someText = "abcdefgHIJKLMN";
char[] data = someText.toCharArray();
int LEN = someText.length();
char[] datas = new char[LEN];
System.out.println("Original Text ("+String.valueOf(LEN)+"): "+someText);
for (int i = 0; i < LEN; i++) {
data[i] = Character.valueOf((char) i);
System.out.println(String.valueOf(i) + " = " + String.valueOf((char) i));
}
System.out.println("Add 10 into each charactor : "); // ex a =1 , a+10 : now it's 'k'
for (int i = 0; i < LEN; i++) {
char c = Character.valueOf((char) (Character.getNumericValue(Character.valueOf(data[i])) + 10));
datas[i] = c;
System.out.print(String.valueOf(c));
}
System.out.println("Subtract 10 from each charactor : ");// ex k =11 , k-10 : now it should be 'a'
for (int i = 0; i < LEN; i++) {
char c = (char) (Character.getNumericValue(Character.valueOf(datas[i])) - 10);
System.out.print(String.valueOf(c));
}
But after adding and subtracting that loops dose not display anything.
If there is any solution to achieve this type of things without changing original length of text?
This is the thing I want to do:
Let say character value of a is 97 then we add 10 into it:(97+10) = 107 now it's not a it's should be different letter such as k because 107 character value is :K
I think the problem is in line 8:
data[i] = Character.valueOf((char) i);
When i = 0, data[i] is not 'a'. 'a' has a value of 97 (hex 61):
http://www.utf8-chartable.de/
Moreover you can add chars using '+' but the result of '+' operator is integer, so you only have to cast it to char - ie.
char c = (char) (data[i] + 10);.
Also in your loops you used print instead of println, that's why the output was not so clear. Try the code below and see if it works out for you.
String someText = "abcdefgHIJKLMN";
char[] data = someText.toCharArray();
int LEN = someText.length();
char[] datas = new char[LEN];
System.out.println("Original Text ("+String.valueOf(LEN)+"): "+someText);
for (int i = 0; i < LEN; i++) {
System.out.println(String.valueOf(i) + " = " + data[i]);
}
System.out.println("Add 10 into each charactor : "); // ex a =1 , a+10 : now it's 'k'
for (int i = 0; i < LEN; i++) {
char c = (char) (data[i] + 10);
datas[i] = c;
System.out.println(String.valueOf(c));
}
System.out.println("Subtract 10 from each charactor : ");// ex k =11 , k-10 : now it should be 'a'
for (int i = 0; i < LEN; i++) {
char c = (char) (datas[i] - 10);
System.out.println(String.valueOf(c));
}
I am writing a java code for finding element Ex.food for any attribute(attr)Ex.description in XML.
What I have done
I am taking first char of attr as start position and then checking if it equals to "<" .From this point I am looping to ignore white space,tab etc and proceed to append valid char till I find another white space,tab.But this is not working.It is supposed to find the first word after "<" and print that only .But its actually going till the end from the the point it find first char after "<"
Note:I cannot use XML parsers like DOM etc
XML
<breakfast_menu>
<food name="Belgian Waffles" price="$5.95" discount="20"
description="Two" calories="650" />
</breakfast_menu>
for (int k = start_position; k >= 0; k--) {
char testChar = xmlInString.charAt(k);
String temp = Character.toString(testChar);
if ("<".equals(temp)) {
System.out.println(k + "value of k");
for (int j = k + 1; j >= 0; j++) {
char appendChar = xmlInString.charAt(j);
String temp1 = Character.toString(appendChar);
if(!("".equals(temp1))) {
System.out.println(j + " " + appendChar);
}
}
}
}
I made few changes now and its working as expected.i.e giving first word after "<". If you have any suggestion please let me know.
int k, j, l;
for (k = start_position; k >= 0; k--) {
char testChar = xmlInString.charAt(k);
String temp = Character.toString(testChar);
if ("<".equals(temp)) {
break;
}
}
for (j = k + 1; j <= start_position; j++) {
char appendChar = xmlInString.charAt(j);
String temp1 = Character.toString(appendChar);
if (!("".equals(temp1))) {
break;
}
}
for (l = j; l <= start_position; l++) {
char appendChar1 = xmlInString.charAt(l);
String temp2 = Character.toString(appendChar1);
if (" ".equals(temp2)) {
break;
}
}
System.out.println(xmlInString.substring(j, l));
I think this will help
String str = "<food name=\"Belgian Waffles\" price=\"$5.95\" discount=\"20\"\n" ;
String res = str.substring(str.indexOf("<"), str.indexOf(" ", str.indexOf("<") + "<".length()) + " ".length());
System.out.println(res);
output
<food
Your inner while loop for (int j = k + 1; j >= 0; j++) { is broken. The condition j >= 0 doesn't make sense - j only increments so how could it ever be < 0? Instead you should be looking for the next space, tab, etc.
I don't think your solution is going to work, but that is what's wrong with the code you have posted and why it's running off the end.
I have this code which is working fine but the thing is that the result is showing as below.
public static int[] countlist (char[] list){
int [] counts = new int[list.length];
for (int k = 0; k < list.length; k++) {
for (int m = 0; m < list.length; m++) {
if (list[m] == list[k]){
counts[m]++;
}
}
System.out.println( "Letter " + list[k] + " = " + counts[k]);
}
}
Output:
Letter T = 1
Letter T = 2
Letter N = 1
Letter T = 3
Letter Z = 1
Letter N = 2
Letter H = 1
Letter H = 2
How do I have to do to get the output for each letter once?
Thanks alot
For example, I want output to be like below
Letter T = 3
Letter N = 2
Letter Z = 1
Letter H = 2
Use a HashMap to hold the counts/frequency of individual characters.
Traverse through your list and for each element do:
if the element is not present in the HashMap, insert it with the frequency 1
if the element is present in the HashMap, increase the frequency by 1.
At the end, printing the key/value pairs of the HashMap will give you the desired output.
I'm not that familiar with java yet that I can type the code quickly now but basically you can create an array and have the keys be the letters and the values the values of the letters
in PHP this would work something alike:
$array = array();
$array['T'] = 1;
$array['T'] = 2;
$array['T'] = 3;
$array['N'] = 2;
$array['Z'] = 1;
$array['H'] = 2;
echo print_r($array); //Resulting in T=>3, N=>2, Z=>1, H=>2
If you don't want the first value of (for example) T to be overwritten all you have to do is implement an IF statement checking if $array['T'] already exists.
EDIT:
in your provided code you would have to implement it where I've marked it:
public static int[] countlist (char[] list){
int [] counts = new int[list.length];
for (int k = 0; k < list.length; k++) {
for (int m = 0; m < list.length; m++) {
if (list[m] == list[k]){
counts[m]++;
}
}
//====Insert the code here====
System.out.println( "Letter " + list[k] + " = " + counts[k]);
}
}
Primitive arrays to store the result is mandatory? You could use a Hashmap and define the letter as the key and the counter as the value.
Map<Character, Integer> charactersOccurrences = new HashMap<Character, Integer>();
for (int k = 0; k < list.length; k++) {
if (charactersOccurrences.containsKey(list[k])) {
charactersOccurrences.put(list[k], charactersOccurrences.get(k) + 1);
} else {
charactersOccurrences.put(list[k], 1);
}
}
Then to print:
for(char aLetter : charactersOccurrences.keySet()) {
System.out.println("Letter " + aLetter + " = " + charactersOccurrences.get(aLetter));
}
public static void countlist (char[] list)
{
Map<Character, Integer> map = new HashMap<Character, Integer>();
for (int k = 0; k < list.length; k++)
{
if (map.containsKey(list[k]))
{
map.put(list[k], map.get(list[k]) + 1);
}
else
{
map.put(list[k], 1);
}
}
for (Map.Entry<Character, Integer> entry : map.entrySet())
{
System.out.println( "letter = " + entry.getKey() + ", count = " + entry.getValue() );
}
}