Java int array and char array implementation: why does this work? - java

I am working on the Kattis problem "abc" in a programming seminar class. The question asks you to input three ints between 0 and 100, and have them match the pattern of another group of three char inputs with the case: A < B < C. Here 'A' will be int with least value, 'B' will be second greatest value, etc. I determined my logic but was unsure how to match values to char. Then a fellow student gave me help with the last line but I didn't get a chance to ask about how it worked. Code I have is as follows:
public class ABC {
public static void main(String[] args) {
var scanner = new Scanner(System.in);
int[] num = new int[3];
for (int i=0; i<num.length; i++) {
num[i] = scanner.nextInt();
}
Arrays.sort(num);
char[] chArr = scanner.next().toCharArray();
for (int i=0; i<chArr.length; i++) {
System.out.println(num[chArr[i] - 'A']); //How does num[chArr[i] - 'A'] work?
}
}
}
Input:
1 2 3
C A B
Output:
3 1 2
So, my question is: How does the expression in the println at the end work? I'm a noob to posting on SO, so any suggestions would be gratefully accepted.

A char in C is literally just an 8-bit integer. It tends to be used to represent ASCII characters, but in code it's an integer. Or in other words, char and uint8 are essentially the same type (in fact, one is an alias for the other in most implementations).
This relationship persists, in some form, into Java. A char is fundamentally an integer that presents itself as a character. Thus, you can do integer arithmetic with characters.
To examine num[chArr[i] - 'A']:
chArr[i] retrieves the character at index i of chArr, an array of chars. Say this is 'C'.
Note that the ASCII value of 'C' is 67.
Note that the ASCII value of 'A' is 65.
67 - 65 = 2. So, 'C' is the 3rd letter of the alphabet, meaning it corresponds to index 2 of num.
Retrieve the value at index 2 of num, and print it.

It's quite easy to understand:
Example :
char a = 'a';
char b = 'b';
// zero = 0 a this point
int zero = a - 'a';
// one = 1; and so on
int one = b - 'b';
Now in your case:
// is equivalent to whatever you enter and the difference of 'A'.
num[chArr[i] - 'A']
But if you enter something whose difference with A is more than the size of nums you are going to get an Array out bounds exception.

Related

How to count the remaining uppercase letter T for the letter occurrences counter?

I need some guidance from the code I have here, which counts the alphabet letter occurrences from a sentence.
public static void main(String[] args) {
int wordCount = 0;
String word = "The quick brown fox jumps over the lazy dog near the bank of the river";
for (char letter = 'a'; letter <= 'z'; letter++) {
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == letter) {
wordCount++;
}
}
if (wordCount > 0) {
System.out.print(letter + "=" + wordCount + ", ");
wordCount = 0;
}
}
}
Output:
a=3, b=2, c=1, d=1, e=7, f=2, g=1, h=4, i=2, j=1, k=2, l=1, m=1, n=3, o=5, p=1, q=1, r=5, s=1, t=3, u=2, v=2, w=1, x=1, y=1, z=1,
My issue here is that my program doesn't seem to count the uppercase letter T at the start of my sentence; thus, the result of the occurrences of letter t lacks one more (since my expected output for the occurrences of t is 4, but it resulted in only 3)(This code is a little bit simple, but I'm a bit baffled in terms of utilizing loops and arrays.
Should I add another for loop in creating the alphabet letters but this time in an uppercase form and put them in an array?
Your responses and guides would really help me on this code that I am constructing.
Thank you very much, everyone!!!
Well, a T is not a t. Us humans tend to interpret them as (loosely) the same, but to a machine, they aren't.
You have three options here:
You could convert the whole string to lowercase, so T becomes t prior to processing the string. You could use String::toLowerCase for that.
You could also convert each character to lowercase using Character::toLowerCase. This will delegate the conversion to the Character class, which contains many methods to act upon a character.
if (Character.toLowerCase(word.charAt(i)) == letter) {
wordCount++;
}
Another option is to do some arithmetic to convert the uppercase characters to lowercase.
char c = word.charAt(i);
if (c >= 'A' && c <= 'Z') {
c += 32;
}
if (c == letter) {
wordCount++;
}
This works because the difference between 'A' and 'a' is 32.
Note that your code is a little inefficient regarding time-complexity. You have a loop within a loop, so you're iterating 26 times over the whole string.
Another fairly well-known approach is to create an array of 26 positions, one for each letter. For each letter, you increment the value of the array index corresponding to the letter:
// Let's agree that position 0 is for the 'a' and position 25 for the 'z'
int[] frequencies = new int[26];
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
// <<Convert your character to lowercase here>>
// Also check if your character is a Latin letter
int position = c - 'a'; // Now 'a' => 0 and 'z' => 25
frequencies[position]++;
}
Now, the only thing you need to do is loop over the frequencies array and print the quantities.

