C++ Pointer Arithmetic and Concatenation Question - c++

How does this code concatenate the data from the string buffer? What is the * 10 doing? I know that by subtracting '0' you are subtracting the ASCII so turn into an integer.
char *buf; // assume that buf is assigned a value such as 01234567891234567
long key_num = 0;
someFunction(&key_num);
...
void someFunction(long *key_num) {
for (int i = 0; i < 18; i++)
*key_num = *key_num * 10 + (buf[i] - '0')
}
(Copied from my memory of code that I am working on recently)

It's basically an atoi-type (or atol-type) function for creating an integral value from a string. Consider the string "123".
Before starting, key_num is set to zero.
On the first iteration, that's multiplied by 10 to give you 0, then it has the character value '1' added and '0' subtracted, effectively adding 1 to give 1.
On the second iteration, that's multiplied by 10 to give you 10, then it has the character value '2' added and '0' subtracted, effectively adding 2 to give 12.
On the third iteration, that's multiplied by 10 to give you 120, then it has the character value '3' added and '0' subtracted, effectively adding 3 to give 123.
Voila! There you have it, 123.
If you change the code to look like:
#include <iostream>
char buf[] = "012345678901234567";
void someFunction(long long *key_num) {
std::cout << *key_num << std::endl;
for (int i = 0; i < 18; i++) {
*key_num = *key_num * 10 + (buf[i] - '0');
std::cout << *key_num << std::endl;
}
}
int main (void) {
long long x = 0;
someFunction (&x);
return 0;
}
then you should see it in action (I had to change your value from the 17-character array you provided in your comment to an 18-character one, otherwise you'd get some problems when you tried to use the character beyond the end; I also had to change to a long long because my longs weren't big enough):
0
0
1
12
123
1234
12345
123456
1234567
12345678
123456789
1234567890
12345678901
123456789012
1234567890123
12345678901234
123456789012345
1234567890123456
12345678901234567

As a shorter example with the number 1234, that can be thought of as:
1000 * 1 + 100 * 2 + 10 * 3 + 4
Or:
10 * (10 * (10 * 1 + 2) + 3) + 4
The first time through the loop, *key_num would be 1. The second time it is multiplied by 10 and 2 added (ie 12), the third time multiplied by 10 and 3 added (ie 123), the fourth time multiplied by 10 and 4 added (ie 1234).

It just multiples the current long value (*key_num) by 10, adds the digit value, then stores the result again.
EDIT: It's not bit-shifting anything. It's just math. You can imagine it as shifting decimal digits, but it's binary internally.
key_num = 0 (0)
key_num = key_num * 10 + ('0' - '0') (0)
key_num = key_num * 10 + ('1' - '0') (1)
key_num = key_num * 10 + ('2' - '0') (12)

Related

919B | nth Numbers having digit sum as 10 | Codeforces

