I am having issue to understand this code. The goal is to add the sum of all digit from a number until there is only 1 digit recursively
long long superDigit(string n, int k) {
if (n.size() == 1)
return stoi(n);
long long sum = 0;
for (int i = 0 ; i < n.size() ; i++)
sum += (n[i] - '0') * k;
return superDigit(to_string(sum),1);
}
However, i don't understand this line
sum += (n[i] - '0') * k;
n is a string k is an integer what to expect from this kind of multiplication ?
Moreover i tested the operator - on string and i don't get how it works.
Every character has a numerical value. You can find these values on the ASCII Table. The characters 0-9 are placed in a contiguous chunk on the ASCII table, with 0 at 48 and 9 and 57. So, when you do a char minus '0', you get how far away it is from '0' on the ASCII table, effectively converting the character to its corresponding number. '0' - '0' is 0 since they're the same character, '1' - '0' is 1 since 1 is right next to 0 (49 - 48), '2' - '0' is 2 since it's 2 away (50 - 48 = 2), and so on.
Related
I referred a program for time conversion and not able to understand some part of the code. Here's the full program.
#include<iostream>
#include<cstdio>
using namespace std;
int main() {
string s;
cin >> s;
int n = s.length();
int hh, mm, ss;
hh = (s[0] - '0') * 10 + (s[1] - '0');
mm = (s[3] - '0') * 10 + (s[4] - '0');
ss = (s[6] - '0') * 10 + (s[7] - '0');
if (hh < 12 && s[8] == 'P') hh += 12;
if (hh == 12 && s[8] == 'A') hh = 0;
printf("%02d:%02d:%02d\n", hh, mm, ss);
return 0;
}
The part of code i am not able to understand is
hh = (s[0] - '0') * 10 + (s[1] - '0');
mm = (s[3] - '0') * 10 + (s[4] - '0');
ss = (s[6] - '0') * 10 + (s[7] - '0');
Thanks in advance.
If you see e.g. this ASCII table (ASCII being the most common character encoding scheme) you can see that the character '2' has the decimal value 50, and that the character '0' has the decimal value 48.
Considering that a character is just really a small integer, we can use normal arithmetic on them. That means if you do e.g. '2' - '0' that's the same as doing 50 - 48 which results in the decimal value 2.
So to get the decimal value of a character digit, just subtract '0'.
The multiplication with 10 is because we're dealing with the decimal system, where a number such as 21 is the same as 2 * 10 + 1.
It should be noted that the C++ specification explicitly says that all digits have to be encoded in a contiguous range, so it doesn't matter which encoding is used this will always work.
You might see this "trick" being used to get a decimal value for letters as well, but note that the C++ specification doesn't say anything about that. In fact there are encodings where the range of letters is not contiguous and where this will not work. It's only specified to work on digits.
In the ASCCI encoding numbers are encoded sequentially. This is:
'0' has the value 48
'1' has the value 49
'2' has the value 50
etc
Therefor, 'x' - '0' == x from '0' to '9'
For example:
if you have your string 12:23:53 we have:
hh = (s[0] - '0') * 10 + (s[1] - '0');
(s[0] - '0') means '1'-'0' which is equal to 1, but this is the ten, so *10 + (s[1] - '0') which is '2'-'0', so 2. In total 12.
Same thing for the minutes and seconds.
I was looking at the code below and I got the logic but I cannot seem to understand what is the use of '0'.
class Solution
{
public:
string addBinary(string a, string b)
{
string s = "";
int c = 0, i = a.size() - 1, j = b.size() - 1;
while(i >= 0 || j >= 0 || c == 1)
{
c += i >= 0 ? a[i --] - '0' : 0;
c += j >= 0 ? b[j --] - '0': 0;
s = char(c % 2 + '0') + s;
c /= 2;
}
return s;
}
};
The C and C++ standards require that the characters '0'..'9' be contiguous and increasing. So to convert one of those characters to the digit that it represents you subtract '0' and to convert a digit to the character that represents it you add '0'.
C++ requires ([lex.charset]/3) that, in the basic character set, the numerals '0', '1', '2', ..., '9' are encoded as contiguous values. That means that given a numeral character c, you can compute its integral value as the expression c - '0'.
The value '0' represent offset of ascii table for numeric character representation.
To compare two values when one is ascii and another is binary you need to convert to same base representation.
In ASCII code character 0, represented as '0' in C (and many other languages) has the value 48. Also in ASCII the other 9 numerals are contiguous: '0', '1', etc.
A string is composed of characters. So if you subtract '0' to another numeral you get its numeric value.
I'm new in C++ and I have simple problem. I have to change my number (1011) to decimal result. Cmath is included. I try to use pow method but look at my output please:
Code:
char *b = "1011";
int maxPow = 3;
for (int i = 0; i < 3; ++i) {
cout << b[i] * pow(b[i], (maxPow - i) / 1.0) << endl;
}
Output:
5.7648e+006
110592
2401
I try to make it like this:
result = 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0
The problem is with my array? Where? Please, help me if you can.
So, the problem you're running into, is that you are looping over a ascii value and multiplying the ascii value. Try something like int digit = b[i]-'0'; and then substitute where you use b[i] with the variable digit.
subtracting '0' ... means you are subtracting the ascii value of zero from a given character. So subtracting the ascii value of '0' from '0' gives you the numerical value 0, or subtracting ascii '0' from ascii '1', giving you the numerical value 1.
Take a look at - http://www.asciitable.com/index/asciifull.gif to get a better understanding.
Another little demo you can do, is just cout b[i], and you will see the value 48 or 49 printed, as they are the numerical values of ascii 0 and ascii 1, respectively.
So my problem was that I was trying to use a truncation hash function as a collision index increment/decrement... I had to use it as the first main function, and use a more uniform hash function as the second hash function in its place.
My corrected code is below:
// ============================ HASH FUNCTIONS ============================ \\
// Hash function 1 (Base-26)
int Hash_1(char *key2)
{
int index;
index = (int)((key2[0] - 'A' + 1) * pow(26, 3)) + ((key2[1] - 'A' + 1) * pow(26, 2)) + ((key2[2] - 'A' + 1) * 26) + ((key2[3] - 'A' + 1));
return (index % TABLESIZE);
}
// Hash function 2 (Folding)
int Hash_2(char *key2)
{
int index;
index = ((key2[0] - 'A' + 1) * (key2[1] - 'A' + 1)) + ((key2[2] - 'A' + 1) * (key2[3] - 'A' + 1));
return (index % TABLESIZE);
}
// Hash function 3 (Truncation)
int Hash_3(char *key2)
{
int index;
index = ((key2[1] - 'A' + 1) * (key2[2] - 'A' + 1));
return (index % TABLESIZE);
}
// ========================= DOUBLE HASH FUNCTIONS ========================= \\
// Double hash 1 (Linear Probing)
int ProbeDec_1(char *key2)
{
return 1;
}
// Double hash 2 (Middle Squaring)
int ProbeDec_2(char *key2)
{
int index;
index = (int)pow(((key2[1] - 'A' + 1) + (key2[2] - 'A' + 1)), 2);
return (index % TABLESIZE);
}
// Double hash 3 (Division)
int ProbeDec_3(char *key2)
{
int index;
int primeNum = 7;
index = max((key2[3] / primeNum), 1) % primeNum;
return (index % TABLESIZE);
}
You can create a perfect "hash" for 4-letter strings.
There are less than 32 letters in the latin alphabet, there are less than 64 letters in the latin alphabet if you distinguish between upper and lower case letters.
Why mention 32 and 64? Because they are fifth and sixth powers of two.
We can create a 32 bit integer that uniquely represents a 4-letter word (distinguishing between upper and lower letters) as follows:
bits 0 to 5 encode the first letter of the string
bits 6 to 11 encode the second
bits 12 to 17 encode the third
bits 18 to 23 encode the fourth
bits 24 to 31 are set to 0
By encode, I mean something like:
"A" is encoded as 000000
"a" is encoded as 000001
"B" is 000010
"b" is 000011
and so on. We know we can fit all the letters in whatever encoding you want because there are fewer letters than there are available bit arrangements.
You can even encode each letter as key - 'A' + 1, as you seem to prefer.
I would strongly suggest you create a function that takes a character and returns its encoded value. Generally, if you find yourself writing the same piece of code in more than 3 places, you should consider making it a function.
Equally important, since writing hash functions is mostly about bit-fiddling, you should learn how to use the shift operators < and > instead of pow.
You should also learn about integer operations.
What exactly do you thing 1 / (1 - (key2[2] - 'A' + 1)) can possibly return?
None of your functions can be called "hash functions".
If you want to use something like "truncation" or "division" you should first figure out what that means.
I was studying faster I/O methods for programming problems,
I found out this method of using getchar_unlocked() (though risky but still).
I looked around quite a bit but couldn't get how it scanned an integer value
or in other words what do the 4 lines mean and how they work in the scanint() function
defined below
#include<iostream>
#include<cstdio>
#define gc getchar_unlocked
void scanint(int &x)
{
register int c = gc();
x = 0;
for(;(c<48 || c>57);c = gc());
for(;c>47 && c<58;c = gc())
{x = (x<<1) + (x<<3) + c - 48;}
}
int main()
{
int n,k;
scanint(n);
scanint(k);
int cnt=0;
while(n--)
{
int num;
scanint(num);
if(num%k==0)cnt++;
}
printf("%d",cnt);
return 0;
}
The code has hard-coded ASCII values for the chars '0' and '9', so it skips over anything which does not lie in that range (the first for loop in the four lines of interest to you).
Then while it sees characters in the '0' - '9' range it multiplies its running total by 10 (by shifting it left once to double it, then adding that to itself shifted left three times, which is like multiplying by 8) and adds the current char - the code for '0'.
ASCII value of '0' is 48, and each subsequent digit goes one more. i.e. '1'->49, '2'->50... and so on.
A side effect of this is that if you take a character digit, meaning something between '0' and '9', and subtract the ASCII value of '0' from it, then you get the integer value of that digit.
So in the line x = (x<<1) + (x<<3) + c - 48;, the c-48 part is converting the digit character (an ASCII coded character) into a number between 0-9 that refers to that character.
(x<<1)+(x<<3) is the same as x * 10,(For more information, checkout http://en.wikipedia.org/wiki/Multiplication_algorithm#Shift_and_add and How can I multiply and divide using only bit shifting and adding? ) in fact this part of the code is unnecessarily obfuscated. The compiler can optimize multiplication in many different ways to make it as fast as possible, so we don't need to manually implement the bit shifting. It makes for an interesting college level puzzle though.
for(;(c<48 || c>57);c = gc()); This loop will ignore all the characters until it receives one that falls within the '0' to '9' range. So if the user started by typing a space or any other character, it'll simply be ignored.
By the time the code hits for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;} line, the variable c is already initialized to the first digit that the user has typed. This loop leaves the initialization empty so the control flow will dive right into the loop and start computing the number as each character is typed.
The loop will go on as long as the user keeps typing digits, as soon as the user types something other than a digit, the loop will terminate, finalizing the number.
Until the user keeps typing digits, the line x = (x<<1) + (x<<3) + c - 48; will keep getting executed over and over again, with each time c being the character just typed. And x will multiply itself by 10 and add the new digit in.
Let's say the user types 2014. Here's how the values in c and x will progress.
c = '2' #ASCII value 50
x = 2
c = '0' #ASCII value 48
x = 20
c = '1' #ASCII value 49
x = 201
c = '4' #ASCII value 52
x = 2014
HTH.
The line
for(;(c<48 || c>57);c = gc());
reads the characters which are not in between '0' to '9'.
The line
for(;c>47 && c<58;c = gc())
reads the characters between '0' to '9' one by one.
The line
{x = (x<<1) + (x<<3) + c - 48;}
is simply equivalent to
x = 10 * x + c - 48;
A simplified version of this function can be rewritten as:
#define gc getchar_unlocked
int read_int()
{
char c = gc();
while(c<'0' || c>'9')
c = gc();
int ret = 0;
while(c>='0' && c<='9')
{
ret = 10 * ret + c - 48;
c = gc();
}
return ret;
}