Why does the Russian Peasant Algorithm work with negative numbers when using Logic Right Shift? - bit-manipulation

I was tasked to write the Russian Multiplication Algorithm in any programming language without using any multiplication/division operators (or math methods from libraries etc.) except the shift operators. I used Java and this is my method:
public static int multiply(int a, int b) {
System.out.printf("%d %d\n",a,b);
if(b == 1 || b == -1 || a == 0)
return a;
int a0 = a << 1;
int b0 = b >>> 1;
int recursionResult = multiply(a0,b0);
if((b & 1) == 1)
recursionResult += a;
return recursionResult;
}
This works for me without any problems. However, I don't understand why it does for negative b.
I tried using the arithmetic right shift for dividing b by 2 at first. It failed, and when I looked at the output, I completely get why. Then I tried using the logic right shift just for fun (before maybe trying to invert b if it is negative, and inverting it back at the end), and it suddenly worked!
The output looks like this (for a=11, b=-50, as an example):
11 -50
22 2147483623
44 1073741811
88 536870905
176 268435452
352 134217726
704 67108863
1408 33554431
2816 16777215
5632 8388607
11264 4194303
22528 2097151
45056 1048575
90112 524287
180224 262143
360448 131071
720896 65535
1441792 32767
2883584 16383
5767168 8191
11534336 4095
23068672 2047
46137344 1023
92274688 511
184549376 255
369098752 127
738197504 63
1476395008 31
-1342177280 15
1610612736 7
-1073741824 3
-2147483648 1
This looks quite random to me, but in the end, you get -550, the correct result. Can anyone explain this to me?

Related

2nd Variation on Caesar Cipher (Having problems with splitting final string into parts)

