C++ programing code counts[s[i] - '0'] ++; - c++

for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]))
counts[s[i] - '0'] ++;
}
what does this code means, any one can able to explain this code " counts[s[i] - '0'] ++;" exact opertion

counts is a ten-element array, which is being used to count how many times each digit appears in s.
Specifically:
s[i] - '0' turns '0' into 0, '1' into 1 etc.
counts[...]++ increments the corresponding element of the array.

Hope this helps.
1) Ascii value of '0' is 48
2) Whenever s[i] is a digit (between 0-9 inclusive)
3) s[i] - '0' evaluates to an index (between 0..9 inclusive);
Example:
Ascii value of '1' is 49
Say s[i] is '1'
then s[i] - '0' is 49-48 = 1
4) counts[s[i]-'0']++ would count the number of times a particular digit has been found in s[i].

The code is counting how many times a digit (1-9) is appearing in string s.
Note. 'i' - '0' is the same as i - 0 if i is a digit.
The reason is that characters '0' -'9' have consecutive ASCII values. So the difference in ASCII value between 'i' and '0' is i;
Now let's say
string s = "1b21cc55";
and
int count[10] is all zeros
in the loop
we check s[i],
s[0] = 1 ---> isdigit(1) = yes ----> count[1-0] += 1 ---> count[1] is 1;
s[1] = b ---> isdigit(b) = no ;
s[2] = 2 ---> isdigit(2) = yes ----> count[2-0] += 1; ---> count[2] is 1;
s[3] = 1 ---> isdigit(1) = yes ----> count[1-0] += 1; ---> count[1] is 2;
and so on ...
At the end count[i] will tell you how many is are in the string.

counts is an array.
s[i] is a character which contains numbers in ASCII. '0', '1',
'2', ...
s[i] - '0' converts them into integer numbers. 1, 2, 3, ...
Above number indicates the index of n'th item in the array --> X
counts[X] ++ increments one the X'th item of the array.

Related

