A many-to-one mapping in the natural domain using discrete input variables? - c++

I would like to find a mapping f:X --> N, with multiple discrete natural variables X of varying dimension, where f produces a unique number between 0 to the multiplication of all dimensions. For example. Assume X = {a,b,c}, with dimensions |a| = 2, |b| = 3, |c| = 2. f should produce 0 to 12 (2*3*2).
a b c | f(X)
0 0 0 | 0
0 0 1 | 1
0 1 0 | 2
0 1 1 | 3
0 2 0 | 4
0 2 1 | 5
1 0 0 | 6
1 0 1 | 7
1 1 0 | 8
1 1 1 | 9
1 2 0 | 10
1 2 1 | 11
This is easy when all dimensions are equal. Assume binary for example:
f(a=1,b=0,c=1) = 1*2^2 + 0*2^1 + 1*2^0 = 5
Using this naively with varying dimensions we would get overlapping values:
f(a=0,b=1,c=1) = 0*2^2 + 1*3^1 + 1*2^2 = 4
f(a=1,b=0,c=0) = 1*2^2 + 0*3^1 + 0*2^2 = 4
A computationally fast function is preferred as I intend to use/implement it in C++. Any help is appreciated!

Ok, the most important part here is math and algorythmics. You have variable dimensions of size (from least order to most one) d0, d1, ... ,dn. A tuple (x0, x1, ... , xn) with xi < di will represent the following number: x0 + d0 * x1 + ... + d0 * d1 * ... * dn-1 * xn
In pseudo-code, I would write:
result = 0
loop for i=n to 0 step -1
result = result * d[i] + x[i]
To implement it in C++, my advice would be to create a class where the constructor would take the number of dimensions and the dimensions itself (or simply a vector<int> containing the dimensions), and a method that would accept an array or a vector of same size containing the values. Optionaly, you could control that no input value is greater than its dimension.
A possible C++ implementation could be:
class F {
vector<int> dims;
public:
F(vector<int> d) : dims(d) {}
int to_int(vector<int> x) {
if (x.size() != dims.size()) {
throw std::invalid_argument("Wrong size");
}
int result = 0;
for (int i = dims.size() - 1; i >= 0; i--) {
if (x[i] >= dims[i]) {
throw std::invalid_argument("Value >= dimension");
}
result = result * dims[i] + x[i];
}
return result;
}
};

Related

How to check if exists array[i][j] in c++?