Prompt:
In this country soldiers are poor but they need a certain level of secrecy for their communications so, though they do not know Caesar cypher, they reinvent it in the following way.
They use ASCII, without really knowing it, but code only letters a-z and A-Z. Other characters are kept such as.
They change the "rotate" each new message. This "rotate" is a prefix for their message once the message is coded. The prefix is built of 2 letters, the second one being shifted from the first one by the "rotate", the first one is the first letter, after being downcased, of the uncoded message.
For example if the "rotate" is 2, if the first letter of the uncoded message is 'J' the prefix should be 'jl'.
To lessen risk they cut the coded message and the prefix in five pieces since they have only five runners and each runner has only one piece.
If possible the message will be evenly split between the five runners; if not possible, parts 1, 2, 3, 4 will be longer and part 5 shorter. The fifth part can have length equal to the other ones or shorter. If there are many options of how to split, choose the option where the fifth part has the longest length, provided that the previous conditions are fulfilled. If the last part is the empty string don't put this empty string in the resulting array.
For example, if the coded message has a length of 17 the five parts will have lengths of 4, 4, 4, 4, 1. The parts 1, 2, 3, 4 are evenly split and the last part of length 1 is shorter. If the length is 16 the parts will be of lengths 4, 4, 4, 4, 0. Parts 1, 2, 3, 4 are evenly split and the fifth runner will stay at home since his part is the empty string and is not kept.
Could you ease them in programming their coding?
Example with shift = 1 :
message : "I should have known that you would have a perfect answer for me!!!"
code : => ["ijJ tipvme ibw", "f lopxo uibu z", "pv xpvme ibwf ", "b qfsgfdu botx", "fs gps nf!!!"]
By the way, maybe could you give them a hand to decode?
//Ends here
Issues faced:
Can't figure out how to divide the encoded string according to the given conditions. I understand the math behind how the division needs to be done, but can't convert it into code. I know that the num variable that I used needs to be decremented by 4 and the count variable should be incremented by 4 till the condition (num/4 > count) because the condition is such that if the string can be split in multiple ways, then we should do it such that the 5th part is of the longest length.
My code:
static vector<string> encodeStr(const string &s, int shift)
{
char pre = tolower(s[0]);
pre += shift;
string newS = "";
newS += tolower(s[0]);
newS += pre;
vector<string> ans;
for (int i = 0; i < (int)s.size(); i++)
{
if ((s[i] >= 65 && s[i] <= 90) || (s[i] >= 97 && s[i] <= 122))
{
char c = s[i];
c += shift;
newS += c;
}
else
newS.push_back(s[i]);
}
if (newS.size() % 4 == 0)
{
int parts = newS.size() / 4;
int start = 0;
while (start < (int)newS.size())
{
ans.push_back(newS.substr(start, parts));
start += parts;
}
}
else if (newS.size() % 5 == 0)
{
int parts = newS.size() / 5;
int start = 0;
while (start < (int)newS.length())
{
ans.push_back(newS.substr(start, parts));
start += parts;
}
}
else if (newS.length() % 5 != 0 && newS.length() % 4 != 0)
{
int num = newS.length();
int count = 0;
int start = 0;
while (num % 4 != 0)
{
num--;
count++;
}
while (num / 4 > count)
{
num = num - 4;
count = count + 4;
}
int x = newS.length() - count;
int parts = x / 4;
while (start < (int)newS.length() - count)
{
ans.push_back(newS.substr(start, parts));
start += parts;
}
ans.push_back(newS.substr((int)newS.size() - count, count));
}
return ans;
}
static string decode(vector<string> &s)
{
string s1 = "";
char check = ' ' - 1;
for (int i = 0; i < (int)s.size(); i++)
{
s1 += s[i];
}
char a = s1[1];
char b = s1[0];
int shift = a - b;
s1.erase(0, 2);
transform(s1.begin(), s1.end(), s1.begin(), [&](auto x)
{
if ((x >= 65 && x <= 90) || (x >= 97 && x <= 122))
return x -= shift;
else
return x;
});
for (int i = 0; i < (int)s1.size(); i++)
{
if (s1[i] == check)
{
s1[i]++;
}
}
return s1;
}
Code Output
First, we need to extract the important requirements from the story-text. An evaluation of the text leads to:
Caesar cypher
Based on ASCII
only upper and lowercase alpha letters shall be encoded ('A'-'Z', 'a'-'z')
The key (shift-information) shall be encoded and transmitted by along the message as 2 letter prefix. Taking the first letter of the text, unencrypted, as part 1 of the encrypted key and shifting this letter by the key and transmit it as part 2.
If possible the message will be evenly split between the five runners; if not possible, parts 1, 2, 3, 4 will be longer and part 5 shorter. The fifth part can have length equal to the other ones or shorter.
The 2-letter encrypted key shall be a prefix for parts of the split message.
For the following design, we can derive 3 major blocks:
We need a Caesar Cypher encryption/decryption algorithm
The key encryption/decryption must be implemented
The original message must be split according to requirements.
Let us start with the design for the Caesar Cypher encryption/decryption algorithm. We will take advantage of the ASCII code, where all characters have a defined associated numerical value. Please see the table below for the printable characters:
Hex Dec Bin Hex Dec Bin Hex Dec Bin
20 32 00100000 # 40 64 01000000 ` 60 96 01100000
! 21 33 00100001 A 41 65 01000001 a 61 97 01100001
" 22 34 00100010 B 42 66 01000010 b 62 98 01100010
# 23 35 00100011 C 43 67 01000011 c 63 99 01100011
$ 24 36 00100100 D 44 68 01000100 d 64 100 01100100
% 25 37 00100101 E 45 69 01000101 e 65 101 01100101
& 26 38 00100110 F 46 70 01000110 f 66 102 01100110
' 27 39 00100111 G 47 71 01000111 g 67 103 01100111
( 28 40 00101000 H 48 72 01001000 h 68 104 01101000
) 29 41 00101001 I 49 73 01001001 i 69 105 01101001
* 2a 42 00101010 J 4a 74 01001010 j 6a 106 01101010
+ 2b 43 00101011 K 4b 75 01001011 k 6b 107 01101011
, 2c 44 00101100 L 4c 76 01001100 l 6c 108 01101100
- 2d 45 00101101 M 4d 77 01001101 m 6d 109 01101101
. 2e 46 00101110 N 4e 78 01001110 n 6e 110 01101110
/ 2f 47 00101111 O 4f 79 01001111 o 6f 111 01101111
0 30 48 00110000 P 50 80 01010000 p 70 112 01110000
1 31 49 00110001 Q 51 81 01010001 q 71 113 01110001
2 32 50 00110010 R 52 82 01010010 r 72 114 01110010
3 33 51 00110011 S 53 83 01010011 s 73 115 01110011
4 34 52 00110100 T 54 84 01010100 t 74 116 01110100
5 35 53 00110101 U 55 85 01010101 u 75 117 01110101
6 36 54 00110110 V 56 86 01010110 v 76 118 01110110
7 37 55 00110111 W 57 87 01010111 w 77 119 01110111
8 38 56 00111000 X 58 88 01011000 x 78 120 01111000
9 39 57 00111001 Y 59 89 01011001 y 79 121 01111001
: 3a 58 00111010 Z 5a 90 01011010 z 7a 122 01111010
; 3b 59 00111011 [ 5b 91 01011011 { 7b 123 01111011
< 3c 60 00111100 \ 5c 92 01011100 | 7c 124 01111100
= 3d 61 00111101 ] 5d 93 01011101 } 7d 125 01111101
> 3e 62 00111110 ^ 5e 94 01011110 ~ 7e 126 01111110
? 3f 63 00111111 _ 5f 95 01011111 Del 7f 127 01111111
We observe that upper- and lowercase numbers only differ in one bit, which is equal to a distance of 32. We will use this property later.
Then, now, let us come to the core algorithm. Shifting letters.
The biggest problems are potential overflows. So, we need to deal with that.
Then we need to understand what encryption and decryption means. If encryption will shift everthing one to the right, decryption will shift it back to left again.
So, with "def" and key=1, the encrpyted string will be "efg".
And decrpytion with key=1, will shift it to left again. Result: "def"
We can observe that, for decryption, we simply need to shift by -1, so the negative of the key.
Important result: Encryption and decryption can be done with the same routine. We just need to invert the keys.
Let us look now at the overflow problematic. For the moment we will start with uppercase characters only. Characters have an associated code as shown in above ASCII table. For example, the letter 'A' is encoded with 65, 'B' with 66 and so on. Because we do not want to calculate with such big numbers, we normalize them. We simply subtract 'A' from each character. Then
'A' - 'A' = 0
'B' - 'A' = 1
'C' - 'A' = 2
'D' - 'A' = 3
You see the pattern. If we want to encrypt now the letter 'C' with key 3, we can do the following.
'C' - 'A' + 3 = 5 Then we add again 'A' to get back the letter and we will get 5 + 'A' = 'F'
That is the whole magic.
But what to do with an overflow, beyond 'Z'. This can be handled by a simple modulo division. Let us look at 'Z' + 1. We do 'Z' - 'A' = 25, then +1 = 26 and now, modulo 26 = 0. At the end again plus 'A' will be 'A'.
And so on and so on. The resulting formula is: (c - 'A' + key) % 26 +'A'
Next, what with negative keys? This is also simple. Assume an 'A' and key=-1.
Result will be a 'Z'. But this is the same as shifting positions 25 to the right. So, we can simply convert a negative key to a positive shift. The simple statement will be:
if (key < 0) key = (26 + (key % 26)) % 26;
With the above formular, there is even no need to check for a negative values. It will work for positive and negative values.
So, key = (26 + (key % 26)) % 26; will always work, for encrpytion and decrytion, for positive and negative keys.
Some extended information: Please have a look at any ASCII table and remeber, what we said above. We found out already, that any uppercase and lowercase character differ by 32. Or, if you look again to the binary representation:
char dec bin char dec bin
'A' 65 0100 0001 'a' 97 0110 0001
'B' 66 0100 0010 'b' 98 0110 0010
'C' 67 0100 0011 'b' 99 0110 0011
. . .
So, if you already know that a character is alpha, then the only difference between upper- and lowercase is bit number 5. If we want to know, if char is lowercase, we can get this by masking this bit. c & 0b0010 0000. Which is equal to c & 32 or c & 0x20.
If we want to operater on either uppercase or lowercase characters, then we can mask the "case" away. With c & 0b00011111 or c & 31 or c & 0x1F we will get always equivalents for uppercase charcters, already normalized to start with value 1.
char dez bin Masking char dez bin Masking
'A' 65 0100 0001 & 0x1b = 1 'a' 97 0110 0001 & 0x1b = 1
'B' 66 0100 0010 & 0x1b = 2 'b' 98 0110 0010 & 0x1b = 2
'C' 67 0100 0011 & 0x1b = 3 'b' 99 0110 0011 & 0x1b = 3
. . .
So, if we use an alpha character, mask it, and subtract 1, then we get as a result 0..25 for any upper- or lowercase character.
Again, I would like tor repeat the key handling. Positive keys will encrypt a string, negative keys will decrypt a string. But, as said above, negative keys can be transformed into positive ones. Example:
Shifting by -1 is same as shifting by +25
Shifting by -2 is same as shifting by +24
Shifting by -3 is same as shifting by +23
Shifting by -4 is same as shifting by +22
So,it is very obvious that we can calculate an always positive key by: 26 + key. For negative keys, this will give us the above offsets.
And for positve keys, we would have an overflow over 26, which we can elimiate by a modulo 26 division:
'A'--> 0 + 26 = 26 26 % 26 = 0
'B'--> 1 + 26 = 27 27 % 26 = 1
'C'--> 2 + 26 = 28 28 % 26 = 2
'D'--> 3 + 26 = 29 29 % 26 = 3
--> (c + key) % 26 will eliminate overflows and result in the correct new en/decryptd character.
And, if we combine this with the above wisdom for negative keys, we can write: ((26+(key%26))%26) which will work for all positive and negative keys.
If we now implement all above gathered wisdom in code, we can come up with bascically one C++ statement for the whole encryption and decryption, using std::transform:
std::string caesar(const std::string& in, int key) {
std::string res(in.size(), ' ');
std::transform(in.begin(), in.end(), res.begin(), [&](char c) {return std::isalpha(c) ? (char)((((c & 31) - 1 + ((26 + (key % 26)) % 26)) % 26 + 65) | (c & 32)) : c; });
return res;
}
This will do, what we described above:
(c & 31) - 1 will normalize a character. Meaning, convert to uppercase and to a range of 0-25
((26 + (key % 26)) % 26)) % 26 will do the key shift.
+ 65 will convert the nomalized value (0-25) back to a letter ('A'-'Z')
| (c & 32)) : c This will restore the lower case, if the letter was lower case before.
Now, we derived a complete algorithm and function for encryption and decryption using Caeser Cypher.
.
Next is splitting up the message in 5 parts.
The requirement was:
If possible the message will be evenly split between the five runners; if not possible, parts 1, 2, 3, 4 will be longer and part 5 shorter. The fifth part can have length equal to the other ones or shorter.
This can again be achieved with integer and modulo division. Basically, we will do an integer division to get the number of letters for each of the 5 chunks. Then we use a modulo division, to get the rest.
It is clear, but I will repeat it. If we do an integer division by 5, then the rest can be max 4. And this rest can then be distributed and added 1 by one to other chunks. Let us make an example using 23.
23 % 5 = 4 So, initially each chunk will be 4 letters long
Chunk 1: 4
Chunk 2: 4
Chunk 3: 4
Chunk 4: 4
Chunk 5: 4
------------
Sum: 20 // The rest, 3 is missing
Rest can be calculated with:
23 % 5 = 3 // So, we have a rest or remainder of 3. This we will distribute now:
Remainder = 3
Chunk 1: 4 + 1 = 5 3 - 1 = 2
Chunk 2: 4 + 1 = 5 2 - 1 = 1
Chunk 3: 4 + 1 = 5 1 - 1 = 0 Now everything was distributed
Chunk 4: 4 4
Chunk 5: 4 4
-------------------
Sum: 23
We now know, how chunksizes can be calculated.
For splitting the original strings into substrings, we can use the corresponding std::strings substr function, which is described here. You see, that we need to calculate a "start position" and a "length" value. Let us write a short piece of code for that.
#include <iostream>
#include <array>
#include <string>
constexpr std::size_t NumberOfChunks = 5u;
struct SDefs {
struct SDef {
std::size_t startPosition{}; // For substr function, we need a start position
std::size_t count{}; // and a count aof characters
};
std::array<SDef, NumberOfChunks> sDefs{}; // We have an array of 5 for this Positions and Counts
void calculate(const std::string& s) { // Calculation function
const size_t chunk = s.size() / NumberOfChunks; // Calculate the basic chunksize of all chunks
size_t remainder = s.size() % NumberOfChunks; // Calculate the rest that needs to be distributed
for (std::size_t startPos{}; SDef & sdef : sDefs) { // Calculate all positions and counts in a loop
sdef.startPosition = startPos; // Set startposition
sdef.count = chunk + (remainder ? 1 : 0); // And the chunk size, including potential distributed remainder
startPos += sdef.count; // Next startposition
if (remainder) --remainder; // And next remainder, if any
}
}
SDef& operator[](const std::size_t i) { return sDefs[i]; } // Easier accessibility
};
// Test code
int main () {
SDefs sdefs{};
std::string test{ "12345678901234567890123" };
sdefs.calculate(test);
for (std::size_t i{}; i < NumberOfChunks; ++i)
std::cout << "Chunk " << i+1 << " Start position: " << sdefs[i].startPosition << "\tCount: " << sdefs[i].count << '\n';
}
.
Finally: The transmission of the key. For encrypting, we simply take the first character of the text, or, in our case the substring. and then apply the encryption/decryption function on that to get the second letter.
And because the requirement was to use lower case characters, we set the 5th bit for the characters.
For decryption, in order to get the key, we need to subtract the second letter from the first. Thats all. Then we can invert it and use our encryption/decryption function again.
By the way. This method is dangerous and easy to hack, because you have always repeating letters at the beginning of a chunk.
For the final result, we need to add a little bit of house keeping code.
Then, lets_put everything together and create some program:
#include <iostream>
#include <array>
#include <string>
#include <algorithm>
#include <cctype>
constexpr std::size_t NumberOfChunks = 5u; // Maybe modified to whatever you need
// ---------------------------------------------------------------------------------------------------------
// Chunk calculator
struct SDefs {
struct SDef {
std::size_t startPosition{}; // For substr function, we need a start position
std::size_t count{}; // and a count aof characters
};
std::array<SDef, NumberOfChunks> sDefs{}; // We have an array of 5 for this Positions and Counts
void calculate(const std::string& s) { // Calculation function
const size_t chunk = s.size() / NumberOfChunks; // Calculate the basic chunksize of all chunks
size_t remainder = s.size() % NumberOfChunks; // Calculate the rest that needs to be distributed
for (std::size_t startPos{}; SDef & sdef : sDefs) { // Calculate all positions and counts in a loop
sdef.startPosition = startPos; // Set startposition
sdef.count = chunk + (remainder ? 1 : 0); // And the chunk size, including potential distributed remainder
startPos += sdef.count; // Next startposition
if (remainder) --remainder; // And next remainder, if any
}
}
SDef& operator[](const std::size_t i) { return sDefs[i]; } // Easier accessibility
};
// ---------------------------------------------------------------------------------------------------------
// Caesar Cypher
std::string caesar(const std::string& in, int key) {
std::string res(in.size(), ' ');
std::transform(in.begin(), in.end(), res.begin(), [&](char c) {return std::isalpha(c) ? (char)((((c & 31) - 1 + ((26 + (key % 26)) % 26)) % 26 + 65) | (c & 32)) : c; });
return res;
}
// Get a prefix, based on a given key
std::string getKeyPrefix(const std::string& s, const int key) {
std::string prefix("AA");
if (auto i = std::find_if(s.begin(), s.end(), std::isalpha); i != s.end()) {
prefix[0] = *i |32;
prefix[1] = (char)((((*i & 31) - 1 + ((26 + (key % 26)) % 26)) % 26 + 65) | 32);
}
return prefix;
}
// ---------------------------------------------------------------------------------------------------------
std::string test{"This was a major hack. What a pity that nobody will read or value it."};
int main() {
std::cout << "\nPlease enter a key: ";
if (int key{}; std::cin >> key) {
// Here we will store our encrypter and later decypted messages
std::array<std::string, NumberOfChunks> messages{};
// Here we will calculate the substrings properties
SDefs sdef{};
sdef.calculate(test);
// Encryption
for (std::size_t i{}; std::string& message : messages) {
// Get substring
const std::string sub = test.substr(sdef[i].startPosition, sdef[i].count);
// Encrypt sub string text
message = getKeyPrefix(sub, key) + caesar(sub,key);
// Debug output
std::cout << "Encrypted Message chunk " << i++ << ":\t" << message << '\n';
}
// Decryption
std::cout << "\n\nDecrypted Message:\n\n";
for (std::string& message : messages) {
// get key, inverted
int dkey = message[0] - message[1];
// Get substring
std::string sub = message.substr(2);
// Derypt sub string text
message = caesar(sub, dkey);
// Debug output
std::cout << message;
}
std::cout << "\n\n";
}
else
std::cerr << "\n\n***Error: Invalid input\n\n";
}
Have fun.
Checksum: fkems hajk eks ἀρμιν μοντιγνι qod krtd ghja