Can Someone explain this Program ? I don't understand it [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
This is the program for converting the ascii sentence to character sentence. But i dont understand the num = num * 10 + (str[i] - '0'); why it us used and why it's needed?
#include <bits/stdc++.h>
using namespace std;
void asciiToSentence(string str, int len)
{
int num = 0;
for (int i = 0; i < len; i++) {
num = num * 10 + (str[i] - '0');
if (num >= 32 && num <= 122) {
char ch = (char)num;
cout << ch;
num = 0;
}
}
}
int main()
{
string str = "973265";
int len = str.length();
asciiToSentence(str, len);
return 0;
}
Firstly, bits/* are not standard headers, you shouldn't be using them otherwise your code may not compile with compilers like MSVC. Refer this.
Now let's come to your query : str[i] - '0' is simply a way to convert char to respective int, i.e. '0' to 0. You can find more discussion on this thread.
What does your code do?
It just keeps on extracting chars from your string (in loop), converting it to int and adding to num after multiplying it by 10. This is basically converting a part of string, say, "97" to an integer 97.
When num comes in range from 32 (' ') to 122 ('Z') (both inclusive), it cast them to char and prints it.
Explanation of Sample Output:
Your code prints a A to console. You will get this result if you can figure out the substrings. Here consider these three - "97" "32" "65". Then "97" will be converted to 97 (as int), then will be cast to char and end up being 'a' ('a' has ASCII value of 97). Similarly "32", will be a space ' ', and "65" will be 'A'.
These substrings didn't come here by magic. Let me explain one for you :
You have str = "973265", num = 0, then the loop begins :
i = 0 -> str[i] = '9' -> str[i] - '0' = 9 -> num = 0*10 + 9 = 9 -> is num in range [32, 122]? false -> go to next iteration.
i = 1 -> str[i] = '7' -> str[i] - '7' = 7 -> num = 9*10 + 7 = 97 -> is num in range [32, 122]? true -> ch = (char)num = (char)97 = 'A' -> print ch, i.e. 'A' -> num = 0 -> go to next iteration.
Pro Tip: Use your debugger, set breakpoints, watch variables and step through your code for better understanding.
Note that: When I wrote ____ - I meant ____ like this ____.
"convert" -- conversion -- '0' <-> 0 or "12" <-> 12
"cast" -- casting -- '0' <-> 48 (assuming your compiler is using ASCII).
In http://www.asciitable.com/, you can see that 0 has ascii value of 48, 1 is 49, 2 is 50 and so on.
So str[i] - '0' will give you 0 if str[i] == '0', 1 if str[i] == '1' and so on. This is a simple trick to convert numeric char into its mathematical value.
Let's call str[i] - '0' as x, so the line you don't understand becomes num = num * 10 + x. What this does is, take the original num (say it was 32), add a 0 behind it (so it becomes 320), then add x (if x is 7, num becomes 327).
So overall, this code is basically a function that converts a number string into integer type.

my run-length encoding doesn't work with big numbers

I have a assingment were I need to code and decode txt files, for example: hello how are you? has to be coded as hel2o how are you? and aaaaaaaaaajkle as a10jkle.
while ( ! invoer.eof ( ) ) {
if (kar >= '0' && kar <= '9') {
counter = kar-48;
while (counter > 1){
uitvoer.put(vorigeKar);
counter--;
}
}else if (kar == '/'){
kar = invoer.get();
uitvoer.put(kar);
}else{
uitvoer.put(kar);
}
vorigeKar = kar;
kar = invoer.get ( );
}
but the problem I have is if need to decode a12bhr, the answer is aaaaaaaaaaaabhr but I can't seem to get the 12 as number without problems, I also can't use any strings or array's.
c++
I believe that you are making following mistake: imagine you give a32, then you read the character a and save it as vorigeKar (previous character, I am , Flemish so I understand Dutch :-) ).
Then you read 3, you understand that it is a number and you repeat vorigeKar three times, which leads to aaa. Then you read 2 and repeat vorigeKar two times, leading to aaaaa (five times, five equals 3 + 2).
You need to learn how to keep on reading numeric characters, and translate them into complete numbers (like 32, or 12 in your case).
Like #Dominique said in his answers, You're doing it wrong.
Let me tell you my logic, you can try it.
Pesudo Code + Logic:
Store word as a char array or string, so that it'll be easy to print at last
Loop{
Read - a //check if it's number by subtracting from '0'
Read - 1 //check if number = true. Store it in int res[] = res*10 + 1
//Also store the previous index in an index array(ie) index of char 'a' if you encounter a number first time.
Read - 2 //check if number = true. Store it in res = res*10 + 2
Read - b , h and so on till "space" character
If you encounter another number, then store it's previous character's index in index array and then store the number in a res[] array.
Now using index array you can get the index of your repeating character to be printed and print it for it's corresponding times which we have stored in the result array.
This goes for the second, third...etc:- numbers in your word till the end of the word
}
First, even though you say you can't use strings, you still need to know the basic principle behind how to turn a stream of digit characters into an integer.
Assuming the number is positive, here is a simple function that turns a series of digits into a number:
#include <iostream>
#include <cctype>
int runningTotal(char ch, int lastNum)
{
return lastNum * 10 + (ch -'0');
}
int main()
{
// As a test
char s[] = "a123b23cd1/";
int totalNumber = 0;
for (size_t i = 0; s[i] != '/'; ++i)
{
char digit = s[i]; // This is the character "read from the file"
if ( isdigit( digit) )
totalNumber = runningTotal(digit, totalNumber);
else
{
if ( totalNumber > 0 )
std::cout << totalNumber << "\n";
totalNumber = 0;
}
}
std::cout << totalNumber;
}
Output:
123
23
1
So what was done? The character array is the "file". I then loop for each character, building up the number. The runningTotal is a function that builds the integer from each digit character encountered. When a non-digit is found, we output that number and start the total from 0 again.
The code does not save the letter to "multiply" -- I leave that to you as homework. But the code above illustrates how to take digits and create the number from them. For using a file, you would simply replace the for loop with the reading of each character from the file.

Using getchar_unlocked()

I recently learnt that using getchar_unlocked() is a faster way of reading input.
I searched on the internet and found the code snippet below:
But I am unable to understand it.
void fast_scanf(int &number)
{
register int ch = getchar_unlocked();
number= 0;
while (ch > 47 && ch < 58) {
number = number * 10 + ch - 48;
ch = getchar_unlocked();
}
}
int main(void)
{
int test_cases;fast_scanf(test_cases);
while (test_cases--)
{
int n;
fast_scanf(n);
int array[n];
for (int i = 0; i < n; i++)
fast_scanf(array[i]);
}
return 0;
}
So, this code takes input for an integer array of size n for a given number of test_cases . I didn't understand anything in the function fast_scanf, like why this line:
while (ch > 47 && ch < 58)
{ number = number * 10 + ch - 48;
why the register is used while declaring ch?
why the getchar_unlocked() is used twice in the function? and so on..
It would be great help if someone elaborates this for me. Thanks in advance!
Okay, since what you are asking needs to be explained clearly, I am writing it here... so I don't jumble it all up inside the comments...
The function: (Edited it a bit to make it look like more C++-standard)
void fast_scanf(int &number)
{
auto ch = getchar_unlocked();
number= 0;
while (ch >= '0' && ch <= '9')
{
number = number * 10 + ch - '0';
ch = getchar_unlocked();
}
}
Here, take up consideration by looking at the ASCII Table first, since you won't understand how the results are coming up if you don't...
1) Here, you have a character ch takes up the input character from the user using getchar_unlocked() (The auto keyword does that automatically for you and is only usable in C++, not C)...
2) You assign the variable number to zero so that the variable can be re-used, note that the variable is a reference so it changes inside your program as well...
3) while (ch >= '0' && ch <= '9')... As pointed out, checks whether the characters is within the numerical ASCII limit, similar to saying that the character has to be greater than or equal to 48 but less than or equal to 57...
4) Here, things are a little bit tricky, Variable number is multiplied with the product of itself and 10 and the real integer value of the character you stored)...
5) In the next line, ch is reassigned so that you don't have to stay in the loop forever, since ch will remain that number forever if the user doesn't type anything... remember a loop goes back to where it was declared after reaching the end, checks if the condition is true, continues if it is true else breaks)...
For example: 456764
Here, ch will first take 4 then the others follow so we go with 4 first...
1) Number will be assigned to zero. While loop checks if the given character is a number or not, if it is continues the loop else breaks it...
2) Multiplication of 0 with 10 will be zero... and adding it with difference 52 (that is '4') with 48 (that is '0') gives you 4 (the real numerical value, not the char '4')...
So the variable number now is 4...
And the same continues with the others as well... See...
number = number * 10 + '5' - '0'
number = 4 * 10 + 53 - 48
number = 40 + 5
number = 45... etc, etc. for other numbers...

count consecutive 1's in binary

I am writing code in Hackerrank. And recently the problem said, convert decimal to base 2 and then count the max consecutive 1's in the binary number. And first I come with following solution. It works fine. But I do not understand the counting part of it, even though I wrote it.
The code is
int main(){
int n,ind=0, count=0, mmax=0;
char bin[100];
cin >> n;
while(n){
if(n%2==0) {
bin[ind]='0';
n = n / 2;
ind = ind + 1;
}
else if(n%2==1) {
bin[ind]='1';
n = n / 2;
ind = ind + 1;
}
}
for(int i=0; i<=(ind-1); i++){
if(bin[i] == '1' && bin[i+1] == '1'){
count++;
if(mmax < count)
mmax = count;
}
else
count=0;
}
cout << mmax + 1 << endl;
return 0;
}
In the above code, I guess that variable mmax will give me the max consecutive number of 1's but it gives me value that has (max consecutive - 1), So I just wrote like that and submitted the code. But I am curious about. why it is working that way. I am little bit of confused the way that code works like this.
Thanks
Lets say you have this binary sequence:
11110
Your code will compare starting from the first and second:
|11|110 1 && 1 -> max = 1
1|11|10 1 && 1 -> max = 2
11|11|0 1 && 1 -> max = 3
111|10| 1 && 0 -> max = 3
you can see, that although there are 4 1's you only do 3 comparisons, so your max will always be -1 of the actual max. You can fix this by adding mmax += 1 after your for loop.
Just a little bit of trace using small example will show why.
First, lets say there is only 1 '1' in your array.
Since you require both the current position and your next position to be '1', you will always get 0 for this case.
Let's say I have "11111". At the first '1', since next position is also '1', you increment count once. This repeats until 4th '1' and you increment your count 4 times in total so far. When you reach 5th '1', your next position is not '1', thus your count stops at 4.
In general, your method is like counting gaps between fingers, given 5 fingers, you get 4 gaps.
Side note: your code will fail for the case when there is no '1' in your array.

Caesar cipher in C++

To start off, I'm four weeks into a C++ course and I don't even know loops yet, so please speak baby talk?
Okay, so I'm supposed to read a twelve character string (plus NULL makes thirteen) from a file, and then shift the letters backwards three, and then print my results to screen and file. I'm okay with everything except the shifting letters. I don't want to write miles of code to take each character individually, subtract three, and re-assemble the string, but I'm not sure how to work with the whole string at once. Can someone recommend a really simple method of doing this?
If you are dealing with simple letters (A to Z or a to z), then you can assume that the internals codes are linear.
Letters are coded as numbers, between 0 and 127. A is coded as 65, B as 66, C as 67, Z as 90.
In order to shift letters, you just have to change the internal letter code as if it were a number, so basically just substracting 3 from the character. Beware of edge cases though, because substracting 3 to 'A' will give you '>' (code 62) and not 'X' (code 88). You can deal with them using "if" statements or the modulo operator ("%").
Here is an ASCII characters table to help you
Once you've loaded your string in, you can use the modulous operator to rotate while keeping within the confines of A-Z space.
I'd keep track of whether the letter was a capital to start with:
bool isCaps = ( letter >= 'A' ) && ( letter <= 'Z' );
if( isCaps )
letter -= 'A'-'a';
and then just do the cipher shift like this:
int shift = -3;
letter -= 'a'; // to make it a number from 0-25
letter = ( letter + shift + 26 ) % 26;
// add 26 in case the shift is negative
letter += 'a'; // back to ascii code
finally finish off with
if( isCaps )
letter += 'A'-'a';
so, putting all this together we get:
char *mystring; // ciphertext
int shift = -3; // ciphershift
for( char *letter = mystring; letter; ++letter )
{
bool isCaps = ( *letter >= 'A' ) && ( *letter <= 'Z' );
if( isCaps )
*letter -= 'A'-'a';
letter -= 'a';
letter = ( letter + shift + 26 ) % 26;
letter += 'a';
if( isCaps )
letter += 'A'-'a';
}
You're going to have to learn loops. They will allow you to repeat some code over the characters of a string, which is exactly what you need here. You'll keep an integer variable that will be your index into the string, and inside the loop do your letter-shifting on the character at that index and increment the index variable by one until you reach NULL.
Edit: If you're not expected to know about loops yet in your course, maybe they want you to do this:
string[0] -= 3; // this is short for "string[0] = string[0] - 3;"
string[1] -= 3;
string[2] -= 3;
...
It will only result in 12 lines of code rather than miles. You don't have to "reassemble" the string this way, you can just edit each character in-place. Then I bet after making you do that, they'll show you the fast way of doing it using loops.
Iterate over the characters with a for loop. And do what you want with the char*. Then put the new char back.
for(int i=0; i<12; i++){
string[i] = string[i] - 3;
}
Where string is your character array (string). There is a bit more involved if you want to make it periodic (I.E. have A wrap round to Z, but the above code should help you get started)
I'm a little unclear what you mean by "shift the letters backwards 3"?
Does that mean D ==> A?
If so, here's a simple loop.
(I didn't do reading from the file, or writing to the file... Thats your part)
#include <string.h>
int main(void)
{
char input[13] = "ABCDEFGHIJKL";
int i;
int len = strlen(input);
for(i=0; i<len; ++i)
{
input[i] = input[i]-3;
}
printf("%s", input); // OUTPUT is: ">?#ABCDEFGHI"
}