what does "ch - 'a' " mean? [duplicate] - java

This question already has answers here:
Adding and subtracting chars, why does this work? [duplicate]
(4 answers)
Closed 4 years ago.
I was going through a piece of code which i was not able to understand. Thought of checking this with our community.
In the below code, i am not able to understand what the line count[ch-'a']++ does. or how can we write the same in java 7. What the explanation says is that we have a String s and an int array count. We iterate through the string s and count the no of occurrences of the characters in s and put the frequencies of count into the array. please help!!
String s = "test";
int[] count = new int[26];
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
count[ch-'a']++;
}

the code is trying to count the number of occurrence of each character.
and it allocates it such that
a occupies position 0
b occupies position 1
etc etc
to get position 0, you need to call 'a' - 'a'
to get position 1, you need to call 'b' - 'a'
so what is happening in "count[ch-'a']++;" is eqivalent to
int position = ch -'a'; // get position
count[position] = count [position] + 1; // increment the count in that particular position

You are iterating over an array of ints count and incrementing the integer value at index ch-'a', which results in an integer value, e.g count['a'-'a'] == count[0] to flag that the character exists in the string.
you subtract in ch - 'a' because the integer value of alphabetic characters does not start at 0.

It means to treat the two characters like integers and subtract one from the other. For instance,
'b' - 'a' == 1
In the code you posted, it's counting up all the lowercase characters into an array data structure. In other words, the count[0] will be very large if there are many lowercase 'a's in the String, count[1] will be large if many lowecase 'b's, etc.

count[] is here to store occurrences of each letter from String passed as argument (at count[0] there will be stored number of occurences of 'a', at count[1] number of occurences of 'b',... at count[25] occurences of 'z').
Now in the following line:
char ch = s.charAt(i);
You store currently checked character from given String. (when i = 0, it's 't'). Keep in mind, that each char can be presented as int (it's an ASCII code) . To see list of all numeric values corresponding to each char, you can search for the ASCII table in the Internet (e. g. here, at column "Dec"). So for 't' it's 116.
By saying:
count[ch-'a']++;
You mean count[116 - 97]++, it's count[19]++. Subtracting by 'a' is subtracting by 97 and it's here to help quickly find index in the array in which you store occurrences of currently checked char ch. Look, for 'a' it would be count['a' - 'a'] (count[0] - first index in count array), for 'z' count[122 - 97] (count[25] - last index in count array)

Related

I keep getting a "java.lang.StringIndexOutOfBoundsException" even though my for loop counter adjusts for length by subtracting 1

So my main goal is to create a program that can decrypt a caesar cipher. I have everything set up so that I have the regular alphabet set up in one array and then a decoder array where I have shifted the alphabet based on a shift/key the user inputs. (ie. if the user inputs a shift of 6, the regular alphabet array starts a, b, c... and then the decoder array starts g, h, i...).
I am currently stuck on going through the encrypted message (user inputted) and decoding each letter one by one by matching it up to the decoder array. It keeps giving me an index out of bounds error even though in the for loop that I have set up, I have subtracted one from the length of the message to compensate for it starting at 0.
The error only happens at the last character too (that's what the 35 is. I have a 35 character string that I'm using to test). But when I try to print the decoded message up until the error, I'm just getting nulls (I'm storing each decoded char in an array and print each character stored as the for loop is running).
Here is the piece of code that I'm currently stuck on:
//Decoding message by looping through each letter in String message
for (int x = 0; x < (message.length() - 1); x ++) //Gets next letter in message
{
for (int y = 0; y < (decodedArray.length - 1); x++) //Goes through decodedArray array
{
if (String.valueOf(message.charAt(x)) == (decodedArray[y])) //Comparing character to each position in decodedArray
{
decodedMessage[x] = alphabetArray[y];
}
System.out.print(decodedMessage[x]); //Testing only. Prints each character stored in array but only printing nulls.
}
}
I haven't added any checks for spaces yet because I'm currently stuck on this error but if any of you can add that, that would be greatly appreciated. I'm not sure if comparing a char to a space would work.
According to the current code in the question, I can say there are 2 problems with your code,
If you need to compare char, you can directly use to == operator without needing it to convert it to string by using String.ValueOf().
You are incrementing x in the 2nd loop, instead you need to increment y

Removing a single char from a string of letters based on a number position in JAVA [duplicate]

