Find a combination of elements from different arrays - c++

I recently started learning C++ and ran into problems with this task:
I am given 4 arrays of different lengths with different values.
vector<int> A = {1,2,3,4};
vector<int> B = {1,3,44};
vector<int> C = {1,23};
vector<int> D = {0,2,5,4};
I need to implement a function that goes through all possible variations of the elements of these vectors and checks if there are such values a from array A, b from array B, c from array C and d from array D that their sum would be 0(a+b+c+d=0)
I wrote such a program, but it outputs 1, although the desired combination does not exist.
using namespace std;
vector<int> test;
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <= A.size(); ai++){
test[0] = A[ai];
for ( int bi = 0; bi <= B.size(); bi++){
test[1] = B[bi];
for ( int ci = 0; ci <= C.size(); ci++){
test[2] = C[ci];
for ( int di = 0; di <= D.size(); di++){
test[3] = D[di];
if (sum (test) == 0){
return true;
}
}
}
}
}
}
I would be happy if you could explain what the problem is

Vectors don't increase their size by themself. You either need to construct with right size, resize it, or push_back elements (you can also insert, but vectors arent very efficient at that). In your code you never add any element to test and accessing any element, eg test[0] = A[ai]; causes undefined behavior.
Further, valid indices are [0, size()) (ie size() excluded, it is not a valid index). Hence your loops are accessing the input vectors out-of-bounds, causing undefined behavior again. The loops conditions should be for ( int ai = 0; ai < A.size(); ai++){.
Not returning something from a non-void function is again undefined behavior. When your abcd0 does not find a combination that adds up to 0 it does not return anything.
After fixing those issues your code does produce the expected output: https://godbolt.org/z/KvW1nePMh.
However, I suggest you to...
not use global variables. It makes the code difficult to reason about. For example we need to see all your code to know if you actually do resize test. If test was local to abcd0 we would only need to consider that function to know what happens to test.
read about Why is “using namespace std;” considered bad practice?
not pass parameters by value when you can pass them by const reference to avoid unnecessary copies.
using range based for loops helps to avoid making mistakes with the bounds.
Trying to change not more than necessary, your code could look like this:
#include <vector>
#include <iostream>
int sum (const std::vector<int>& v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(const std::vector<int>& A,
const std::vector<int>& B,
const std::vector<int>& C,
const std::vector<int>& D){
for (const auto& a : A){
for (const auto& b : B){
for (const auto& c : C){
for (const auto& d : D){
if (sum ({a,b,c,d}) == 0){
return true;
}
}
}
}
}
return false;
}
int main() {
std::vector<int> A = {1,2,3,4};
std::vector<int> B = {1,3,44};
std::vector<int> C = {1,23};
std::vector<int> D = {0,2,5,4};
std::cout << abcd0(A,B,C,D);
}
Note that I removed the vector test completely. You don't need to construct it explicitly, but you can pass a temporary to sum. sum could use std::accumulate, or you could simply add the four numbers directly in abcd0. I suppose this is for exercise, so let's leave it at that.

Edit : The answer written by #463035818_is_not_a_number is the answer you should refer to.
As mentioned in the comments by #Alan Birtles, there's nothing in that code that adds elements to test. Also, as mentioned in comments by #PaulMcKenzie, the condition in loops should be modified. Currently, it is looping all the way up to the size of the vector which is invalid(since the index runs from 0 to the size of vector-1). For implementing the algorithm that you've in mind (as I inferred from your code), you can declare and initialise the vector all the way down in the 4th loop.
Here's the modified code,
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <A.size(); ai++){
for ( int bi = 0; bi <B.size(); bi++){
for ( int ci = 0; ci <C.size(); ci++){
for ( int di = 0; di <D.size(); di++){
vector<int> test = {A[ai], B[bi], C[ci], D[di]};
if (sum (test) == 0){
return true;
}
}
}
}
}
return false;
}
The algorithm is inefficient though. You can try sorting the vectors first. Loop through the first two of them while using the 2 pointer technique to check if desired sum is available from the remaining two vectors

