suppose you have three global vectors V1, V2, and V3.
suppose you have a function which performs a set of actions, such as VN[3]++, on one of the above vectors determined by an int value.
in python i would do something like:
global:
v1 = [1,2,3]
v2 = [1,2,3]
v3 = [1,2,3]
lists = [v1, v2, v3]
def function (determiner):
list = lists[determiner]
list[1] += 1...
I think in theory i could just have separate ifs for each possible value of determiner, but it seems like bad code to repeat a length of code multiple times.
(1) What is the correct way to approach this problem? I assume I would use pointers, but I've just learned about them today and i've been struggling to get my code to work. Here's a sample of the code i've been trying.
vector <int> counts0;
vector <int> counts1;
void editor(int determiner){
if (determiner == 1) {
vector<int> & count_l = counts1;
}
else if (determiner = 2) {
vector<int> & count_l = counts2;
}
count_l[5]++;
}
There are two ways to achieve this, depending on what you expect. If lists should reference the vectors, use pointers (as you said, just remember to dereference before indexing)
std::vector<int> a, b, c;
std::vector<std::vector<int>*> lists = {&a, &b, &c};
void editor(int determiner)
{
(*lists[determiner])[5]++;
}
If you want a copy of all vectors in list, don't use pointers (this can be expensive when you modify lists a lot, only use this approach with const data).
std::vector<std::vector<int>> lists = {{1, 2, 3}, {1, 2, 3}, {1, 2, 3}};
void editor(int determiner)
{
lists[determiner][5]++;
}
Related
I am trying to implement a bottom up approach function to the rod cutting problem and I need to use this particular pseudo-code from the CLRS textbook. In it there two functions and one calls the other in this fashion
(r,s) = EXTENDED-BOTTOM-UP-CUT-ROD(p,n)
Where r and s are two different arrays. The function also returns two arrays. I am currently using C++ and I've tried things such as
(r,s)=function(p,n);
[r,s]=function(p,n);
{r,s}=function(p,n);
//return statements follow similar attempts
return (r,s);
return {r,s};
return [r,s];
All these typically resulted in errors or incorrect outputs. Perhaps I shouldn't be using basic arrays for this implementation?
You can use tuples and "structured binding" in C++17 to return multiple values efficiently as below:
#include <tuple>
#invlude <vector>
std::tuple<std::vector<int>,std::vector<int>> func_that_returns_two_vectors() {
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {4, 5, 6};
return {std::move(v1), std::move(v2)};
}
int main() {
auto [v1, v2] = func_that_returns_two_vectors();
return 0;
}
To do something similar pre-C++17 you can use std::tie.
I want to rotate a subset of an vector inside the whole vector. The subset to be rotated is defined by another vector.
What I want to achieve is this:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
// ???
}
auto whole = std::vector<int> {1, 2, 3, 4, 5};
auto part = std::vector<int> { 2, 3, 4 };
auto part2 = std::vector<int> {1, 5};
rotateSubset(whole, part);
// whole is now 1, 3, 4, 2, 5;
rotateSubset(whole, part2);
// whole is now 5, 3, 4, 2, 1
The given subset is guaranteed to be contained by the larger whole set. The subset could be any subset of the whole, in any order; it need not be contiguous.
This is what I've tried so far:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
assert(subset.isSubsetOf(whole)); // don't worry about the implementation of this pseudo-code for now
std::rotate(subset.begin(), subset.end());
if (subset.size() == whole.size())
whole = subset;
else
{
// copy the subset vector into the whole vector in the new order
auto it = subset.cbegin();
for (auto& element : whole)
if (std::find(subset.cbegin(), subset.cend(), element) != subset.cend())
element = *it++;
}
}
This works, however it feels a bit sketchy to me. I was wondering if there was some neat way of using the Ranges library in C++20 to do it. Something like this:
// PSEUDO-CODE
auto subRange = std::ranges::views::subset(whole, part);
std::rotate(subRange.begin(), subRange.end());
I don't have a good knowledge of the Ranges library yet, but I think that something like this should be possible.
Please note: I want the solution to use a simple std::rotate() at some level. The reason for this is that I want to perform other similar functions on a sub-set as well (i.e. std::shuffle()), so the actual function that does the rotation / shuffling / whatever will be a variable in the final version. It's the "altering a subset" part that I'm really interested in here; the rest will come together later.
In C++, I can statically initialize an array, e.g.:
int a[] = { 1, 2, 3 };
Is there an easy way to initialize a dynamically-allocated array to a set of immediate values?
int *p = new int[3];
p = { 1, 2, 3 }; // syntax error
...or do I absolutely have to copy these values manually?
You can in C++0x:
int* p = new int[3] { 1, 2, 3 };
...
delete[] p;
But I like vectors better:
std::vector<int> v { 1, 2, 3 };
If you don't have a C++0x compiler, boost can help you:
#include <boost/assign/list_of.hpp>
using boost::assign::list_of;
vector<int> v = list_of(1)(2)(3);
You have to assign each element of the dynamic array explicitly (e.g. in a for or while loop)
However the syntax int *p = new int [3](); does initialize all elements to 0 (value initialization $8.5/5)
To avoid endless push_backs, I usually initialize a tr1::array and create a std::vector (or any other container std container) out of the result;
const std::tr1::array<T, 6> values = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(values.begin(), values.end());
The only annoyance here is that you have to provide the number of values explicitly.
This can of course be done without using a tr1::array aswell;
const T values[] = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(&values[0], &values[sizeof(values)/sizeof(values[0])]);
Althrough you dont have to provide the number of elements explicitly, I prefer the first version.
No, you cannot initialize a dynamically created array in the same way.
Most of the time you'll find yourself using dynamic allocation in situations where static initialization doesn't really make sense anyway. Such as when you have arrays containing thousands of items. So this isn't usually a big deal.
Using helper variable:
const int p_data[] = {1, 2, 3};
int* p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
or, one line
int p_data[] = {1, 2, 3}, *p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
Never heard of such thing possible, that would be nice to have.
Keep in mind that by initializing the array in the code that way
int a[] = { 1, 2, 3 };
..... only gains you easier code writing and NOT performance.
After all, the CPU will do the work of assigning values to the array, either way you do it.
I have a struct of the form
struct Thing {
std::vector<bool> A;
std::vector<int> B;
};
in the main the struct is created inside a for loop and used as the input to a function
for(int i=0;i<50;i++) {
Thing temporalthing;
temporalthing.A=A;
temporalthing.B=B;
temporalresult=fun1(temporalthing,data)
}
A and B are hardcoded into a series of vectors stored like this
std::vector<bool> A1{ 1,0,1};
std::vector<int> B1{ 2,1,3};
std::vector<bool> A2{ 0,1,1};
std::vector<int> B2{ 4,2,3}; ....
I want for each iteration of the for loop to take the corresponding value of A and B (loop 1 take A1 and B1, loop 2 take A2 and B2, ETC), if this were MATLAB this would be easy using reflection but I understand C++ does not have reflection, my other option would be to use a Switch Case structure of 50 different values that surely would work but I am not sure if this is the most optimal way to do it. Is there a better way?
I am new to C++ having a lot more experience with MATLAB but trying to learn... any help is very appreciated
My suggestion:
Change
temporalthing.A=A;
temporalthing.B=B;
to
temporalthing.A = getA(i);
temporalthing.B = getB(i);
The functions getA() and getB() can use whatever logic to return you an A and a B for the given i.
A simple implementation for getA() would be to store the various As in a vector.
std::vector<int>& getA(size_t i)
{
static std::vector<std::vector<int>> aList;
if ( aList.empty() )
{
// Fill up the list
aList[0] = {1, 0, 1};
aList[1] = {0, 1, 1};
// etc.
}
return aList[i];
}
Do the same thing for getB().
If getA() can use i to compute the return value, then, it does not have to store the As.
std::vector<int> getA(size_t i)
{
int v1 = func1(i);
int v2 = func2(i);
int v3 = func3(i);
return {v1, v2, v3};
}
What is the simplest way to convert array to vector?
void test(vector<int> _array)
{
...
}
int x[3]={1, 2, 3};
test(x); // Syntax error.
I want to convert x from int array to vector in simplest way.
Use the vector constructor that takes two iterators, note that pointers are valid iterators, and use the implicit conversion from arrays to pointers:
int x[3] = {1, 2, 3};
std::vector<int> v(x, x + sizeof x / sizeof x[0]);
test(v);
or
test(std::vector<int>(x, x + sizeof x / sizeof x[0]));
where sizeof x / sizeof x[0] is obviously 3 in this context; it's the generic way of getting the number of elements in an array. Note that x + sizeof x / sizeof x[0] points one element beyond the last element.
Personally, I quite like the C++2011 approach because it neither requires you to use sizeof() nor to remember adjusting the array bounds if you ever change the array bounds (and you can define the relevant function in C++2003 if you want, too):
#include <iterator>
#include <vector>
int x[] = { 1, 2, 3, 4, 5 };
std::vector<int> v(std::begin(x), std::end(x));
Obviously, with C++2011 you might want to use initializer lists anyway:
std::vector<int> v({ 1, 2, 3, 4, 5 });
Pointers can be used like any other iterators:
int x[3] = {1, 2, 3};
std::vector<int> v(x, x + 3);
test(v)
You're asking the wrong question here - instead of forcing everything into a vector ask how you can convert test to work with iterators instead of a specific container. You can provide an overload too in order to retain compatibility (and handle other containers at the same time for free):
void test(const std::vector<int>& in) {
// Iterate over vector and do whatever
}
becomes:
template <typename Iterator>
void test(Iterator begin, const Iterator end) {
// Iterate over range and do whatever
}
template <typename Container>
void test(const Container& in) {
test(std::begin(in), std::end(in));
}
Which lets you do:
int x[3]={1, 2, 3};
test(x); // Now correct
(Ideone demo)
One simple way can be the use of assign() function that is pre-defined in vector class.
e.g.
array[5]={1,2,3,4,5};
vector<int> v;
v.assign(array, array+5); // 5 is size of array.
One way can be to use the array's bound in one go like this:
int a[3] = {1, 2, 3};
vector<int> v(a, *(&a+1));