This question already has answers here:
How to remove single character from a String by index
(23 answers)
Closed 4 years ago.
To give some context to the title, let's say I have an array of INTs. So, for example (1,2,3,4,5).
Each number in the array represents a char in a string. So if the string is hello then array[3] is going to represent "l".
What is the most efficient or simplest way to remove a char from a string, replace the char and then add it back into the string?
So using the example above I could change "l" to "d", add it back to the string so my final string is "hedlo".
here is part of my code:
method used for max:
public static int getMax(int[] inputArray){
int maxValue = inputArray[0];
for(int i=1;i < inputArray.length;i++){
if(inputArray[i] > maxValue){
maxValue = inputArray[i];
}
}
return maxValue;
}
here is the code for using the max value in the array as the position in the string results to edit. The char to edit should be replaced with an "m" in the actual case
int max = getMax(array);
results.setCharAt(max, 'm');
String result = results.toString();
Yes, it can easiyl be done. Below I have some code from https://stackoverflow.com/a/4576556/9354346
StringBuilder str = new StringBuilder("hello");
str.setCharAt(2, 'd');
String result = str.toString();
Without knowing why you're doing this, I'm not sure exactly what to recommend but here's something to think about. ASCII characters have numerical values associated with them. Table.
If you cast an int to a char, it will convert it to that value. So like,
char c = (char) 97;
would evaluate to 'a.' If you want 'a' to start at 1, you could just add 96 to everything.
To convert, you could add to an int the difference in the table. So from 'a' to 'd', add 3.
EDIT:
I answered this assuming you were changing an array of ints that was representing a string. Re-reading the question, I'm not sure that's what you're doing! If you need to change a character of a string to a different character, you can use the substring function to grab characters before the change, and after the change and put the new character in the middle.
String x = "Hello";
x = x.substring(0,2) + 'd' + x.substring(3);
This makes x say "Hedlo."

Counting Common Elements in a String Array

I am trying to make a program to count common elements occuring in all the Strings in a String[] array. I have the following:-
A master array and a flag array both of size 26
Now for each string: I am marking frequency 1 for each character that appears in the string without incrementing in flag array.
Now I am adding the values of flag array to corresponding values of master array
my code looks like this
for(String str : arr)
{
for(char ch : str.toCharArray())
{
flag[ch - 97] = 1;
master[ch - 97] =master[ch -97] + flag[ch - 97];
}
}
My plan is to finally count elements in the master array that have value equal to input string array's length. This count will represent the count of characters that are common to all the strings
But my code has a flaw.
if a String has duplicate elements for example, 'ball' (with 2 ls). The corresponding value of the element in master array is getting incremented again.
Which makes its value larger than what I wanted.
So this is what I did.
for(String str : arr)
{
newstr = ""; //to keep track of each character in the string
for(char ch : str.toCharArray())
{
int counter = 0;
for(int i = 0; i < newstr.length();i++)
{
char ch2 = newstr.charAt(i);
if (ch == ch2 )
{
counter = counter + 1; //if duplicate
break;
}
}
if(counter == 1)
{
break;
}
flag[ch - 97] = 1;
master[ch - 97] =master[ch -97] + flag[ch - 97];
newstr = newstr + ch;
}
}
Is this the right approach? or could this code be more optimized?
IMHO - "The right approach" is one you fully understand and can refactor at will. There are generally always multiple ways to approach solving any programming problem. Personally, I would approach (what I think is) the problem you are trying to solve in a manner more ideomatic to Java.
For the entire array of strings you are going to examine, every character in the first string you examine is in every string examined so far, so every character in that first string would go into a Map<Character, Integer> i.e. charCountMap.put(aChar, 1) For the second string and every string thereafter: If a character in the string under examination is in the map's keySet, then increment the associated Integer (increment that key's associated value) charCountMap.get(aChar)++. After examining every character in every string, then the keys in the keyset that map to Integers with values that match the original string array's length are exactly the characters that were found in every string.
So far, this proposed solution doesn't solve the repeating character problem you describe above. To solve that part, I think you need to keep a separate list of unique characters "seen so far" in the "string under examination" (and empty the list for every new string). You would check the "seen so far" list first, and skip all further processing of that character if found in "seen so far", only characters not "seen so far" (in this string under examination) would be checked against the map's keyset. example code
There is also a recursive approach to programming a solution to this problem, but I'll leave that fruit hanging low...