Here is the link to the question. Essentially, it asks to find the kth number having digit sum as 10. I have tried multiple solutions and also looked upon solutions online. Specifically this one (also shared below). The one with constant time talks about outliers in Arithmetic Progression and uses it to find the nth number having sum as 10. Obviously, the code is incorrect as it fails for test cases when k=1000 etc.
#include <bits/stdc++.h>
using namespace std;
int findNth(int n)
{
int nthElement = 19 + (n - 1) * 9;
int outliersCount = (int)log10(nthElement) - 1;
// find the nth perfect number
nthElement += 9 * outliersCount;
return nthElement;
}
int main()
{
cout << findNth(5) << endl;
return 0;
}
Eventually, I ended up writing combination of Arithmetic Progression + brute force as below
#include <bits/stdc++.h>
using namespace std;
#define ll unsigned long long
int main() {
int n;
cin >> n;
int count = 0;
ll i = 19;
for (; ; i += 9) {
int curr = i;
int localSum = 0;
while (curr) {
localSum += curr%10;
curr /= 10;
}
if (localSum == 10) {
count += 1;
}
if (count == n) {
break;
}
}
cout << i << endl;
return 0;
}
I am wondering, if there is no constant time or better algorithm that does not require me to calculate the sum, but my algorithm always hops in a way that I have number whose digit sum is 10?
Here is a Python solution that you can translate into C++.
cached_count_ds_l = {}
def count_digit_sum_length (s, l):
k = (s, l)
if k not in cached_count_ds_l:
if l < 2:
if s == 0:
return 1
elif l == 1 and s < 10:
return 1
else:
return 0
else:
ans = 0
for i in range(min(10, s+1)):
ans += count_digit_sum_length(s-i, l-1)
cached_count_ds_l[k] = ans
return cached_count_ds_l[k]
def nth_of_sum (s, n):
l = 0
while count_digit_sum_length(s, l) < n:
l += 1
digits = []
while 0 < l:
for i in range(10):
if count_digit_sum_length(s-i, l-1) < n:
n -= count_digit_sum_length(s-i, l-1)
else:
digits.append(str(i))
s -= i
l -= 1
break
return int("".join(digits))
print(nth_of_sum(10, 1000))
The idea is to use dynamic programming to find how many numbers there are of a given maximum length with a given digit sum. And then to use that to cross off whole blocks of numbers on the way to finding the right one.
The main logic goes like this:
0 numbers of length 0 sum to 10
- need longer
0 numbers of length 1 sum to 10
- need longer
9 numbers of length 2 sum to 10
- need longer
63 numbers of length 3 sum to 10
- need longer
282 numbers of length 4 sum to 10
- need longer
996 numbers of length 5 sum to 10
- need longer
2997 numbers of length 6 sum to 10
- answer has length 6
Looking for 1000th number of length 6 that sums to 10
- 996 with a leading 0 sum to 10
- Need the 4th past 99999
- 715 with a leading 1 sum to 10
- Have a leading 1
Looking for 4th number of length 5 that sums to 9
- 495 with a leading 0 sum to 9
- Have a leading 10
Looking for 4th number of length 4 that sums to 9
- 220 with a leading 0 sum to 9
- Have a leading 100
Looking for 4th number of length 3 that sums to 9
- 55 with a leading 0 sum to 9
- Have a leading 1000
Looking for 4th number of length 2 that sums to 9
- 1 with a leading 0 sum to 9
- Need the 3rd past 9
- 1 with a leading 1 sum to 9
- Need the 2nd past 19
- 1 with a leading 2 sum to 9
- Need the 1st past 29
- 1 with a leading 3 sum to 9
- Have a leading 10003
Looking for 1st number of length 1 that sums to 6
- 0 with a leading 0 sum to 6
- Need the 1st past 0
- 0 with a leading 1 sum to 6
- Need the 1st past 1
- 0 with a leading 2 sum to 6
- Need the 1st past 2
- 0 with a leading 3 sum to 6
- Need the 1st past 3
- 0 with a leading 4 sum to 6
- Need the 1st past 4
- 0 with a leading 5 sum to 6
- Need the 1st past 5
- 1 with a leading 6 sum to 6
- Have a leading 100036
And it finishes in a fraction of a second.
Incidentally the million'th is 20111220000010, the billionth is 10111000000002000000010000002100, and the trillionth is 10000000100000100000100000000000001000000000000100000000010110001000.

Using bit wise operators

Am working on a C++ app in Windows platform. There's a unsigned char pointer that get's bytes in decimal format.
unsigned char array[160];
This will have values like this,
array[0] = 0
array[1] = 0
array[2] = 176
array[3] = 52
array[4] = 0
array[5] = 0
array[6] = 223
array[7] = 78
array[8] = 0
array[9] = 0
array[10] = 123
array[11] = 39
array[12] = 0
array[13] = 0
array[14] = 172
array[15] = 51
.......
........
.........
and so forth...
I need to take each block of 4 bytes and then calculate its decimal value.
So for eg., for the 1st 4 bytes the combined hex value is B034. Now i need to convert this to decimal and divide by 1000.
As you see, for each 4 byte block the 1st 2 bytes are always 0. So i can ignore those and then take the last 2 bytes of that block. So from above example, it's 176 & 52.
There're many ways of doing this, but i want to do it via using bit wise operators.
Below is what i tried, but it's not working. Basically am ignoring the 1st 2 bytes of every 4 byte block.
int index = 0
for (int i = 0 ; i <= 160; i++) {
index++;
index++;
float Val = ((Array[index]<<8)+Array[index+1])/1000.0f;
index++;
}
Since you're processing the array four-by-four, I recommend that you increment i by 4 in the for loop. You can also avoid confusion after dropping the unnecessary index variable - you have i in the loop and can use it directly, no?
Another thing: Prefer bitwise OR over arithmetic addition when you're trying to "concatenate" numbers, although their outcome is identical.
for (int i = 0 ; i <= 160; i += 4) {
float val = ((array[i + 2] << 8) | array[i + 3]) / 1000.0f;
}
First of all, i <= 160 is one iteration too many.
Second, your incrementation is wrong; for index, you have
Iteration 1:
1, 2, 3
And you're combining 2 and 3 - this is correct.
Iteration 2:
4, 5, 6
And you're combining 5 and 6 - should be 6 and 7.
Iteration 3:
7, 8, 9
And you're combining 8 and 9 - should be 10 and 11.
You need to increment four times per iteration, not three.
But I think it's simpler to start looping at the first index you're interested in - 2 - and increment by 4 (the "stride") directly:
for (int i = 2; i < 160; i += 4) {
float Val = ((Array[i]<<8)+Array[i+1])/1000.0f;
}