Why does a bool array have a int type output that is not 1 or 0? [duplicate]

Many compilers seem to be keeping only 0 or 1 in bool values, but I'm not sure this will always work:
int a = 2;
bool b = a;
int c = 3 + b; // 4 or 5?
Yes:
In C++ (§4.5/4):
An rvalue of type bool can be
converted to an rvalue of type int,
with false becoming zero and true
becoming one.
In C, when a value is converted to _Bool, it becomes 0 or 1 (§6.3.1.2/1):
When any scalar value is converted to
_Bool, the result is 0 if the value compares equal to 0; otherwise, the
result is 1.
When converting to int, it's pretty straight-forward. int can hold 0 and 1, so there's no change in value (§6.3.1.3).
Well, not always...
const int n = 100;
bool b[n];
for (int i = 0; i < n; ++i)
{
int x = b[i];
if (x & ~1)
{
std::cout << x << ' ';
}
}
Output on my system:
28 255 34 148 92 192 119 46 165 192 119 232 26 195 119 44 255 34 96 157 192 119
8 47 78 192 119 41 78 192 119 8 250 64 2 194 205 146 124 192 73 64 4 255 34 56 2
55 34 224 255 34 148 92 192 119 80 40 190 119 255 255 255 255 41 78 192 119 66 7
8 192 119 192 73 64 240 255 34 25 74 64 192 73 64
The reason for this apparently weird output is laid out in the standard, 3.9.1 §6:
Values of type bool are either true or false. Using a bool value in ways described by this International Standard as "undefined", such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false.
Is C/C++ .......
There's no language named C/C++.
bool type always guaranteed to be 0 or 1 when typecast'ed to int?
In C++ yes because section $4.5/4 says
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one.
.
int c = 3 + b; // 4 or 5?
The value of c will be 4
One more example when you are out of the safe boat:
bool b = false;
*(reinterpret_cast<char*>(&b)) = 0xFF;
int from_bool = b;
cout << from_bool << " is " << (b ? "true" : "false");
Output (g++ (GCC) 4.4.7):
255 is true
To be added to the FredOverflow's example.
There is no bool type in C pre C99 (Such as C90), however the bool type in C99/C++ is always guaranteed to be 0 or 1.
In C, all boolean operation are guaranteed to return either 0 or 1, whether the bool type is defined or not.
So a && b or !a or a || b will always return 0 or 1 in C or C++ regardless of the type of a and b.
Types with padding bits may behave strangely if the padding bits don't hold the values expected for the type. Most C89 implementations didn't use padding bits with any of their integer types, but C99 requires that implementations define such a type: _Bool. Reading a _Bool when all of its bits are zero will yield zero. Writing any non-zero value to a _Bool will set its bits to some pattern which will yield 1 when read. Writing zero will set the bits to a pattern (which may or may not be all-bits-zero) which will yield 0 when read.
Unless specified otherwise in an implementation's documentation, any bit pattern other than all-bits-zero which could not have been produced by storing a zero or non-zero value to a _Bool is a trap representation; the Standard says nothing about what will happen if an attempt is made to read such a value. Given, e.g.
union boolChar { _Bool b; unsigned char c; } bc;
storing zero to bc.c and reading bc.b will yield zero. Storing zero or one to bc.b will set bc.c to values which, if written, will cause bc.b to hold zero or one. Storing any other value to bc.c and reading bc.b will yield Undefined Behavior.