Problem replacing char in char array with a digit

Given a string, I have to replace all vowels with their respective position in the array. However, my code returns some strange symbols instead of numbers. Where's the problem?
String s = "this is my string";
char p = 1;
char[] formatted = s.toCharArray();
for(int i = 0; i < formatted.length; i++) {
if(formatted[i] == 'a' ||formatted[i] == 'e' ||formatted[i] == 'i'
||formatted[i] == 'o' ||formatted[i] == 'u') {
formatted[i] = p;
}
p++;
}
s = String.valueOf(formatted);
System.out.println(s);
P.S: Numbers are bigger than 10
this is my s t r i n g
012345678910 11 12 13 14
The position of i in string is 14 but 14 is not a character; it's a numeric string. It means that you need to deal with strings instead of characters. Split s using "" as the delimiter, process the resulting array and finally join the array back into a string using "" as the delimiter.
class Main {
public static void main(String[] args) {
String s = "this is my string";
String[] formatted = s.split("");
for (int i = 0; i < formatted.length; i++) {
if (formatted[i].matches("(?i)[aeiou]")) {
formatted[i] = String.valueOf(i);
}
}
s = String.join("", formatted);
System.out.println(s);
}
}
Output:
th2s 5s my str14ng
The regex, (?i)[aeiou] specifies case-insensitive match for one of the vowels where (?i) specifies the case-insensitiveness. Test it here.
The character '1' has a different value from the number 1.
You can change
char p = 1;
to
char p = '1';
and I think that will give you what you want, as long you're not trying to insert more than 9 numbers in your string. Otherwise you'll need to cope with inserting extra digits, which you cannot do into a char-array, because it has a fixed length.
the root of the problem is already in the comments,
in java the types make a difference in memory size and its representation
int x = 1;
and
char y = '1'
are not holding the same value, this is because many numerical representations are related with ascii codes and the value you have to assing to y to get the number 1 printed is HEX 0x31 or DEC 49.
take a look at the ascci table

How can we calculate frequency of characters in a string

I was looking into the solution of the problem.
static void printCharWithFreq(String str)
{
// size of the string 'str'
int n = str.length();
// 'freq[]' implemented as hash table
int[] freq = new int[SIZE];
// accumulate freqeuncy of each character
// in 'str'
for (int i = 0; i < n; i++)
freq[str.charAt(i) - 'a']++;
// traverse 'str' from left to right
for (int i = 0; i < n; i++) {
// if frequency of character str.charAt(i)
// is not equal to 0
if (freq[str.charAt(i) - 'a'] != 0) {
// print the character along with its
// frequency
System.out.print(str.charAt(i));
System.out.print(freq[str.charAt(i) - 'a'] + " ");
// update frequency of str.charAt(i) to
// 0 so that the same character is not
// printed again
freq[str.charAt(i) - 'a'] = 0;
}
}
}
I am not able to understand how
for (int i = 0; i < n; i++)
freq[str.charAt(i) - 'a']++;
is able to calculate the frequency of the elements.
and how is it stored back in to the position.
I am confused with it.
Can anyone please help me with it?
The lowercase ASCII letters are occupying a continuous part of the ASCII table, from index 97 to 122. If your input is composed of lowercase ASCII letters the expression str.charAt(i) - 'a' will evaluate to values from range [0, 25]. a will become 0, b will become 1, c will become 2 and so on.
However this approach fails for non lowercase ASCII characters, e.g. uppercase 'A' letter has value 65, 'A' - 'a' will be 65 - 97 thus attempting to access a negative array index.
It seems to me that you could rewrite your solution in a much simpler way. Unless i'm misunderstanding it then that solution is far more complex than it needs to be.
s.chars().mapToObj(c -> (char) c).collect(Collectors.groupingBy(c -> c, Collectors.counting()));
As for the frequency, characters in Java are backed by ASCII codes. So you can subtract chars from each other to obtain ASCII values. Thanks to #BackSlash for the stream implementation.

How to print a random character from a string?

