Print integer from array A based on array B integer? - c++

New to C++. I am looking for advise on the approach to this problem.
Given the following array:
Array A
1 21 43 54 99
Array B
1 4 5
What I want to achieve:
Array B integer is use to find the position of the value in array A. The end result, using the above two array, will be
End result
1 54 99
Where array B 1 will extract 1 from array A, array B 4 will extract out 54 from array A and so on. How should I approach this problem?

So you can iterate over arrB and get the desired values by doing the following:
#include <iostream>
int main(){
int arrA[] = {1, 21, 43, 54, 99};
int arrB[] = {1, 4, 5};
// iterating over arrB
for (int i = 0; i < 3; ++i)
std::cout << arrA[arrB[i] - 1] << ' ';
return 0;
}
Output :
1 54 99
Note :
Don't forget to add the required conditions (ensure accessing array within bounds) to escape from the undefined behavior.

Related

C++ 2D Vector initialization with another vector

vector<vector<double>> weights
{
{1},
{1}
};
Above is my code to make a 2x1 vector each holding 1.
I would like to make a matrix of 2xN that I could use to multiply with that vector.
I have seen other stackoverflow questions that talk about creating matrices, and most of the ones I've seen are with fixed values, or user input.
But what I would like to do, is initialize the entire first column of N length with 1s, and the initialize the entire second column with a second vector I already have.
I am unsure how in C++ I could accomplish this. I'm way more familiar with R, and in R this is a pretty simple task. Any thoughts or guidance?
You mean like this?
std::vector<int> vinner {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
std::vector<std::vector<int>> v {
std::vector<int>(10, 1),
vinner
};
int main(int argc, char **argv)
{
for (auto i : v) {
for (auto j : i) {
std::cout << j << " ";
}
std::cout << "\n";
}
return 0;
}
Output:
$ clang++ -o vect vect.cpp -std=c++17
$ ./vect
1 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10

array behaviour with auto and decltype

Can someone please explain me what's actually happening in the following code:-
#include<iostream>
using std::cout;
using std::endl;
int main(){
int ia[]= {2,1,2,3,4,6,6,7,8,9};
auto ia2(ia);
*ia2= 19;
for(auto i : ia){
cout<<ia[i] << " " ;
}
//now my new ia = {5,1,2,3,4,6,6,7,8,9};
decltype(ia) ia3= {0,1,2,3,4};
for(auto i : ia3){
cout<<ia[i] << endl ;
}
return 0;
}
My output is coming as follows :-
21949 1 2 3 4 6 6 7 8 9 19
1
2
3
4
19
19
19
19
19
I am all confused, first of all I created an array ia with 2,1,2,3,4,6,6,7,8,9
then I learned with auto you're actually creating pointer to the first element
then I changed the value at first element by using *ia2= 19 which should have changed the value of 2 to 19 then I used for range loop to display the elements in ia array I used decltype as it doesn't create pointers but instead create an array. I again used for range loop to display elements but of ia instead of ia3 and I don't understand how I am getting output like this. Can somebody please let me understand this code.

C++ negative array indices

I want to loop an array then during each loop I want to loop backwards over the previous 5 elements.
So given this array
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
and this nested loop
for(int i=0;i<arr.size;i++)
{
for(int h=i-5; h<i; h++)
{
//things happen
}
}
So, if i=0, second loop would loop last few elements 4,6,2,6,5.
How could you handle this?
I'm assuming that:
You only want to go over previous values (i.e. no wrap around) You
You don't actually want arr to be a multi-dimensional array as suggested
by your choice of tags
You want to include the current i in your five values
This is just a small modification to your code that will do (what I think) you are asking:
#include <math>
int main()
{
int arr[24]={3, 1, 4, 1, 7, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}
for(int i=0;i<arr.size;i++)
{
for(int h = max(i-4, 0); h < i+1; h++)
{
//things happen
}
}
}
note the h = max(i-4, 0) and h < i+1This will reduce the number of iterations of the inner loop so that it starts from index 0 and loops up through the five values up to and including i. (four values and i). h will always be within bounds.
The case where i==arr.size won't be a problem in the inner loop as the outer loop will terminate before that happens (i is always within bounds).
Edit: I saw this comment:
I want the first element to consider the last final 5 elements of the array though.
in which case, your loops should look like:
for(int i=0;i<arr.size;i++)
{
for(int h=0; h<5; h++)
{
int index = (i + arr.size - h) % arr.size;
//things happen
//access array with arr[index];
}
}
This should do what you want:
When i=0, h=0 index=(0+24-0)%24 which is 0. For h=1 we go one less, index=(0+24-1)%24 = 23 and so on for the next values of h.
The code gets the last 5 values, wrapping round, inclusive of the current value. (so will get 20,21,22,23,0 when i=0, 21,22,23,0,1 when i=1)
If you want the five before, non-inclusive, then inner loop should be:
for(int h=1; h<=5; h++)
here is the current output of the loop as it stands:
i 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 ... 22 22 22 22 22 23 23 23 23 23
h 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 ... 0 1 2 3 4 0 1 2 3 4
index 0 23 22 21 20 1 0 23 22 21 2 1 0 23 22 3 2 1 0 23 ... 22 21 20 19 18 23 22 21 20 19
I assume you want it to loop around (don't know why). if so, use modulo:
int index = (h + arr.size) % arr.size;
Using the modulo operator.
for (int i = 0; i < arr.size; i++)
{
for (int h = 5; h > 0; h--)
{
const int array_length = sizeof(arr) / sizeof(arr[0]);
int index = (i - h + array_length) % array_length; // Use 'sizeof(arr) / sizeof(arr[0])' to get the size of the array
//things happen
}
}
Is using if statement not an option?
const int array_size = 24;
int arr[array_size] = { 1,3,4,5,...,2 }
for(int i=0;i<array_size;i++)
{
for(int h=i-5; h<i; h++)
{
int arr_index = (h >= 0) ? h : (array_size + h);
//do your things with arr[arr_index]
}
}
you may also start the nested loop with something like:
for(int h=i-min(i,5);h<i;++h)
{
}
which let you process first 5 cells as well. also, if you are dealing with some kind of signal or image processing consider extending arr to have 29 elements with preceding 5 zeros or whatever value would be suitable, and start the first for-loop with 5th element.
Just make an if statement in nested loop. Something like this
for( int h = i-5; h < i; h++ )
{
// do stuff
if( i == 0 )
break;
}

What is the idea of a good random numbers generator?

I am writing a program for card games. There can be several game players (say, from 2 to 7). A deck consists of 54 cards. I need to distribute/deal cards to the players randomly.
We can consider the deck of 54 cards as a char array of 54 elements. Let us suppose that in a certain game each player must be given with 6 cards. The number of players is 2. So, it is necessary to generate two arrays, each of them consists of 6 elements selected from a "big" array of 54 elements. Moreover, in those two generated arrays there should not be shared/duplicate elements.
I tried a recursive algorithm to obtain a sequence of m unique random numbers from 0 to (m - 1).
X(n+1) = (a * X(n) + c) mod m
You need to set the parameters:
m -- module, m > 0
a -- factor, 0 <= a < m
c -- increment, 0 <= c < m
X(0) -- initial value , 0 <= X(0) < m
Numbers c and m must be coprime.
(a - 1) is divisible by p for each prime p that is a divisor of m
If m is divisible by 4 then (a - 1) must be divisible by 4.
Here's the code for this algorithm. As you can see, the parameters a, c, m and X(0) satisfy the mentioned conditions.
int a = 13,
c = 11,
m = 54, // because the total number of cards is 54
x0 = 1;
int x[100];
x[0] = x0;
cout << x[0] << " ";
for (int i = 1; i < m; i++)
{
x[i] = (a * x[i - 1] + c) % m;
cout << x[i] << " ";
}
The result is: 1 24 53 52 39 32 49 0 11 46 15 44 43 30 23 40 45 2 37 6 35 34 21 14 31 36 47 28 51 26 25 12 5 22 27 38 19 42 17 16 3 50
13 18 29 10 33 8 7 48 41 4 9 20. Do you think it is random?
What can you say about this algorithm? In general, what should be the idea of ​​a random distribution of cards for each player?
You see, if I integrate this algorithm to my program, it will deal the same sequence of cards as it is shown above each time you launch the program (because the parameters do not change). So I will need to change a, m, c and X(0) between launches of my program. Then I will have another problem: how to set these parameters automatically (and randomly, too) so that they satisfy the necessary conditions (see the bulleted list above).
It seems to me like you're making an unnecessarily complex system.
A much simpler approach is to create an array of all of your elements, shuffle it, and then just remove elements one at a time.
A simple and efficient way of shuffling is to use a Fisher-Yates shuffle:
//Initialize an array/vector/etc. with all the possible values
for (int i = NUMBER_OF_ELEMENTS-1; i >= 0; i--)
{
//Pick a random integer j between 0 and i (inclusive)
//Swap elements i and j
}
Now, you can just iterate through the shuffled array, picking the next element every time you need a new card.
int pos = 0; //The position of the next card in the deck
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < NUMBER_OF_PLAYERS; j++)
{
player[j].addCard(deck[pos++])
}
}
Ideally, you would probably want to wrap some of this into classes, but I've left that out for brevity.
You cannot guarantee randomness the way you put it. It is a generated sequence with low informational enthropy - in other words it is easily hacked.
You can simply use standard rand() from stdlib http://www.cplusplus.com/reference/cstdlib/rand/.
I'd recommend using mt19937 comes with std in c++11 http://www.cplusplus.com/reference/random/mt19937/ or boost one as mentioned in comments.
another way to do it, could be to randomize the action of taking a card instead of a shuffle the container.
something like this :
// first step
// init and fill container
std::vector<int> v;
for (int i = 0; i < 54; ++i)
v.push_back(i);
// second step
// take a random card
srand(time(NULL)); // init seed
int i = std::rand() % v.size();
int card = v[i]; // get card
v.erase(vec.begin() + i); // remove card from deck
return card;
for the second step, you need <ctime> and <cstdlib>. I am not sure it is better than the other solution. Just my two cents.