Inserting letters into a string at every possible spot [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am looking to insert a single letter one by one into every possible index of a string.
For example the string ry
Would go "ary" "bry" "cry" ... "zry" ... "ray" "rby" .... "rzy" ... "rya" "ryb"
I am not sure how to begin, any help?
Try this
System.out.println("originaltext".replaceAll(".{1}","$0ry"));
The above is using the String replaceAll(String regex, String replacement) method - "Replaces each substring of this string that matches the given regular expression with the given replacement."
".{1}" - The regular expression used to find exactly one occurrence({1}) of any character(.)
"$0ry" - The replacement string with "$0" for the matched value followed by the required characters(ry).
This is repeated for all matches!
Example Code
String originalString = /* your original string */;
char[] characters = /* array of characters you want to insert */;
Vector<String> newStrings = new Vector<>();
String newString;
for (int idx = 0; idx < originalString.length() + 1; ++idx) {
for (char ch : characters) {
newString = originalString.substring(0, idx)
+ ch
+ originalString.substring(idx, originalString.length());
newStrings.add(newString);
}
}
Explanation
Processing all cases:
In order to insert every single letter into an index in a string, you need a loop to iterate through every letter.
In order to insert a letter into every index in a string, you need a loop to iterate through every index in the string.
To do both at once, you should nest one loop inside the other. That way, every combination of an index and a character will be processed. In the problem you presented, it does not matter which loop goes inside the other--it will work either way.
(you actually have to iterate through every index in the string +1... I explain why below)
Forming the new string:
First, it is important to note the following:
What you want to do is not "insert a character into an index" but rather "insert a character between two indices". The distinction is important because you do not want to replace the previous character at that index, but rather move all characters starting at that index to the right by one index in order to make room for a new character "at that index."
This is why you must iterate through every index of the original string plus one. Because once you "insert" the character, the length of the new string is actually equal to originalString.length() + 1, i.e. there are n + 1 possible locations where you can "insert" the character.
Considering this, the way you actually form a new string (in the way you want to) is by getting everything to the left of your target index, getting everything to the right of your target index, and then concatenating them with the new character in between, e.g. leftSubstring + newCharacter + rightSubstring.
Now, it might seem that this would not work for the very first and very last index, because the leftSubstring and/or rightSubstring would be an empty string. However, string concatenation still works even with an empty string.
Notes about Example Code
characters can also be any collection that implements iterable. It does not have to be a primitive array.
characters does not have to contain primitive char elements. It may contain any type that can be concatenated with a String.
Note that the substring(int,int) method of String returns the substring including the character at beginIndex but not including the character at endIndex. One implication of this is that endIndex may be equal to string.length() without any problems.
Well you will need a loop for from i = 0 to your string's length
Then another loop for every character you want to insert - so if you want to keep creating new strings with every possible letter from A to Z make a loop from char A = 'a' to 'z' and keep increasing them ++A(this should work in java).
This should give you some ideas.
Supposing, for instance, you want them all in a list, you could do something like that (iterating all places to insert and iterating over all letters):
List<String> insertLetters(String s) {
List<String> list = new ArrayList<String>();
for (int i = 0; i <= s.length(); i++) {
String prefix = s.substring(0, i);
String postfix = s.substring(i, s.length());
for (char letter = 'a'; letter <= 'z'; letter++) {
String newString = prefix + letter + postfix;
list.add(newString);
}
}
return list;
}
String x = "ry";
char[] alphabets = "abcdefghijklmnopqrstuvwxyz".toCharArray();
String[] alphabets2 = new String[alphabets.length];
for (int i=0;i<alphabets.length;i++){
char z = alphabets[i];
alphabets2[i] = z + x;
}
for (String s: alphabets2
) {
System.out.println(s);
}
First of all you would need a Array of alphabet (Easier for you to continue).
I will not give you exact answer, but something to start, so you would learn.
int length = 0;
Arrays here
while(length <= 2) {
think what would be here: hint you put to index (length 0) the all alphabet and move to index 1 and then 2
}

Find the letter that occur most times from user with using tables [duplicate]

This question already has answers here:
Java program to find the character that appears the most number of times in a String?
(8 answers)
Closed 6 years ago.
I got a task from my university today:
Write a program that reads a ( short ) text from the user and prints the so called max letter (most common character in string) , that the letter which the greatest number of occurrences of the given text .
Here it is enough to look at English letters (A- Z) , and not differentiate between uppercase and lowercase letters in the count of the number of occurrences .
For example, if : text = " Ada bada " so should the print show the most common character, this example it would be a.
This is an introductory course, so in this submission we do not need to use the " scanner - class" . We have not gone through this so much.
The program will use the show message input two get the text from user .
Info: The program shall not use while loop ( true / false ) , "return " statement / "break " statement .
I've been struggling with how I can get char values into a table.. am I correct I need to use array to search for most common character? I think I need to use the binarySearch, but that only supports int not char.
I'll be happy for any answers. hint's and solutions. etc.. if you're very kind a full working program, but again please don't use the things I have written down in the "info" section above.
My code:
String text = showInputDialog("Write a short text: ");
//format string to char
String a = text;
char c = a.charAt(4);
/*with this layout it collects number 4 character in the text and print out.
* I could as always go with many char c... but that wouldn't be a clean program * code.. I think I need to make it into a for-loop.. I have only worked with * *for-loops with numbers, not char (letters).. Help? :)
*/
out.print( text + "\n" + c)
//each letter into 1 char, into table
//search for most used letter
Here's the common logic:
split your string into chars
loop over the chars
store the occurrences in a hash, putting the letter as key and occurrences as value
return the highest value in the hash
As how to split string into chars, etc., you can use Google. :)
Here's a similar question.
There's a common program asked to write in schools to calculate the frequency of a letter in a given String. The only thing you gotta do here is find which letter has the maximum frequency. Here's a code that illustrates it:
String s <--- value entered by user
char max_alpha=' '; int max_freq=0, ct=0;
char c;
for(int i=0;i<s.length();i++){
c=s.charAt(i);
if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){
for(int j=0;j<s.length();j++){
if(s.charAt(j)==c)
ct++;
} //for j
}
if(ct>max_freq){
max_freq=ct;
max_alpha=c;
}
ct=0;
s=s.replace(c,'*');
}
System.out.println("Letter appearing maximum times is "+max_alpha);
System.out.println(max_alpha+" appears "+max_freq+" times");
NOTE: This program presumes that all characters in the string are in the same case, i.e., uppercase or lowercase. You can convert the string to a particular case just after getting the input.
I guess this is not a good assigment, if you are unsure about how to start. I wish you for having better teachers!
So you have a text, as:
String text = showInputDialog("Write a short text: ");
The next thing is to have a loop which goes trough each letter of this text, and gets each char of it:
for (int i=0;i<text.length();i++) {
char c=text.charAt(i);
}
Then comes the calculation. The easiest thing is to use a hashMap. I am unsure if this is a good topic for a beginners course, so I guess a more beginner friendly solution would be a better fit.
Make an array of integers - this is the "table" you are referring to.
Each item in the array will correspond to the occurrance of one letter, e.g. histogram[0] will count how many "A", histogram[1] will count how many "B" you have found.
int[] histogram = new int[26]; // assume English alphabet only
for (int i=0;i<histogram.length;i++) {
histogram[i]=0;
}
for (int i=0;i<text.length();i++) {
char c=Character.toUppercase(text.charAt(i));
if ((c>=65) && (c<=90)) {
// it is a letter, histogram[0] contains occurrences of "A", etc.
histogram[c-65]=histogram[c-65]+1;
}
}
Then finally find the biggest occurrence with a for loop...
int candidate=0;
int max=0;
for (int i=0;i<histogram.length;i++) {
if (histogram[i]>max) {
// this has higher occurrence than our previous candidate
max=histogram[i];
candidate=i; // this is the index of char, i.e. 0 if A has the max occurrence
}
}
And print the result:
System.out.println(Character.toString((char)(candidate+65));
Note how messy this all comes as we use ASCII codes, and only letters... Not to mention that this solution does not work at all for non-English texts.
If you have the power of generics and hashmaps, and know some more string functions, this mess can be simplified as:
String text = showInputDialog("Write a short text: ");
Map<Char,Integer> histogram=new HashMap<Char,Integer>();
for (int i=0;i<text.length();i++) {
char c=text.toUppercase().charAt(i));
if (histogram.containsKey(c)) {
// we know this letter, increment its occurrence
int occurrence=histogram.get(c);
histogram.put(c,occurrence+1);
}
else {
// we dunno this letter yet, it is the first occurrence
histogram.put(c,1);
}
}
char candidate=' ';
int max=0;
for (Char c:histogram.keySet()) {
if (histogram.get(c)>max) {
// this has higher occurrence than our previous candidate
max=histogram.get(c);
candidate=c; // this is the char itself
}
}
System.out.println(c);
small print: i didn't run this code but it shall be ok.

Categories