I have two dimensional array of chars, where all numbers, excluding one * (as given in picture (two examples)
My task is to sum up all neighbour integers ( in example 1, neighbours of * are 4,2,5,8 and sum is 4+2+5+8=19)
But in example 2, * doesn't have top neighbour.
My initial code was like:
arr[i-1][j] + arr[i+1][j] + arr[i][j-1] + arr[i][j+1]
But then I understood that in case like a[0][-1] doesn't exist. So can you help me to to solve my problem
You need to explicitly check each one. The following should work:
bool inRange(int i, int j) {
const auto n = 4; // you need to set this somewhere, or pass it in
return (i >= 0) && (i < n) && (j >= 0) && (j < n);
}
auto sum = (inRange(i-1, j) ? arr[i-1][j] : 0)
+ (inRange(i+1, j) ? arr[i+1][j] : 0)
+ (inRange(i, j-1) ? arr[i][j-1] : 0)
+ (inRange(i, j+1) ? arr[i][j+1] : 0);
You can probably write this a little cleaner, but you need to check not only for the -1, but also for when you go over 3.
There can be multiple solutions to this problem, but if you want to avoid checking bound each time you can extend the matrix dimension by 1 than needed. That means if you have an array:
1 * 4 7
8 9 2 3
5 1 2 4
4 3 6 5
Implement it as:
0 0 0 0 0 0
0 1 * 4 7 0
0 8 9 2 3 0
0 5 1 2 4 0
0 4 3 6 5 0
0 0 0 0 0 0
Doing this won't even affect your sum at the end.

Ordering an array based on 2D array of relations (higher, lower, doesn't matter)

I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.

Partitioning arrays by index

I am fairly new to C++, and am struggling through a problem that seems to have a solid solution but I just can't seem to find it. I have a contiguous array of ints starting at zero:
int i[6] = { 0, 1, 2, 3, 4, 5 }; // this is actually from an iterator
I would like to partition the array into groups of three. The design is to have two methods, j and k, such that given an i they will return the other two elements from the same group of three. For example:
i j(i) k(i)
0 1 2
1 0 2
2 0 1
3 4 5
4 3 5
5 3 4
The solution seems to involve summing the i with its value mod three and either plus or minus one, but I can't quite seem to work out the logic.
This should work:
int d = i % 3;
int j = i - d + ( d == 0 );
int k = i - d + 2 - ( d == 2 );
or following statement for k could be more readable:
int k = i - d + ( d == 2 ? 1 : 2 );
This should do it:
int j(int i)
{
int div = i / 3;
if (i%3 != 0)
return 3*div;
else
return 3*div+1;
}
int k(int i)
{
int div = i / 3;
if (i%3 != 2)
return 3*div+2;
else
return 3*div+1;
}
Test.
If you want shorter functions:
int j(int i)
{
return i/3*3 + (i%3 ? 0 : 1);
}
int k(int i)
{
return i/3*3 + (i%3-2 ? 2 : 1);
}
Well, first, notice that
j(i) == j(3+i) == j(6+i) == j(9+i) == ...
k(i) == k(3+i) == k(6+i) == k(9+i) == ...
In other words, you only need to find a formula for
j(i), i = 0, 1, 2
k(i), i = 0, 1, 2
and then for the rest of the cases simply plug in i mod 3.
From there, you'll have trouble finding a simple formula because your "rotation" isn't standard. Instead of
i j(i) k(i)
0 1 2
1 2 0
2 0 1
for which the formula would have been
j(i) = (i + 1) % 3
k(i) = (i + 2) % 3
you have
i j(i) k(i)
0 1 2
1 0 1
2 0 2
for which the only formula I can think of at the moment is
j(i) = (i == 0 ? 1 : 0)
k(i) = (i == 1 ? 1 : 2)
If the values of your array (let's call it arr, not i in order to avoid confusion with the index i) do not coincide with their respective index, you have to perform a reverse lookup to figure out their index first. I propose using an std::map<int,size_t> or an std::unordered_map<int,size_t>.
That structure reflects the inverse of arr and you can extra the index for a particular value with its subscript operator or the at member function. From then, you can operate purely on the indices, and use modulo (%) to access the previous and the next element as suggested in the other answers.

problem in dynamic allocation of 3-dimensional array

array_2D = new ushort * [nx];
// Allocate each member of the "main" array
//
for (ii = 0; ii < nx; ii++)
array_2D[ii] = new ushort[ny];
// Allocate "main" array
array_3D = new ushort ** [numexp];
// Allocate each member of the "main" array
for(kk=0;kk<numexp;kk++)
array_3D[kk]= new ushort * [nx];
for(kk=0;kk<numexp;kk++)
for(ii=0;ii<nx;ii++)
array_3D[kk][ii]= new ushort[ny];
the values of numexp,nx and ny is obtained by user..
Is this the correct form for dynamic allocation for a 3d array....We know that the code is working for the 2D array...If this is not correct can anyone suggest a better method?
I think the simplest way to allocate and deal with a multidimensional array is to use one big 1d array (or better yet a std::vector) and provide an interface to index into correctly.
This is easiest to think about first in 2 dimensions. Consider a 2D array with "x" and "y" axis
x=0 1 2
y=0 a b c
1 d e f
2 g h i
We can represent this using a 1-d array, rearranged as follows:
y= 0 0 0 1 1 1 2 2 2
x= 0 1 2 0 1 2 0 1 2
array: a b c d e f g h i
So our 2d array is simply
unsigned int maxX = 0;
unsigned int maxY = 0;
std::cout << "Enter x and y dimensions":
std::cin << maxX << maxY
int array = new int[maxX*maxY];
// write to the location where x = 1, y = 2
int x = 1;
int y = 2;
array[y*maxX/*jump to correct row*/+x/*shift into correct column*/] = 0;
The most important thing is to wrap up the accessing into a neat interface so you only have to figure this out once
(In a similar way we can work with 3-d arrays
z = 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
y = 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 0 0 0 1 1 1 2 2 2
x = 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
array: a b c d e f g h i j k l m n o p q r s t u v w x
Once you figure out how to index into the array correctly and put this code in a common place, you don't have to deal with the nastiness of pointers to arrays of pointers to arrays of pointers. You'll only have to do one delete [] at the end.
Looks fine too me, so long an array of arr[numexp][nx][ny] is what you wanted.
A little tip: you can put the allocation of the third dimension into the loop of the second dimension, aka you allocate each 3rd dimension while the parent subarray gets allocated:
ushort*** array_3D = new ushort**[nx];
for(int i=0; i<nx; ++i){
array_3D[i] = new ushort*[ny];
for(int j=0; j<ny; ++j)
array_3D[i][j] = new ushort[nz];
}
And of course, the general hint: Do that with std::vectors to not have to deal with that nasty (de)allocation stuff. :)
#include <vector>
int main(){
using namespace std;
typedef unsigned short ushort;
typedef vector<ushort> usvec;
vector<vector<usvec> > my3DVector(numexp, vector<usvec>(nx, vector<ushort>(ny)));
// size of -- dimension 1 ^^^^^^ -- dimension 2 ^^ --- dimension 3 ^^
}

Direct formula for summing XOR

I have to XOR numbers from 1 to N, does there exist a direct formula for it ?
For example if N = 6 then 1^2^3^4^5^6 = 7 I want to do it without using any loop so I need an O(1) formula (if any)
Your formula is N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ):
int main()
{
int S = 0;
for (int N = 0; N < 50; ++N) {
S = (S^N);
int check = N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) );
std::cout << "N = " << N << ": " << S << ", " << check << std::endl;
if (check != S) throw;
}
return 0;
}
Output:
N = 0: 0, 0 N = 1: 1, 1 N = 2: 3, 3
N = 3: 0, 0 N = 4: 4, 4 N = 5: 1, 1
N = 6: 7, 7 N = 7: 0, 0 N = 8: 8, 8
N = 9: 1, 1 N = 10: 11, 11 N = 11: 0, 0
N = 12: 12, 12 N = 13: 1, 1 N = 14: 15, 15
N = 15: 0, 0 N = 16: 16, 16 N = 17: 1, 1
N = 18: 19, 19 N = 19: 0, 0 N = 20: 20, 20
N = 21: 1, 1 N = 22: 23, 23 N = 23: 0, 0
N = 24: 24, 24 N = 25: 1, 1 N = 26: 27, 27
N = 27: 0, 0 N = 28: 28, 28 N = 29: 1, 1
N = 30: 31, 31 N = 31: 0, 0 N = 32: 32, 32
N = 33: 1, 1 N = 34: 35, 35 N = 35: 0, 0
N = 36: 36, 36 N = 37: 1, 1 N = 38: 39, 39
N = 39: 0, 0 N = 40: 40, 40 N = 41: 1, 1
N = 42: 43, 43 N = 43: 0, 0 N = 44: 44, 44
N = 45: 1, 1 N = 46: 47, 47 N = 47: 0, 0
N = 48: 48, 48 N = 49: 1, 1 N = 50: 51, 51
Explanation:
Low bit is XOR between low bit and next bit.
For each bit except low bit the following holds:
if N is odd then that bit is 0.
if N is even then that bit is equal to corresponded bit of N.
Thus for the case of odd N the result is always 0 or 1.
edit
GSerg Has posted a formula without loops, but deleted it for some reason (undeleted now). The formula is perfectly valid (apart from a little mistake). Here's the C++-like version.
if n % 2 == 1 {
result = (n % 4 == 1) ? 1 : 0;
} else {
result = (n % 4 == 0) ? n : n + 1;
}
One can prove it by induction, checking all reminders of division by 4. Although, no idea how you can come up with it without generating output and seeing regularity.
Please explain your approach a bit more.
Since each bit is independent in xor operation, you can calculate them separately.
Also, if you look at k-th bit of number 0..n, it'll form a pattern. E.g., numbers from 0 to 7 in binary form.
000
001
010
011
100
101
110
111
You see that for k-th bit (k starts from 0), there're 2^k zeroes, 2^k ones, then 2^k zeroes again, etc.
Therefore, you can for each bit calculate how many ones there are without actually going through all numbers from 1 to n.
E.g., for k = 2, there're repeated blocks of 2^2 == 4 zeroes and ones. Then,
int ones = (n / 8) * 4; // full blocks
if (n % 8 >= 4) { // consider incomplete blocks in the end
ones += n % 8 - 3;
}
For odd N, the result is either 1 or 0 (cyclic, 0 for N=3, 1 for N=5, 0 for N=7 etc.)
For even N, the result is either N or N+1 (cyclic, N+1 for N=2, N for N=4, N+1 for N=6, N for N=8 etc).
Pseudocode:
if (N mod 2) = 0
if (N mod 4) = 0 then r = N else r = N+1
else
if (N mod 4) = 1 then r = 1 else r = 0
Lets say the function that XORs all the values from 1 to N be XOR(N), then
XOR(1) = 000 1 = 0 1 ( The 0 is the dec of bin 000)
XOR(2) = 001 1 = 1 1
XOR(3) = 000 0 = 0 0
XOR(4) = 010 0 = 2 0
XOR(5) = 000 1 = 0 1
XOR(6) = 011 1 = 3 1
XOR(7) = 000 0 = 0 0
XOR(8) = 100 0 = 4 0
XOR(9) = 000 1 = 0 1
XOR(10)= 101 1 = 5 1
XOR(11)= 000 0 = 0 0
XOR(12)= 110 0 = 6 0
I hope you can see the pattern. It should be similar for other numbers too.
Try this:
the LSB gets toggled each time the N is odd, so we can say that
rez & 1 == (N & 1) ^ ((N >> 1) & 1)
The same pattern can be observed for the rest of the bits.
Each time the bits B and B+1 (starting from LSB) in N will be different, bit B in the result should be set.
So, the final result will be (including N): rez = N ^ (N >> 1)
EDIT: sorry, it was wrong. the correct answer:
for odd N: rez = (N ^ (N >> 1)) & 1
for even N: rez = (N & ~1) | ((N ^ (N >> 1)) & 1)
Great answer by Alexey Malistov! A variation of his formula: n & 1 ? (n & 2) >> 1 ^ 1 : n | (n & 2) >> 1 or equivalently n & 1 ? !(n & 2) : n | (n & 2) >> 1.
this method avoids using conditionals F(N)=(N&((N&1)-1))|((N&1)^((N&3)>>1)
F(N)= (N&(b0-1)) | (b0^b1)
If you look at the XOR of the first few numbers you get:
N | F(N)
------+------
0001 | 0001
0010 | 0011
0011 | 0000
0100 | 0100
0101 | 0001
0110 | 0111
0111 | 0000
1000 | 1000
1001 | 0001
Hopefully you notice the pattern:
if N mod 4 = 1 than F(N)=1
if N mod 4 = 3 than F(N)=0
if N mod 4 = 0 than F(N)=N
if N mod 4 = 2 than F(N)=N but with the first bit as 1 so N|1
the tricky part is getting this in one statement without conditionals ill explain the logic I used to do this.
take the first 2 significant bits of N call them:
b0 and b1 and these are obtained with:
b0 = N&1
b1 = N&3>>1
Notice that if b0 == 1 we have to 0 all of the bits, but if it isn't all of the bits except for the first bit stay the same. We can do this behavior by:
N & (b0-1) : this works because of 2's complement, -1 is equal to a number with all bits set to 1 and 1-1=0 so when b0=1 this results in F(N)=0.. so that is the first part of the function:
F(N)= (N&(b0-1))...
now this will work for for N mod 4 == 3 and 0, for the other 2 cases lets look solely at b1, b0 and F(N)0:
b0|b1|F(N)0
--+--+-----
1| 1| 0
0| 0| 0
1| 0| 1
0| 1| 1
Ok hopefully this truth table looks familiar! it is b0 XOR b1 (b1^b0). so now that we know how to get the last bit let put that on our function:
F(N)=(N&(b0-1))|b0^b1
and there you go, a function without using conditionals. also this is useful if you want to compute the XOR from positive numbers a to b. you can do:
F(a) XOR F(b).
With minimum change to the original logic:
int xor = 0;
for (int i = 1; i <= N; i++) {
xor ^= i;
}
We can have:
int xor = 0;
for (int i = N - (N % 4); i <= N; i++) {
xor ^= i;
}
It does have a loop but it would take a constant time to execute. The number of times we iterate through the for-loop would vary between 1 and 4.
How about this?
!(n&1)*n+(n%4&n%4<3)
This works fine without any issues for any n;
unsigned int xorn(unsigned int n)
{
if (n % 4 == 0)
return n;
else if(n % 4 == 1)
return 1;
else if(n % 4 == 2)
return n+1;
else
return 0;
}
Take a look at this. This will solve your problem.
https://stackoverflow.com/a/10670524/4973570
To calculate the XOR sum from 1 to N:
int ans,mod=N%4;
if(mod==0) ans=N;
else if(mod==1) ans=1;
else if(mod==2) ans=N+1;
else if(mod==3) ans=0;
If still someone needs it here simple python solution:
def XorSum(L):
res = 0
if (L-1)%4 == 0:
res = L-1
elif (L-1)%4 == 1:
res = 1
elif (L-1)%4 == 2:
res = (L-1)^1
else: #3
res= 0
return res