How to calculate pow(2,n) when n exceeds 64 in c++?

So, I am new to programming in c++ and i came across this question where i need to calculate pow(2,n)/2 where n>64 ?
i tried using unsigned long long int but as the limit of the c++ is only 2^64. So is there any method to calculate this.
Edit:
1 < n < 10^5
The result of the expression is used in further calculation
The question is asked on online platform.So, i cant use libraries like gmp to handle large numbers.
Question
You are given with an array A of size N. An element Ai is said to be charged if its value (Ai) is greater than or equal to Ki. Ki is the total number of subsets of array A that consist of element Ai.
Total charge value of the array is defined as summation of all charged elements present in the array mod (10^9)+7.
Your task is to output the total charge value of the given array.
An important detail here is that you're not being asked to compute 2n for gigantic n. Instead, you're being asked to compute 2n mod 109 + 7 for large n, and that's a different question.
For example, let's suppose you want to compute 270 mod 109 + 1. Notice that 270 doesn't fit into a 64-bit machine word. However, 270 = 230 · 235, and 235 does fit into a 64-bit machine word. Therefore, we could do this calculation to get 270 mod 109 + 7:
270 (mod 109 + 7)
= 235 · 235 (mod 109 + 7)
= (235 mod 109 + 7) · (235 mod 109 + 7) mod 109 + 7
= (34359738368 mod 109 + 7) · (34359738368 mod 109 + 7) mod 109 + 7
= (359738130 · 359738130) mod 109 + 7
= 129411522175896900 mod 109 + 7
= 270016253
More generally, by using repeated squaring, you can compute 2n mod 109 + 7 for any value of n in a way that nicely fits into a 64-bit integer.
Hope this helps!
The common approach in serious numerical work is to rewrite the formula's. You store log(x) instead of x, and later when you do need x it will typically be in a context where you didn't need all those digits anyway.