It looks to me, like you're calling the function every time you want to check an array. Within the function you're initiating int sum_of_elements = 0;.
So at the first run, you're starting with int sum_of_elements = 0;.
It finds the element and increases sum_of_elements up to 1.
Second run you're calling the function and it initiates again with int sum_of_elements = 0;.
This is repeated every time you're checking the next array for the element.
Let me know if I understood that correctly (didn't run it, just skimmed a bit).

Related

Error when using std::vector::size to create another vector

I am learning DSA and while practising my LeetCode questions I came across a question-( https://leetcode.com/problems/find-pivot-index/).
Whenever I use vector prefix(size), I am greeted with errors, but when I do not add the size, the program runs fine.
Below is the code with the size:
class Solution {
public:
int pivotIndex(vector<int>& nums) {
//prefix[] stores the prefix sum of nums[]
vector<int> prefix(nums.size());
int sum2=0;
int l=nums.size();
//Prefix sum of nums in prefix:
for(int i=0;i<l;i++){
sum2=sum2+nums[i];
prefix.push_back(sum2);
}
//Total stores the total sum of the vector given
int total=prefix[l-1];
for(int i=0; i<l;i++)
{
if((prefix[i]-nums[i])==(total-prefix[i]))
{
return i;
}
}
return -1;
}
};
I would really appreciate if someone could explain this to me.
Thanks!
You create prefix to be the same size as nums and then you push_back the same number of elments. prefix will therefore be twice the size of nums after the first loop. You never access the elements you've push_backed in the second loop so the algorithm is broken.
I suggest that you simplify your algorithm. Keep a running sum for the left and the right side. Add to the left and remove from the right as you loop.
Example:
#include <numeric>
#include <vector>
int pivotIndex(const std::vector<int>& nums) {
int lsum = 0;
int rsum = std::accumulate(nums.begin(), nums.end(), 0);
for(int idx = 0; idx < nums.size(); ++idx) {
rsum -= nums[idx]; // remove from the right
if(lsum == rsum) return idx;
lsum += nums[idx]; // add to the left
}
return -1;
}
If you use vector constructor with the integer parameter, you get vector with nums.size() elements initialized by default value. You should use indexing to set the elements:
...
for(int i = 0; i < l; ++i){
sum2 = sum2 + nums[i];
prefix[i] = sum2;
}
...
If you want to use push_back method, you should create a zero size vector. Use the constructor without parameters. You can use reserve method to allocate memory before adding new elements to the vector.

Solution for maximum xor secondary in an array of integers

I am trying to solve this codeforces problem
http://codeforces.com/contest/281/problem/D
Given an array of integers, find the maximum xor of the first and second max element in any of the sub sequences ?
I am not able to figure out the optimal approach to solve this problem. Few of the solving techniques I articulated was using sorting, stack but I could not figure out the right solution.
I googled and found out the problem setter's code for the solution. But I could not understand the solution as it is in c++ and I am naive to it.
Below is the problem setter's code in c++
using namespace std;
using namespace io;
typedef set<int> Set;
typedef set<int, greater<int> > SetRev;
namespace solution {
const int SIZE = 100000 + 11;
int n;
int A[SIZE];
II S[SIZE];
Set P;
SetRev P_rev;
int result;
}
namespace solution {
class Solver {
public:
void solve() {
normalize();
result = get_maximum_xor();
}
int get_maximum_xor() {
int res = 0;
for (int i = 0; i < n; i++) {
int current_value = S[i].first;
Set::iterator it_after = P.upper_bound(S[i].second);
Set::iterator it_before = P_rev.upper_bound(S[i].second);
if (it_after != P.end()) {
int after_value = A[*it_after];
res = max(res, current_value ^ after_value);
}
if (it_before != P_rev.end()) {
int before_value = A[*it_before];
res = max(res, current_value, before_value);
}
P.insert(S[i].second);
P_rev.insert(S[i].second);
}
return res;
}
void normalise() {
for (int i = 0; i < n; i++) {
S[i] = II(A[i], i);
}
sort(S, S + n, greater<II>());
}
}
Can someone please explain me the solution, the approach used as I understand it in pieces and not totally ?
Ok, so Solver::solve() starts by calling normalise:
void normalise() {
for (int i = 0; i < n; i++) {
S[i] = II(A[i], i);
}
sort(S, S + n, greater<II>());
}
What that's doing is taking an array A of integers - say {4, 2, 9}, and populating an array S where A's values are sorted and paired with the index at which they appear in A - for our example, {{2, 1}, {4, 0}, {9, 2}}.
Then the solver calls get_maximum_xor()...
for (int i = 0; i < n; i++) {
int current_value = S[i].first;
Set::iterator it_after = P.upper_bound(S[i].second);
Set::iterator it_before = P_rev.upper_bound(S[i].second);
The "for i" loop is used to get successive sorted values from S (those values originally from A). While you haven't posted a complete program, so we can't know for sure nothing's prepopulating any values in P, I'll assume that. We do know P's is a std::map and upper_bound searches to find the first element in P greater than S[i].second (the index at which current_value appeared in A) and values above, then something similar for P_rev which is a std::map in which values are sorted in descending order, likely it will be kept populated with the same values as P but again we don't have the code.
Then...
if (it_after != P.end()) {
int after_value = A[*it_after];
res = max(res, current_value ^ after_value);
}
...is saying that if any of the values in P were >= S[i].second, look up A at the index it_after found (getting a sense now that P tracks the last elements in each subsequence (?)), and if the current_value XORed with that value from A is more than any earlier result candidate (res), then update res with the new larger value.
It does something similar with P_rev.
Finally...
P.insert(S[i].second);
P_rev.insert(S[i].second);
Adds the index of current_value in A to P and P_rev for future iterations.
So, while I haven't explained why or how the algorithm works (I haven't even read the problem statement), I think that should make it clear what the C++ is doing which is what you said you're struggling with - you're on your own for the rest ;-).

Fastest method to check if all elements of 2d array are equal

I have a 2d array houses[5][2] = {{1,1},{1,1},{1,1},{1,1},{1,1}}
What is the fastest way to check if all the elements inside that array are equal?
Here is what I have tried so far:
```
for(int j=0;j<5;j++){
for(int k=0;k<6;k++){
if(houses[j][k] == houses[j+1][k+1] && j+1 != 5 && k + 1 != 6)
equal = true;
else{
equal = false;
break;
}
}
}
This won't compare all the elements tho, I know how to compare all of them, but it seems to be a very long loop .. is there a faster way to do that?
Your current code will fail because break will only take you out of one loop. You must exit both, which requires a second check, like so:
auto the_value = houses[0][0];
bool equal = true;
for(int j=0;j<5;j++){
for(int k=0;k<6;k++){
if(houses[j][k]!=the_value){
equal = false;
goto done;
}
}
if(!equal)
break
}
(Storing the first element in a variable and then looping over all of the elements to check to see if they are equal to that variable obviates the mess you invoke by checking adjacent elements.)
Breaking out of both loops simultaneously requires the Dark Arts (goto), but may be more readable/maintainable if you are disciplined and may be slightly faster, depending on your compiler:
auto the_value = houses[0][0];
bool equal = true;
for(int j=0;j<5;j++)
for(int k=0;k<6;k++)
if(houses[j][k]!=the_value){
equal = false;
goto done; //Danger, Will Robinson!
}
done:
//More stuff
You may find a flat array to be faster:
auto the_value = houses[0][0];
bool equal = true;
for(int i=0;i<5*6;i++)
if(houses[i]!=the_value){
equal = false;
break;
}
The 2D array is stored as a 1D contiguous array in memory. Using flat array addressing accesses the same memory locations, but explicitly avoids forcing the internal arithmetic. For highly performant code you may wish to consider using flat arrays by default.
Since you might use a function such as this a number of times or have it embedded in otherwise complex code, perhaps you'd like to abstract it:
template<class T>
bool AllEqual(const T& arr, size_t N){
T the_value = arr[0];
for(int i=0;i<N;i++)
if(arr[i]!=the_value)
return false;
return true;
}
AllEqual(houses, 5*6);
Since you're coding in C++, you probably don't want to be using raw arrays anyway. Let's rewrite your code using the STL, assuming flat arrays:
template<class T>
bool AllEqual(const std::vector<T>& arr){
return std::all_of(arr.begin(), arr.end(), [&](const T& x){ return x==arr[0]; });
}
std::vector<int> houses = {}; //Replace with appropriate initialization
if(AllEqual(houses))
//Do stuff
(Also: as another answerer mentioned, the way you are adding data to your array seems to imply that it should be 2x6/6x2 array instead of 5x6/6x5.)
First, do you understand what your array looks like? You have 6 times of two ones, but you used houses[5][6]. That's it 5 rows and 6 columns. You should have gotten an error for that:
main.cpp:5:55: error: excess elements in array initializer
int houses[5][6] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}};
^~~~~
What you really wanted was 6 rows and 2 columns.
As for the way of checking whether all elements of a 2D array are equal, I would follow a simple approach; store the first element of your array to a variable, e.g. named v, and check that value versus all the other elements. If it is not equal to just one element, then it is enough to take a decision and say that not all elements are equal, like in the following example:
#include <iostream>
bool allEqual(int arr[][2], int rows)
{
int v = arr[0][0];
for(int i = 0; i < rows; ++i)
for(int j = 0; j < 2; ++j)
if(v != arr[i][j])
return false;
return true;
}
int main(void)
{
int houses[6][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}};
allEqual(houses, 6) ? std::cout << "All " : std::cout << "Not all ";
std::cout << "elements are equal\n";
return 0;
}
If I emulate a 2D array with an 1D, will it be faster?
I doubt it. They idea is that the memory locations will be contiguous, but this is what happens pretty most in the 2D case, given that the rows are more than the columns.
Here is my experiment:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x -O3 -o 2d 2d.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./2d
2D array took 1.48e-10 seconds.
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x -O3 -o 1d 1d.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./1d
Emulating 2D array with 1D array took 1.5e-10 seconds.
and my code, based on my Time measurements (C++):
#include <iostream>
#define ROWS 10000
#define COLS 20
#define REPEAT 1000
#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>
bool allEqual(int* arr, const int size)
{
int v = arr[0];
for(int i = 0; i < size; ++i)
if(v != arr[i])
return false;
return true;
}
void fill(int* arr, const int size)
{
for(int i = 0; i < size; ++i)
arr[i] = 1;
}
int main(void)
{
const int size = ROWS * COLS;
int houses[size];
fill(houses, size);
bool equal;
using namespace std::chrono;
high_resolution_clock::time_point t1 = high_resolution_clock::now();
for(int i = 0; i < REPEAT; ++i)
equal = allEqual(houses, size);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "Emulating 2D array with 1D array took " << time_span.count()/(double)REPEAT << " seconds.\n";
return 0;
}
where the 2d.cpp is the straightforward way.
Using the equal method provided in this answer for a 2D array, the timings reported are similar.
Moreover, there is std::equal, which is comparable in terms of performance to my code above, reporting a time of:
std::equal with 2D array took 1.63e-10 seconds.
It's complexity is: "Up to linear in the distance between first1 and last1: Compares elements until a mismatch is found."
Summary:
std::equal does OK, and requires the less effort from the programmer, thus use it.
Multiple things:
First, as others have pointed out, the line:
int houses[5][6] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}};
Is wrong, the left hand side declares an array with 5 rows and 6 columns, but the right hand side constitutes an array of 6 rows and 2 columns.
On the general case comparing all elements of a 2d array (or even a 1d array) is in O(n) since for every element you must check all other elements. You can optimize it a little bit but it will still be an O(n) algorithm. On the most general case:
A[n][m] is an array of n rows and m columns
for(int i=0; i<n*m; i++)
{
if(A[0][0] != A[i/n][i%n])
return false;
}
return true;
This may seem a little bit confusing so let me explain:
a 2d array has n*m elements, so an easy way to see all of them in a single loop is doing [i/n] (if i < n, then it's the first row, if n < i < 2n then it's the second row...) and doing [i%n] gives you the remainder. This way we can iterate the entire array in a single loop.
Since we want all elements to be the same, if the first element is equal to all others then they are ll the same, if at least on is different then they are not all the same.
The fastest way:
int houses[6][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,2}};
int equals()
{
int *p = (int *)houses;
int *end = p + 6*2;
int v = *p++;
for(; p < end; p++)
if (*p != v)
return 0;
return 1;
}
I wrote it for fun, don't use that in production.
Instead, iterate through them all:
int equals() {
int v = houses[0][0];
for(int j=0;j<5;j++)
for(int k=0;k<6;k++)
if (houses[i][j] != v)
return false;
return true;
}
We can simply way to check if all the elements inside that array are equal
or not. just assign the first row & column element in a variable. Then compare each element. If not equal then return false.
Code Snippet :
bool Equal(int **arr, int row, int col)
{
int v = arr[0][0];
for(int i=0; i<row; i++)
{
for(int k=0; k<col; k++)
{
if(arr[i][k]!=v) return false;
}
}
return true;
}

how to avoid this for-loop mess in c++?

I need to program all possible sets of numbers from 1 to N for an arbitrary number m of integers without permutation.
Since I don't know how to explain it better here are some examples:
for m = 2
vector<vector<int>> box;
int N = 5;
for(int i = 1; i <= N; i++) {
for(int j = N; j >= i; j--) {
vector<int> dummy;
dummy.push_back(i);
dummy.push_back(j);
box.push_back(dummy);
}
}
for m = 3
vector<vector<int>> box;
int N = 5;
for(int i = 1; i <= N; i++) {
for(int j = N; j >= i; j--) {
for(int k = N; k >= j; k--) {
vector<int> dummy;
dummy.push_back(i);
dummy.push_back(j);
dummy.push_back(k);
box.push_back(dummy);
}
}
}
This works perfectly fine and the result is what I need. But like already mentioned, m can be arbitrary and I can't be bothered to implement this for m = 37 or what ever. N and m are known values but change while the program is running. There must be a better way to implement this than for the m = 37 case to implement a row of 37-for-loops. Can someone help me? I'm kind a clueless :\
edit: to explain better what I'm looking for here are some more examples.
Let's say N = 5 and m = 4, than 1223 is a feasible solution for me, 124 is not since it is to short. Let's say I already found 1223 as a solution, than I don't need 2123, 2213 or any other permutation of this number.
edit2: Or if you prefer a more visual (mathematical?) problem formulation here you go.
Consider m the dimension. With m been 2 you are left with a N size Matrix. I am looking for the upper (or lower) triangle of this Matrix including the diagonal. Let's move to m = 3, the Matrix becomes a 3 dimensional cube (or Tensor if you so wish), now I'm looking for the upper (or lower) tetrahedron including the diagonal-plain. For higher dimensions than 3 I'm looking for the hyper-tetrahedron of the hyper-cube including the hyper-diagonal-plane.
http://howardhinnant.github.io/combinations.html
The following generic algorithms permit a client to visit every combination or permuation of a sequence of length N, r items at time.
Example usage:
std::vector<std::vector<int>> box;
std::vector<int> v(N);
std::iota(begin(v), end(v), 1);
for_each_combination(begin(v), begin(v) + M, end(v), [](auto b, auto e) {
box.emplace_back(b, e);
return false;
});
The above code just shows inserting each combination into box as an example, but you probably don't want to actually do that: assuming that box is simply an intermediary and that your actual work then uses it somewhere else, you can avoid an intermediary and simply do whatever work you need directly in the body of the functor.
Here's a complete, working example using code from the provided link.
Since what you want is combinations with repetition rather than just combinations. Here's an example of implementing this on top of for_each_combination():
template<typename Func>
void for_each_combination_with_repetition(int categories, int slots, Func func) {
std::vector<int> v(slots + categories - 1);
std::iota(begin(v), end(v), 1);
std::vector<int> indices;
for_each_combination(begin(v), begin(v) + slots, end(v), [&](auto b, auto e) {
indices.clear();
int last = 0;
int current_element = 0;
for(;b != e; ++last) {
if (*b == last+1) {
indices.push_back(current_element);
++b;
} else {
++current_element;
}
}
func(begin(indices), end(indices));
return false;
});
}
The wikipedia article on combinations shows a good illustration of what this is doing: it's getting all the combinations (without repetition) of numbers [0, N + M - 1) and then looking for the 'gaps' in the results. The gaps represent transitions from repetitions of one element to repetitions of the next.
The functor you pass to this algorithm is given a range that contains indices into a collection containing the elements you're combining. For example if you want to get all sets of three elements from the set of {x,y}, the results are you want are {{x,x,x}, {x,x,y}, {x,y,y}, {y,y,y}}, and this algorithm represents this by returning ranges of indices into the (ordered) set {x,y}: {{0,0,0}, {0,0,1}, {0,1,1}, {1,1,1}}.
So normally to use this you have a vector or something containing your elements and use the ranges produced by this algorithm as indices into that container. However in your case, since the elements are just the numbers from 1 to N you can use the indices directly by adding one to each index:
for_each_combination_with_repetition(N, M, [&](auto b, auto e) {
for(; b != e; ++b) {
int index = *b;
std::cout << index + 1 << " ";
}
std::cout << '\n';
});
Complete example
An alternative implementation can return vectors that represent counts of each category. E.g. the earlier {{x,x,x}, {x,x,y}, {x,y,y}, {y,y,y}} results could be represented by: {{3,0} {2,1},{1,2}, {0,3}}. Modifying the implementation to produce this representation instead looks like this:
template<typename Func>
void for_each_combination_with_repetition(int categories, int slots, Func func) {
std::vector<int> v(slots + categories - 1);
std::iota(begin(v), end(v), 1);
std::vector<int> repetitions(categories);
for_each_combination(begin(v), begin(v) + slots, end(v), [&](auto b, auto e) {
std::fill(begin(repetitions), end(repetitions), 0);
int last = 0;
int current_element = 0;
for(;b != e; ++last) {
if (*b == last+1) {
++repetitions[current_element];
++b;
} else {
++current_element;
}
}
func(begin(repetitions), end(repetitions));
return false;
});
}
You can use recursion to find all subsets. This can probably be improved stylistically, but here is a quick take at the problem:
std::vector<std::set<int>> subsets(std::vector<int> x)
{
if (x.size() == 0)
return { std::set<int>() };
else
{
int last = x.back();
x.pop_back();
auto sets = subsets(x);
size_t n = sets.size();
for (size_t i = 0; i < n; i++)
{
std::set<int> s = sets[i];
s.insert(last);
sets.push_back(std::move(s));
}
return sets;
}
}
This doubles the number of answers at each recursion step : the number of subsets is 2^n, as expected.
You can substitute std::set for std::vector if you wish.

sorting an array and maintaining element's old index

I have an array A:
A = [10 11 3 15 8 7]
index = 0 1 2 3 4 5
I want to sort this array.After sorting I want the information of old index.For this I can create a structure like this.
struct VnI{
int value;
int index;
};
sorting the array of structure with respect to value solve my problem.But I want to know that is it possible to solve this using sort or any other function in C++11.
I have tried this way:
struct VnI{
int V;
int I;
};
bool comparator(VnI x,VnI y){
if(x.V < y.V)
return true;
return false;
}
int maximumGap(const vector<int> &A) {
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
sort(B.begin(),B.end(),comparator);
for(int i = 0;i < B.size();i++){
cout<<B[i].I<<" "<<B[i].V<<endl;
}
}
But I got runtime error.
Please help.
This code is wrong:
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
When you write B[i], it assumes that B is at least of size i+1. Since the maximum value of i (which you used an index to B) is A.size()-1. The assumption in your code is that B is at least of size A.size(). This assumption is wrong — the fact is that B is of size 0.
Unfortunately operator[] of std::vector doesn't check for out of range index. If you use at(), the code will throw std::out_of_range exception:
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B.at(i).I = i;
B.at(i).V = A[i];
}
Now this would throw std::out_of_range exception.
Anyway, one simple fix could be this:
vector<VnI> B (A.size()); //initialize B with the size of A.
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
However, I'd suggest this solution:
vector<VnI> B;
B.reserve(A.size());
for(int i = 0;i < A.size(); i++){
B.emplace_back(i, A[i]);
}
I'd also suggest you read more about std::vector, especially the following functions:
size()
capacity()
resize()
reserve()
push_back()
operator[]
at()
emplace_back()
and all the constructors.
Also, learn to naming your variables properly and be consistent with it.
Hope that helps.
do you pefer to use vector and pair?
each pair has "first" and "second", put "first"=value to sort,"second"=original index, create a pair for each element and put them into vector to sort:
int N[]={10,11,3,15,8,7};
std::vector<std::pair<int,int> > v;
//create pair for each element
for(int i=0;i<sizeof(N)/sizeof(int);i++){
//first is value of array,second is original index
v.push_back(std::make_pair(N[i],i));
}
//sort the vector of pair
sort(v.begin(),v.end());
//get original index from second of pair
for(std::pair<int,int>& p : v){
std::cout << p.first << ":" << p.second << std::endl;
}
output
3:2
7:5
8:4
10:0
11:1
15:3
Normally what is done is the opposite... i.e. given an array x of elements compute an array of integers ix so that x[ix[i]] appears to be sorted under a certain criteria.
This allows representing the container with different orderings without actually having to move/copy the elements.
With C++11 this can easily be done using lambdas:
// Build the index vector ix
std::vector<int> ix(x.size());
for (int i=0,n=x.size(); i<n; i++) ix[i] = i;
// Sort ix according to the corresponding values in x
// (without touching x)
std::sort(ix.begin(), ix.end(),
[&x](int a, int b) { return x[a] < x[b]; });
This ix index array is what you are asking for (i.e. the "old" position of an element: ix[i] is where the i-th element of the sorted list was in the original array) and there is no need to modify the input array.
You are trying to sort a list of custom objects, answerd here:
SO Link
Once you list the list of VnI objects you can then access there old index's through the I member that I presume is the index.