Distinguishing the values of three int's

I have three integer variables, that can take only the values 0, 1 and 2. I want to distinguish what combination of all three numbers I have, ordering doesn't count. Let's say the variables are called x, y and z. Then x=1, y=0, z=0 and x=0, y=1, z=0 and x=0, y=0, z=1 are all the same number in this case, I will refer to this combination as 001.
Now there are a hundred ways how to do this, but I am asking for an elegant solution, be it only for educational purposes.
I thought about bitwise shifting 001 by the amount of the value:
001 << 0 = 1
001 << 1 = 2
001 << 2 = 4
But then the numbers 002 and 111 would both give 6.
The shift idea is good, but you need 2 bits to count to 3. So try shifting by twice the number of bits:
1 << (2*0) = 1
1 << (2*1) = 4
1 << (2*2) = 16
Add these for all 3 numbers, and the first 2 bits will count how many 0 you have, the second 2 bits will count how many 1 and the third 2 bits will count how many 2.
Edit although the result is 6 bit long (2 bits per number option 0,1,2), you only need the lowest 4 bits for a unique identifier - as if you know how many 0 and 1 you have, then the number of 2 is determined also.
So instead of doing
res = 1<<(2*x);
res+= 1<<(2*y);
res+= 1<<(2*z);
you can do
res = x*x;
res+= y*y;
res+= z*z;
because then
0*0 = 0 // doesn't change result. We don't count 0
1*1 = 1 // we count the number of 1 in the 2 lower bits
2*2 = 4 // we count the number of 2 in the 2 higher bits
hence using only 4 bits instead of 6.
When the number of distinct possibilities is small, using a lookup table could be used.
First, number all possible combinations of three digits, like this:
Combinations N Indexes
------------- - ------
000 0 0
001, 010, 100 1 1, 3, 9
002, 020, 200 2 2, 6, 18
011, 101, 110 3 4, 10, 12
012, 021, 102, 120, 201, 210 4 5, 7, 11, 15, 19, 21
022, 202, 220 5 8, 20, 24
111 6 13
112, 121, 211 7 14, 16, 22
122, 212, 221 8 17, 23, 25
222 9 26
The first column shows identical combinations; the second column shows the number of the combination (I assigned them arbitrarily); the third column shows the indexes of each combination, computed as 9*<first digit> + 3*<second digit> + <third digit>.
Next, build a look-up table for each of these ten combinations, using this expression as an index:
9*a + 3*b + c
where a, b, and c are the three numbers that you have. The table would look like this:
int lookup[] = {
0, 1, 2, 1, 3, 4, 2, 4, 5, 1
, 3, 4, 3, 6, 7, 4, 7, 8, 2, 4
, 5, 4, 7, 8, 5, 8, 9
};
This is a rewrite of the first table, with values at the indexes corresponding to the value in the column N. For example, combination number 1 is founds at indexes 1, 3, and 9; combination 2 is at indexes 2, 6, and 18, and so on.
To obtain the number of the combination, simply check
int combNumber = lookup[9*a + 3*b + c];
For such small numbers, it would be easiest to just check them individually, instead of trying to be fancy, eg:
bool hasZero = false;
bool hasOne = false;
bool hasTwo = false;
// given: char* number or char[] number...
for(int i = 0; i < 3; ++i)
{
switch (number[i])
{
case '0': hasZero = true; break;
case '1': hasOne = true; break;
case '2': hasTwo = true; break;
default: /* error! */ break;
}
}
If I understand you correctly, you have some sequence of numbers that can either be 1, 2, or 3, where the permutation of them doesn't matter (just the different combinations).
That being the case:
std::vector<int> v{1, 2, 3};
std::sort(v.begin(), v.end());
That will keep all of the different combinations properly aligned, and you could easily write a loop to test for equality.
Alternatively, you could use a std::array<int, N> (where N is the number of possible values - in this case 3).
std::array<int, 3> a;
Where you would set a[0] equal to the number of 1s you have, a[1] equal to the number of '2's, etc.
// if your string is 111
a[0] = 3;
// if your string is 110 or 011
a[0] = 2;
// if your string is 100 or 010 or 001
a[0] = 1;
// if your string is 120
a[0] = 1;
a[1] = 1;
// if your string is 123
a[0] = 1;
a[1] = 1;
a[2] = 1;
If you are looking to store it in a single 32-bit integer:
unsigned long x = 1; // number of 1's in your string
unsigned long y = 1; // number of 2's in your string
unsigned long z = 1; // number of 3's in your string
unsigned long result = x | y << 8 | z << 16;
To retrieve the number of each, you would do
unsigned long x = result & 0x000000FF;
unsigned long y = (result >> 8) & 0x000000FF;
unsigned long z = (result >> 16) & 0x000000FF;
This is very similar to what happens in the RBG macros.
int n[3]={0,0,0};
++n[x];
++n[y];
++n[z];
Now, in the n array, you have a unique ordered combination of values for each unique unordered combination of x,y,z.
For example, both x=1,y=0,z=0 and x=0,y=0,z=1 will give you n={2,1,0}