Density of fractions between 2 given numbers

I'm trying to do some analysis over a simple Fraction class and I want some data to compare that type with doubles.
The problem
Right know I'm looking for some good way to get the density of Fractions between 2 numbers. Fractions is basically 2 integers (e.g. pair< long, long>), and the density between s and t is the amount of representable numbers in that range. And it needs to be an exact, or very good approximation done in O(1) or very fast.
To make it a bit simpler, let's say I want all the numbers (not fractions) a/b between s and t, where 0 <= s <= a/b < t <= M, and 0 <= a,b <= M (b > 0, a and b are integers)
Example
If my fractions were of a data type which only count to 6 (M = 6), and I want the density between 0 and 1, the answer would be 12. Those numbers are:
0, 1/6, 1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5, 5/6.
What I thought already
A very naive approach would be to cycle trough all the possible fractions, and count those which can't be simplified. Something like:
long fractionsIn(double s, double t){
long density = 0;
long M = LONG_MAX;
for(int d = 1; d < floor(M/t); d++){
for(int n = ceil(d*s); n < M; n++){
if( gcd(n,d) == 1 )
density++;
}
}
return density;
}
But gcd() is very slow so it doesn't works. I also try doing some math but i couldn't get to anything good.
Solution
Thanks to #m69 answer, I made this code for Fraction = pair<Long,Long>:
//this should give the density of fractions between first and last, or less.
double fractionsIn(unsigned long long first, unsigned long long last){
double pi = 3.141592653589793238462643383279502884;
double max = LONG_MAX; //i can't use LONG_MAX directly
double zeroToOne = max/pi * max/pi * 3; // = approx. amount of numbers in Farey's secuence of order LONG_MAX.
double res = 0;
if(first == 0){
res = zeroToOne;
first++;
}
for(double i = first; i < last; i++){
res += zeroToOne/(i * i+1);
if(i == i+1)
i = nextafter(i+1, last); //if this happens, i might not count some fractions, but i have no other choice
}
return floor(res);
}
The main change is nextafter, which is important with big numbers (1e17)
The result
As I explain at the begining, I was trying to compare Fractions with double. Here is the result for Fraction = pair<Long,Long> (and here how I got the density of doubles):
Density between 0,1: | 1,2 | 1e6,1e6+1 | 1e14,1e14+1 | 1e15-1,1e15 | 1e17-10,1e17 | 1e19-10000,1e19 | 1e19-1000,1e19
Doubles: 4607182418800017408 | 4503599627370496 | 8589934592 | 64 | 8 | 1 | 5 | 0
Fraction: 2.58584e+37 | 1.29292e+37 | 2.58584e+25 | 2.58584e+09 | 2.58584e+07 | 2585 | 1 | 0
Density between 0 and 1
If the integers with which you express the fractions are in the range 0~M, then the density of fractions between the values 0 (inclusive) and 1 (exclusive) is:
M: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0~(1): 1 2 4 6 10 12 18 22 28 32 42 46 58 64 72 80 96 102 120 128 140 150 172 180 200 212 230 242 270 278 308 ...
This is sequence A002088 on OEIS. If you scroll down to the formula section, you'll find information about how to approximate it, e.g.:
Φ(n) = (3 ÷ π2) × n2 + O[n × (ln n)2/3 × (ln ln n)4/3]
(Unfortunately, no more detail is given about the constants involved in the O[x] part. See discussion about the quality of the approximation below.)
Distribution across range
The interval from 0 to 1 contains half of the total number of unique fractions that can be expressed with numbers up to M; e.g. this is the distribution when M = 15 (i.e. 4-bit integers):
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
72 36 12 6 4 2 2 2 1 1 1 1 1 1 1 1
for a total of 144 unique fractions. If you look at the sequence for different values of M, you'll see that the steps in this sequence converge:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1: 1 1
2: 2 1 1
3: 4 2 1 1
4: 6 3 1 1 1
5: 10 5 2 1 1 1
6: 12 6 2 1 1 1 1
7: 18 9 3 2 1 1 1 1
8: 22 11 4 2 1 1 1 1 1
9: 28 14 5 2 2 1 1 1 1 1
10: 32 16 5 3 2 1 1 1 1 1 1
11: 42 21 7 4 2 2 1 1 1 1 1 1
12: 46 23 8 4 2 2 1 1 1 1 1 1 1
13: 58 29 10 5 3 2 2 1 1 1 1 1 1 1
14: 64 32 11 5 4 2 2 1 1 1 1 1 1 1 1
15: 72 36 12 6 4 2 2 2 1 1 1 1 1 1 1 1
Not only is the density between 0 and 1 half of the total number of fractions, but the density between 1 and 2 is a quarter, and the density between 2 and 3 is close to a twelfth, and so on.
As the value of M increases, the distribution of fractions across the ranges 0-1, 1-2, 2-3 ... converges to:
1/2, 1/4, 1/12, 1/24, 1/40, 1/60, 1/84, 1/112, 1/144, 1/180, 1/220, 1/264 ...
This sequence can be calculated by starting with 1/2 and then:
0-1: 1/2 x 1/1 = 1/2
1-2: 1/2 x 1/2 = 1/4
2-3: 1/4 x 1/3 = 1/12
3-4: 1/12 x 2/4 = 1/24
4-5: 1/24 x 3/5 = 1/40
5-6: 1/40 x 4/6 = 1/60
6-7: 1/60 x 5/7 = 1/84
7-8: 1/84 x 6/8 = 1/112
8-9: 1/112 x 7/9 = 1/144 ...
You can of course calculate any of these values directly, without needing the steps inbetween:
0-1: 1/2
6-7: 1/2 x 1/6 x 1/7 = 1/84
(Also note that the second half of the distribution sequence consists of 1's; these are all the integers divided by 1.)
Approximating the density in given interval
Using the formulas provided on the OEIS page, you can calculate or approximate the density in the interval 0-1, and multiplied by 2 this is the total number of unique values that can be expressed as fractions.
Given two values s and t, you can then calculate and sum the densities in the intervals s ~ s+1, s+1 ~ s+2, ... t-1 ~ t, or use an interpolation to get a faster but less precise approximate value.
Example
Let's assume that we're using 10-bit integers, capable of expressing values from 0 to 1023. Using this table linked from the OEIS page, we find that the density between 0~1 is 318452, and the total number of fractions is 636904.
If we wanted to find the density in the interval s~t = 100~105:
100~101: 1/2 x 1/100 x 1/101 = 1/20200 ; 636904/20200 = 31.53
101~102: 1/2 x 1/101 x 1/102 = 1/20604 ; 636904/20604 = 30.91
102~103: 1/2 x 1/102 x 1/103 = 1/21012 ; 636904/21012 = 30.31
103~104: 1/2 x 1/103 x 1/104 = 1/21424 ; 636904/21424 = 29.73
104~105: 1/2 x 1/104 x 1/105 = 1/21840 ; 636904/21840 = 29.16
Rounding these values gives the sum:
32 + 31 + 30 + 30 + 29 = 152
A brute force algorithm gives this result:
32 + 32 + 30 + 28 + 28 = 150
So we're off by 1.33% for this low value of M and small interval with just 5 values. If we had used linear interpolation between the first and last value:
100~101: 31.53
104~105: 29.16
average: 30.345
total: 151.725 -> 152
we'd have arrived at the same value. For larger intervals, the sum of all the densities will probably be closer to the real value, because rounding errors will cancel each other out, but the results of linear interpolation will probably become less accurate. For ever larger values of M, the calculated densities should converge with the actual values.
Quality of approximation of Φ(n)
Using this simplified formula:
Φ(n) = (3 ÷ π2) × n2
the results are almost always smaller than the actual values, but they are within 1% for n ≥ 182, within 0.1% for n ≥ 1880 and within 0.01% for n ≥ 19494. I would suggest hard-coding the lower range (the first 50,000 values can be found here), and then using the simplified formula from the point where the approximation is good enough.
Here's a simple code example with the first 182 values of Φ(n) hard-coded. The approximation of the distribution sequence seems to add an error of a similar magnitude as the approximation of Φ(n), so it should be possible to get a decent approximation. The code simply iterates over every integer in the interval s~t and sums the fractions. To speed up the code and still get a good result, you should probably calculate the fractions at several points in the interval, and then use some sort of non-linear interpolation.
function fractions01(M) {
var phi = [0,1,2,4,6,10,12,18,22,28,32,42,46,58,64,72,80,96,102,120,128,140,150,172,180,200,212,230,242,270,278,308,
324,344,360,384,396,432,450,474,490,530,542,584,604,628,650,696,712,754,774,806,830,882,900,940,964,1000,
1028,1086,1102,1162,1192,1228,1260,1308,1328,1394,1426,1470,1494,1564,1588,1660,1696,1736,1772,1832,1856,
1934,1966,2020,2060,2142,2166,2230,2272,2328,2368,2456,2480,2552,2596,2656,2702,2774,2806,2902,2944,3004,
3044,3144,3176,3278,3326,3374,3426,3532,3568,3676,3716,3788,3836,3948,3984,4072,4128,4200,4258,4354,4386,
4496,4556,4636,4696,4796,4832,4958,5022,5106,5154,5284,5324,5432,5498,5570,5634,5770,5814,5952,6000,6092,
6162,6282,6330,6442,6514,6598,6670,6818,6858,7008,7080,7176,7236,7356,7404,7560,7638,7742,7806,7938,7992,
8154,8234,8314,8396,8562,8610,8766,8830,8938,9022,9194,9250,9370,9450,9566,9654,9832,9880,10060];
if (M < 182) return phi[M];
return Math.round(M * M * 0.30396355092701331433 + M / 4); // experimental; see below
}
function fractions(M, s, t) {
var half = fractions01(M);
var frac = (s == 0) ? half : 0;
for (var i = (s == 0) ? 1 : s; i < t && i <= M; i++) {
if (2 * i < M) {
var f = Math.round(half / (i * (i + 1)));
frac += (f < 2) ? 2 : f;
}
else ++frac;
}
return frac;
}
var M = 1023, s = 100, t = 105;
document.write(fractions(M, s, t));
Comparing the approximation of Φ(n) with the list of the 50,000 first values suggests that adding M÷4 is a workable substitute for the second part of the formula; I have not tested this for larger values of n, so use with caution.
Blue: simplified formula. Red: improved simplified formula.
Quality of approximation of distribution
Comparing the results for M=1023 with those of a brute-force algorithm, the errors are small in real terms, never more than -7 or +6, and above the interval 205~206 they are limited to -1 ~ +1. However, a large part of the range (57~1024) has fewer than 100 fractions per integer, and in the interval 171~1024 there are only 10 fractions or fewer per integer. This means that small errors and rounding errors of -1 or +1 can have a large impact on the result, e.g.:
interval: 241 ~ 250
fractions/integer: 6
approximation: 5
total: 50 (instead of 60)
To improve the results for intervals with few fractions per integer, I would suggest combining the method described above with a seperate approach for the last part of the range:
Alternative method for last part of range
As already mentioned, and implemented in the code example, the second half of the range, M÷2 ~ M, has 1 fraction per integer. Also, the interval M÷3 ~ M÷2 has 2; the interval M÷4 ~ M÷3 has 4. This is of course the Φ(n) sequence again:
M/2 ~ M : 1
M/3 ~ M/2: 2
M/4 ~ M/3: 4
M/5 ~ M/4: 6
M/6 ~ M/5: 10
M/7 ~ M/6: 12
M/8 ~ M/7: 18
M/9 ~ M/8: 22
M/10 ~ M/9: 28
M/11 ~ M/10: 32
M/12 ~ M/11: 42
M/13 ~ M/12: 46
M/14 ~ M/13: 58
M/15 ~ M/14: 64
M/16 ~ M/15: 72
M/17 ~ M/16: 80
M/18 ~ M/17: 96
M/19 ~ M/18: 102 ...
Between these intervals, one integer can have a different number of fractions, depending on the exact value of M, e.g.:
interval fractions
202 ~ 203 10
203 ~ 204 10
204 ~ 205 9
205 ~ 206 6
206 ~ 207 6
The interval 204 ~ 205 lies on the edge between intervals, because M ÷ 5 = 204.6; it has 6 + 3 = 9 fractions because M modulo 5 is 3. If M had been 1022 or 1024 instead of 1023, it would have 8 or 10 fractions. (This example is straightforward because 5 is a prime; see below.)
Again, I would suggest using the hard-coded values for Φ(n) to calculate the number of fractions for the last part of the range. If you use the first 17 values as listed above, this covers the part of the range with fewer than 100 fractions per integer, so that would reduce the impact of rounding errors below 1%. The first 56 values would give you 0.1%, the first 182 values 0.01%.
Together with the values of Φ(n), you could hard-code the number of fractions of the edge intervals for each modulo value, e.g.:
modulo: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
M/ 2 1 2
M/ 3 2 3 4
M/ 4 4 5 5 6
M/ 5 6 7 8 9 10
M/ 6 10 11 11 11 11 12
M/ 7 12 13 14 15 16 17 18
M/ 8 18 19 19 20 20 21 21 22
M/ 9 22 23 24 24 25 26 26 27 28
M/10 28 29 29 30 30 30 30 31 31 32
M/11 32 33 34 35 36 37 38 39 40 41 42
M/12 42 43 43 43 43 44 44 45 45 45 45 46
M/13 46 47 48 49 50 51 52 53 54 55 56 57 58
M/14 58 59 59 60 60 61 61 61 61 62 62 63 63 64
M/15 64 65 66 66 67 67 67 68 69 69 69 70 70 71 72
M/16 72 73 73 74 74 75 75 76 76 77 77 78 78 79 79 80
M/17 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
M/18 96 97 97 97 97 98 98 99 99 99 99 100 100 101 101 101 101 102
This is exactly the same as: (Sum of phi(k)) where m <= k <= M where phi(k) is the Euler Totient Function and with phi(0) = 1 (as defined by the problem). There is no known closed form for this sum. However there are many optimizations known as mentioned in the wiki link. This is known as the Totient Summatory Function in Wolfram. The same website also links to the series: A002088 and provides a few asymptotic approximations.
The reasoning is this: consider the number of values of the form {1/M, 2/M, ...., (M-1)/M, M/M}. All those fractions that will be reducible to a smaller value will not be counted in phi(M) because they are not relatively prime. They will appear in the summation of another totient.
For example, phi(6) = 12 and you have 1 + phi(6), since you also count the 0.

c++ array sorting with some specifications

I'm using C++. Using sort from STL is allowed.
I have an array of int, like this :
1 4 1 5 145 345 14 4
The numbers are stored in a char* (i read them from a binary file, 4 bytes per numbers)
I want to do two things with this array :
swap each number with the one after that
4 1 5 1 345 145 4 14
sort it by group of 2
4 1 4 14 5 1 345 145
I could code it step by step, but it wouldn't be efficient. What I'm looking for is speed. O(n log n) would be great.
Also, this array can be bigger than 500MB, so memory usage is an issue.
My first idea was to sort the array starting from the end (to swap the numbers 2 by 2) and treating it as a long* (to force the sorting to take 2 int each time). But I couldn't manage to code it, and I'm not even sure it would work.
I hope I was clear enough, thanks for your help : )
This is the most memory efficient layout I could come up with. Obviously the vector I'm using would be replaced by the data blob you're using, assuming endian-ness is all handled well enough. The premise of the code below is simple.
Generate 1024 random values in pairs, each pair consisting of the first number between 1 and 500, the second number between 1 and 50.
Iterate the entire list, flipping all even-index values with their following odd-index brethren.
Send the entire thing to std::qsort with an item width of two (2) int32_t values and a count of half the original vector.
The comparator function simply sorts on the immediate value first, and on the second value if the first is equal.
The sample below does this for 1024 items. I've tested it without output for 134217728 items (exactly 536870912 bytes) and the results were pretty impressive for a measly macbook air laptop, about 15 seconds, only about 10 of that on the actual sort. What is ideally most important is no additional memory allocation is required beyond the data vector. Yes, to the purists, I do use call-stack space, but only because q-sort does.
I hope you get something out of it.
Note: I only show the first part of the output, but I hope it shows what you're looking for.
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <cstdint>
// a most-wacked-out random generator. every other call will
// pull from a rand modulo either the first, or second template
// parameter, in alternation.
template<int N,int M>
struct randN
{
int i = 0;
int32_t operator ()()
{
i = (i+1)%2;
return (i ? rand() % N : rand() % M) + 1;
}
};
// compare to integer values by address.
int pair_cmp(const void* arg1, const void* arg2)
{
const int32_t *left = (const int32_t*)arg1;
const int32_t *right = (const int32_t *)arg2;
return (left[0] == right[0]) ? left[1] - right[1] : left[0] - right[0];
}
int main(int argc, char *argv[])
{
// a crapload of int values
static const size_t N = 1024;
// seed rand()
srand((unsigned)time(0));
// get a huge array of random crap from 1..50
vector<int32_t> data;
data.reserve(N);
std::generate_n(back_inserter(data), N, randN<500,50>());
// flip all the values
for (size_t i=0;i<data.size();i+=2)
{
int32_t tmp = data[i];
data[i] = data[i+1];
data[i+1] = tmp;
}
// now sort in pairs. using qsort only because it lends itself
// *very* nicely to performing block-based sorting.
std::qsort(&data[0], data.size()/2, sizeof(data[0])*2, pair_cmp);
cout << "After sorting..." << endl;
std::copy(data.begin(), data.end(), ostream_iterator<int32_t>(cout,"\n"));
cout << endl << endl;
return EXIT_SUCCESS;
}
Output
After sorting...
1
69
1
83
1
198
1
343
1
367
2
12
2
30
2
135
2
169
2
185
2
284
2
323
2
325
2
347
2
367
2
373
2
382
2
422
2
492
3
286
3
321
3
364
3
377
3
400
3
418
3
441
4
24
4
97
4
153
4
210
4
224
4
250
4
354
4
356
4
386
4
430
5
14
5
26
5
95
5
145
5
302
5
379
5
435
5
436
5
499
6
67
6
104
6
135
6
164
6
179
6
310
6
321
6
399
6
409
6
425
6
467
6
496
7
18
7
65
7
71
7
84
7
116
7
201
7
242
7
251
7
256
7
324
7
325
7
485
8
52
8
93
8
156
8
193
8
285
8
307
8
410
8
456
8
471
9
27
9
116
9
137
9
143
9
190
9
190
9
293
9
419
9
453
With some additional constraints on both your input and your platform, you can probably use an approach like the one you are thinking of. These constraints would include
Your input contains only positive numbers (i.e. can be treated as unsigned)
Your platform provides uint8_t and uint64_t in <cstdint>
You address a single platform with known endianness.
In that case you can divide your input into groups of 8 bytes, do some byte shuffling to arrange each groups as one uint64_t with the "first" number from the input in the lower-valued half and run std::sort on the resulting array. Depending on endianness you may need to do more byte shuffling to rearrange each sorted 8-byte group as a pair of uint32_t in the expected order.
If you can't code this on your own, I'd strongly advise you not to take this approach.
A better and more portable approach (you have some inherent non-portability by starting from a not clearly specified binary file format), would be:
std::vector<int> swap_and_sort_int_pairs(const unsigned char buffer[], size_t buflen) {
const size_t intsz = sizeof(int);
// We have to assume that the binary format in buffer is compatible with our int representation
// we also require an even number of integers
assert(buflen % (2*intsz) == 0);
// load pairwise
std::vector< std::pair<int,int> > pairs;
pairs.reserve(buflen/(2*intsz));
for (const unsigned char* bufp=buffer; bufp<buffer+buflen; bufp+= 2*intsz) {
// It would be better to have a more portable binary -> int conversion
int first_value = *reinterpret_cast<int*>(bufp);
int second_value = *reinterpret_cast<int*>(bufp + intsz);
// swap each pair here
pairs.emplace_back( second_value, firstvalue );
}
// less<pair<..>> does lexicographical ordering, which is what you are looking ofr
std::sort(pairs.begin(), pairs.end());
// convert back to linear vector
std::vector<int> result;
result.reserve(2*pairs.size());
for (auto& entry : pairs) {
result.push_back(entry.first);
result.push_back(entry.second);
}
return result;
}
Both the inital parse/swap pass (which you need anyway) and the final conversion are O(N), so the total complexity is still (O(N log(N)).
If you can continue to work with pairs, you can save the final conversion. The other way to save that conversion would be to use a hand-coded sort with two-int strides and two-int swap: much more work - and possibly still hard to get as efficient as a well-tuned library sort.
Do one thing at a time. First, give your data some *struct*ure. It seems that each 8 byte form a unit of the
form
struct unit {
int key;
int value;
}
If the endianness is right, you can do this in O(1) with a reinterpret_cast. If it isn't, you'll have to live with a O(n) conversion effort. Both vanish compared to the O(n log n) search effort.
When you have an array of these units, you can use std::sort like:
bool compare_units(const unit& a, const unit& b) {
return a.key < b.key;
}
std::sort(array, length, compare_units);
The key to this solution is that you do the "swapping" and byte-interpretation first and then do the sorting.