atoi implementation in C++

Given this implementation of atoi in C++
// A simple atoi() function
int myAtoi(char *str)
{
int res = 0; // Initialize result
// Iterate through all characters of input string and update result
for (int i = 0; str[i] != '\0'; ++i)
res = res*10 + str[i] - '0';
// return result.
return res;
}
// Driver program to test above function
int main()
{
char str[] = "89789";
int val = myAtoi(str);
printf ("%d ", val);
return 0;
}
How exactly does the line
res = res*10 + str[i] - '0';
Change a string of digits into int values? (I'm fairly rusty with C++ to be honest. )
The standard requires that the digits are consecutive in the character set. That means you can use:
str[i] - '0'
To translate the character's value into its equivalent numerical value.
The res * 10 part is to shuffle left the digits in the running total to make room for the new digit you're inserting.
For example, if you were to pass "123" to this function, res would be 1 after the first loop iteration, then 12, and finally 123.
Each step that line does two things:
Shifts all digit left by a place in decimal
Places the current digit at the ones place
The part str[i] - '0' takes the ASCII character of the corresponding digit which are sequentially "0123456789" and subtracts the code for '0' from the current character. This leaves a number in the range 0..9 as to which digit is in that place in the string.
So when looking at your example case the following would happen:
i = 0 → str[i] = '8': res = 0 * 10 + 8 = 8
i = 1 → str[i] = '9': res = 8 * 10 + 9 = 89
i = 2 → str[i] = '7': res = 89 * 10 + 7 = 897
i = 3 → str[i] = '8': res = 897 * 10 + 8 = 8978
i = 4 → str[i] = '9': res = 8978 * 10 + 9 = 89789
And there's your result.
The digits 0123456789are sequential in ASCII.
The char datatype (and literal chars like '0') are integral numbers. In this case, '0' is equivalent to 48. Subtracting this offset will give you the digit in numerical form.
Lets take an example:
str = "234";
to convert it into int, basic idea is to process each character of string like this:
res = 2*100 + 3*10 + 4
or
res = 0
step1: res = 0*10 + 2 = 0 + 2 = 2
step2: res = res*10 + 3 = 20 + 3 = 23
step3: res = res*10 + 4 = 230 + 4 = 234
now since each letter in "234" is actually a character, not int
and has ASCII value associated with it
ASCII of '2' = 50
ASCII of '3' = 51
ASCII of '4' = 52
ASCII of '0' = 48
refer: http://www.asciitable.com/
if i had done this:
res = 0;
res = res*10 + str[0] = 0 + 50 = 50
res = res*10 + str[1] = 500 + 51 = 551
res = res*10 + str[2] = 5510 + 52 = 5562
then i would have obtained 5562, which we don't want.
remember: on using characters in arithmetic expressions, their ASCII value is used up (automatic typecasting of char -> int). Hence we need to convert character '2'(50) to int 2, which we can accomplish like this:
'2' - '0' = 50 - 48 = 2
Lets solve it again with this correction:
res = 0
res = res*10 + (str[0] - '0') = 0 + (50 - 48) = 0 + 2 = 2
res = res*10 + (str[1] - '0') = 20 + (51 - 48) = 20 + 3 = 23
res = res*10 + (str[2] - '0') = 230 + (52 - 48) = 230 + 4 = 234
234 is the required answer

How to find the number of sequences of zeros and ones without "111" [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a problem:
I have a N (N <= 40). N is a length of sequence of zeroz and ones. How to find the number of sequences of zeros and ones in which there are no three "1" together?
Example:
N = 3, answer = 7
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
Here's a solution using a recursive function :
(PHP code here, but it's really simple)
$seq = '';
function tree ($node, $flag, $seq)
{
if ($flag == 3) { return 0; }
if ($node == 0) { echo $seq, ' '; return 0;}
$seq1 = $seq.'1';
$seq2 = $seq.'0';
tree($node-1, $flag+1, $seq1);
tree($node-1, 0, $seq2);
}
tree(8, 0, $seq);
I use a tree to go through all the possible sequences, and a flag to check how many 1 in a row.
If there is two 1 in a row, then the flag reaches 3, and the function is stopped for this branch.
If we reach a leaf of the tree (ie. $node = 0), then the sequence is displayed, and the function ends.
Else, the function explores the two sub-trees starting from the current node.
void tree ( int node, int flag, std::string seq)
{
std::string seq1 = seq;
std::string seq2 = seq;
if(flag ==3) { return; }
if(node ==0) { printf("%s\n",seq.c_str()); return;}
seq1 += '1';
seq2 += '0';
tree(node-1, flag+1, seq1);
tree(node-1, 0, seq2);
}
You can write a grammar for the (non-empty) strings of this language. It's designed so that each string appears exactly once.
S := 0 | 1 | 11 | 10 | 110 | 0S | 10S | 110S
Let a_i be the total number of strings of length i in S.
First, look at the number of strings of length 1 on both sides of the grammar rule. There's a_1 in S by definition which deals with the left-hand-side.
a_1 = 2
For a_2, on the right-hand-side we immediately get two strings of length 2 (11 and 10), plus another two from the 0S rule (00 and 01). This gives us:
a_2 = 2 + a_1 = 4
Similarly, for a_3, we get:
a_3 = 1 + a_2 + a_1 = 7
(So far so good, we've got the right solution 7 for the case where the strings are length three).
For i > 3, consider the number of strings of length i on both sides.
a_i = a_{i-1} + a_{i-2} + a_{i-3}
Now we've got a recurrence we can use. A quick check for a_4...
a_4 = a_1 + a_2 + a_3 = 2 + 4 + 7 = 13.
There's 16 strings of length 4 and three containing 111: 1110, 0111, 1111. So 13 looks right!
Here's some code in Python for the general case, using this recurrence.
def strings_without_111(n):
if n == 0: return 1
a = [2, 4, 7]
for _ in xrange(n - 1):
a = [a[1], a[2], a[0] + a[1] + a[2]]
return a[0]
This is a dp problem. I will explain the solution in a way so that it is easy to modify it to count the number of sequences having no sequence a0a1a2 in them(where ai is arbitrary binary value).
I will use 4 helper variables each counting the sequence up to a given length that are valid and end with 00, 01, 10, and 11 respectively. Name those c00, c01, c10, c11. It is pretty obvious that for length N = 2, those numbers are all 1:
int c00 = 1;
int c01 = 1;
int c10 = 1;
int c11 = 1;
Now assuming we have counted the sequences up to a given length k we count the sequences in the four groups for length k + 1 in the following manner:
int new_c00 = c10 + c00;
int new_c01 = c10 + c00;
int new_c10 = c01 + c11;
int new_c11 = c01;
The logic above is pretty simple - if we append a 0 to either a sequence of length k ending at 0 0 or ending at 1 0 we end up with a new sequence of length k + 1 and ending with 0 0 and so on for the other equations above.
Note that c11 is not added to the number of sequences ending with 1 1 and with length k + 1. That is because if we append 1 to a sequence ending with 1 1 we will end up with an invalid sequence( ending at 1 1 1).
Here is a complete solution for your case:
int c00 = 1;
int c01 = 1;
int c10 = 1;
int c11 = 1;
for (int i = 0; i < n - 2; ++i) {
int new_c00 = c10 + c00;
int new_c01 = c10 + c00;
int new_c10 = c01 + c11;
int new_c11 = c01;
c00 = new_c00;
c01 = new_c01;
c10 = new_c10;
c11 = new_c11;
}
// total valid sequences of length n
int result = c00 + c01 + c10 + c11;
cout << result << endl;
Also you will have to take special care for the case when N < 2, because the above solution does not handle that correctly.
To find a number of all possible sequences for N bits are easy. It is 2^N.
To find all sequences contains 111 a bit harder.
Assume N=3 then Count = 1
111
Assume N=4 then Count = 3
0111
1110
1111
Assume N=5 then Count = 8
11100
11101
11110
11111
01110
01111
00111
10111
If you write simple simulation program it yields 1 3 8 20 47 107 ...
Subtract 2^n - count(n) = 2 4 7 13 24 44 81 149...
Google it and it gives OEIS sequence, known as tribonacci numbers. Solved by simple recurrent equation:
a(n) = a(n - 1) + a(n - 2) + a(n - 3)

Multiple of 5 checking

How is this code working for multiple of 5
bool isMultipleof5(int n)
{
/* If n is a multiple of 5 then we make sure that last
digit of n is 0 */
if ( (n&1) == 1 )
n <<= 1;
float x = n;
x = ( (int)(x*0.1) )*10;
/* If last digit of n is 0 then n will be equal to (int)x */
if ( (int)x == n )
return true;
return false;
}
It first makes n divisable by 2.
Next, it checks if it is divisable by 10 by multiplying with 0.1 and again with 10. The idea that if it is divisable by 10, you will get back to the original, and only then.
So, if the modifies n is divisable by 10 - it is certainly divisable by 5 as well, and since modified n is always divisable by 2, if it is divisable by 5 it will be divisable by 10, and the algorithm works.
NOTE: This is very unsuggested and especially might break with large values due to floating point precision issues. using the % operator should be prefered: return (n % 5) == 0
This is how the code works with some examples.
if ( (n&1) == 1 ) //Checks if the number is odd
n <<= 1; //Multiplies the number by 2 if odd
x = ( (int)(x * 0.1) //Divides the number 10 then truncates any decimal places
* 10 ) //Multiplies it back by 10
if ( (int)x == n ) //If the floating point value equals the (semi) original value its divisible by 5
return true;
return false; //Other wise false
Example:
15 & 1 == 1 //15 is odd
15 <<= 1; //n is now 30
30 / 10 = 3;
3 * 10 = 30; //x is now 30
30 == 30 //15 is a multiple of 5
17 & 1 == 1 //17 is odd
17 <<= 1; //n is now 34
34 / 10 = 3.4;
((int)3.4 = 3) * 10 = 30; //x is now 30
30 != 34 //17 is not a multiple of 5.
As others said though just simply use the mod operator %.
This is how it works:
Double the number. Now anything ending in 5 will be divisible 10 (and also divisible by 5). n <<= 1; (the check for oddness is unnecessary (n&1) == 1)
Divide it by 10, and cast away the fractional part. (int)(x*0.1)
Multiply it by 10, so now we have the same number as in step 1 only if the number in step 1 was already divisible by 10.
The use of floating point to divide by 10 makes this algorithm dangerous and probably incorrect for large values.
Try this
bool isMultipleof5(int n)
{
return (n%5) == 0;
}
A simpler way would be
bool isMultipleof5(int n)
{
return 0 == ( n % 5 ) ;
}
#define IS_MULTIPLE_OF_5(n) (((n)%5) ? 0 : 1)
I'd agree that (n % 5) == 0 would be an ideal solution, but that wasn't really the question.
This code works because it first checks if the input is odd. If it is, it multiplies by two. Since all odd multiples of 5 end with a 5, multiplying by 2 gives a number that ends with 0.
Then it checks if the last digit is 0. This can only happen if it started as a 0 (i.e. was even, we didn't change it) or if it was odd and ended in a 5 (we multiplied by 2). So, if it ends in 0 then the input must have been divisible by 5.
I'd add that this is also an awkward way to check the value of the last digit. I'd suggest n % 10 == 0 instead, but like others mentioned... you could have just used n % 5 == 0 in the first place ;).