I have an assignment due and the last part of the assignment asks:
Suppose s is any string. Write a sequence of statements that will print a random character from s.
Here is what I have come up with so far:
for(int j = 0; j < s.length(); j++){
}
int l = ((int)Math.random()*s.length());
char ch = s.charAt(l);
System.out.println(ch);
I think these are the basic concepts I need to learn how to understand/use to write this code successfully. What I am confused on is where these specific lines of code go, for example if the charAt method should come before the loop, etc.
You almost had it already. I think your main issue was this part:
int l = ((int)Math.random()*s.length());
Your (int) cast is misplaced. If you read the javadoc of Math.random() you see that it returns a double value "greater than or equal to 0.0 and less than 1.0". Casting values of this range to int (i.e. simply cutting off all decimal places) will always result in 0, which only prints the first character of the string.
The solution is to first multiply it with the string's length and do the cast afterwards:
int l = (int)(Math.random()*s.length());
If you only want to print one random character, you don't need a loop of any sort, so you can delete that from your code.
See this fiddle for a working example. What you still need to do is think about how to get the input string (hint: maybe read it from System.in).
public static void main (String[] args) throws java.lang.Exception
{
String s = "foobar42";
int l = (int)(Math.random()*s.length());
char ch = s.charAt(l);
System.out.println(ch);
}
And to finally show off in class, you could also have a look at the Random class which could replace the above line with something like
int l = new Random().nextInt(s.length());
and see if you can grasp the difference between those two approaches. Although that is completely irrelevant to your assignment and way out of scope.
You can get a random character by using s.charAt(x), where x is a random number between 0 and the length of the String-1.
The code for this is as follows:
String s = "text string";
Random rand = new Random();
int randomIndex = rand.nextInt(s.length());//returns a random number between 0 and the index of the last character of the string
System.out.println(s.charAt(randomIndex));
When you need to do this several times, you just put it in a loop like this:
String s = "text string";
for(int i = 0; i < 10; i++) { //prints 10 random characters from the String
Random rand = new Random();
int randomIndex = rand.nextInt(s.length());//returns a random number between 0 and the index of the last character of the string
System.out.println(s.charAt(randomIndex));
}
Try this approach:
String s = "hello world";
System.out.println(Character.toString(s.charAt((new Random()).nextInt(s.length()))));
the s.length() returns the size of s;
the (new Random()).nextInt returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive);
the s.charAt returns the character at the position specified
the Character.toString returns the string representation of the specified character
I would do it like this:
System.out.println(s.charAt((int)(Math.random() * s.length())));

How to get numeric position of alphabets in java? [duplicate]

This question already has answers here:
How to map character to numeric position in java?
(7 answers)
Closed 5 years ago.
How to get numeric position of alphabets in java ?
Suppose through command prompt i have entered abc then as a output i need to get 123 how can i get the numeric position of alphabets in java?
Thanks in advance.
String str = "abcdef";
char[] ch = str.toCharArray();
for(char c : ch){
int temp = (int)c;
int temp_integer = 96; //for lower case
if(temp<=122 & temp>=97)
System.out.print(temp-temp_integer);
}
Output:
123456
#Shiki for Capital/UpperCase letters use the following code:
String str = "DEFGHI";
char[] ch = str.toCharArray();
for(char c : ch){
int temp = (int)c;
int temp_integer = 64; //for upper case
if(temp<=90 & temp>=65)
System.out.print(temp-temp_integer);
}
Output:
456789
Another way to do this problem besides using ASCII conversions is the following:
String input = "abc".toLowerCase();
final static String alphabet = "abcdefghijklmnopqrstuvwxyz";
for(int i=0; i < input.length(); i++){
System.out.print(alphabet.indexOf(input.charAt(i))+1);
}
Convert each character to its ASCII code, subtract the ASCII code for "a" and add 1. I'm deliberately leaving the code as an exercise.
This sounds like homework. If so, please tag it as such.
Also, this won't deal with upper case letters, since you didn't state any requirement to handle them, but if you need to then just lowercase the string before you start.
Oh, and this will only deal with the latin "a" through "z" characters without any accents, etc.
char letter;
for(int i=0; i<text.length(); i++)
{
letter = text.charAt(i);
if(letter>='A' && letter<='Z')
System.out.println((int)letter - 'A'+1);
if(letter>='a' && letter<= 'z')
System.out.println((int)letter - 'a'+1);
}
This depends on the alphabet but for the english one, try this:
String input = "abc".toLowerCase(); //note the to lower case in order to treat a and A the same way
for( int i = 0; i < input.length(); ++i) {
int position = input.charAt(i) - 'a' + 1;
}
First you need to write a loop to iterate over the characters in the string. Take a look at the String class which has methods to give you its length and to find the charAt at each index.
For each character, you need to work out its numeric position. Take a look at this question to see how this could be done.
just logic I can suggest take two arrays.
one is Char array
and another is int array.
convert ur input string to char array,get the position of char from char and int array.
dont expect source code here
String word = "blah blah";
for(int i =0;i<word.length;++i)
{
if(Character.isLowerCase(word.charAt(i)){
System.out.print((int)word.charAt(i) - (int)'a'+1);
}
else{
System.out.print((int)word.charAt(i)-(int)'A' +1);
}
}

Categories