set multiple array variables at the same time (c++) - c++

I'm trying to make an ASCII art using C++, and having some problems in arrays.
Is there any way to set multiple array variables at the same time?
Let me be more specific.
When you initialize an array, you can do this way.
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
By the way shown above, you can set 10 array variables at the same time.
However, I want to (re) set some of the array variables like this?
a[1] = 3;
a[4] = 2;
a[5] = 2;
a[7] = 2;
Since there is NO rule in the variables, I can't do
for(int i=0; i<10; i++) a[i] = i+1;
fill(n);
I can't use an for statement or the fill, fill_n function, since there is no regularity.
To sum up,
Is there any way to set more than 1 array variables at the same time? (Like the second code snipplet above?

Given a index-value mapping list, and assign it one by one.
template<typename T, size_t N>
void Update(T(&arr)[N], const std::vector<std::pair<size_t, T>>& mappings)
{
for (const auto& mapping : mappings)
if(mapping.first < N)
arr[mapping.first] = arr[mapping.second];
}
int main()
{
int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Update(arr, { {1, 3}, {4, 2}, {5, 2}, {7, 2} });
return 0;
}

As far as I'm aware without a pattern a control structure is kind of redundant, you might be better served reading from a file.
// for user input
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 10; i++) {
cout << "Please input your value for array index " << i << endl;
cin >> arr[i];
}
// for manual input in initalization
int arr[10] = { 0, 3, 2, 2, 2, 5, 6, 7, 8, 9 };
However a better approach might be to read it from a file, http://www.cplusplus.com/forum/general/58945/ Read "TheMassiveChipmunk"'s post there for exactly how to do it.

Assuming you know which indices you will be changing upfront you can use a separate index array:
int ind[4]= {1,4,5,7};
..and an accompanying array with values
int new_val[4] = {3,2,2,2};
The you can use the following for loop to assign the values:
for (int i=0; i<4; i++)
arr[ind[i]] = new_val[i];
You should also use some variable signifying the number of indices to be changed like int val_num = 4 instead of plain number 4.

Changes that are defined in runtime to an array can be easily implemented by using a list to save tuples that represent the changes you want to make. As an example, we can write:
#include <tuple>
#include <list>
#include <iostream>
using namespace std;
typedef tuple <int, int> Change;
int main() {
int a[5] = {1,2,3,4,5};
list<Change> changes;
//represents changing the 2-th entry to 8.
Change change(2,8);
changes.push_back(change);
for(auto current_change: changes)
a[get<0>(current_change)] = get<1>(current_change);
cout << a[2] << '\n';
}
Prints 8.

Related

How does a 2D array within another array work?

I am looking at my homework for c++ and having some trouble understanding a part of the code. The code is creating a 2d array and wants to know how many times the elements from 1-9 are repeated.
#include <iostream>
using namespace std;
const int r = 3;
const int c = 4;
void frequency (int a[r][c]);
int main() {
int elems [r][c] = {{1, 1, 3, 4}, {2, 3, 4, 5}, {6, 9, 9, 9}};
frequency(elems);
return 0;
}
void frequency(int a[r][c]){
int arr[10] = {};
for(int i = 0; i < r; i++){
for(int j = 0; j < c; j++){
arr[a[i][j]]++;
}
}
for(int i = 1; i < 10; i++){
cout << i << " is repeated " << arr[i] << " times." << endl;
}
}
I don't understand how the line arr[a[i][j]]++; works -- how does it act as a counter for elements that are repeated?
I don't understand how the line arr[a[i][j]]++; works -- how does it act as a counter for elements that are repeated?
int arr[10] = {}; is creating an int-array with 10 elements (indexed 0-9) all initialized to 0.
arr[a[i][j]]++; is (post-)incrementing an element of arr.
The element at which index? The one at index a[i][j].
You loop through every row in a (i.e. in elems) using i and through every column within that row using j; in essence looping through every element in the order they are spelled in the source code. You are using the numbers in array a to index into the array arr: The first two elements of elems are 1, thus you increment arr[1]. The third number in elems is 3, thus you increment arr[3], ...

Index of vector containing the global minimum

Given a vector of vectors, is there an optimal way to determine the index of the vector which holds the global minimum?
What is the complexity in Big-O notation?
#include <algorithm>
#include <iostream>
#include <vector>
unsigned getMinimumIndex(std::vector<std::vector<unsigned>> const& a) {
if (!a.size())
return 0;
unsigned ret = 0; unsigned temp; unsigned global = 1 << 31;
for (std::size_t idx = 0; idx < a.size(); ++idx) {
if ((temp = *std::min_element(std::begin(a[idx]), std::end(a[idx]))) < global) {
global = temp;
ret = idx;
}
}
return ret;
}
int main() {
std::vector<std::vector<unsigned>> a = {{2, 4, 6, 8}, {3, 9, 5, 7},
{3, 4, 4, 3}, {2, 8, 3, 2},
{4, 4, 4, 0}, {1, 2, 3, 4}};
std::cout << getMinimumIndex(a); // 4-th vector posseses the value '0'
return 0;
}
Since neither your vectors nor the numbers inside a vector are sorted, you have to check every number to be the smallest value.
Thus you get a complexity of O(n).
You can either use iterators like you did or simply use 2 for loops and access the vector with a[i][j] (which should be minor faster because of the missing overhead from iterators).
Also - since you only have unsigned int, you can break as soon as you find 0.

printing a 2D array inside a function in c++

I have made the following program in c++. I just want to print an array elements. My code is as follows:
#include <iostream>
#include <cstdio>
using namespace std;
#define n 5
double dist[n][n];
void read_distances()
{
for(int i = 0; i < n ; i++)
{
for (int j = 0 ;j < n; j++)
{
cout<<dist[i][j]<<" ";
}
cout<<"\n";
}
}
main()
{
double dist[n][n] =
{
{0, 20, 30, 10, 11},
{15, 0, 16, 4, 2},
{3, 5, 0, 2, 4},
{19, 6, 18, 0, 3},
{16, 4, 7, 16, 0}
};
read_distances();
}
I just wanted to print the dist[][] array inside the read_distances() function. But here I am getting all the values 0 as output. what's the reason of this?
The reason is because you declared the dist array in main(), and you initialized its contents, but the function read_distances() prints the values of a global array called dist. It happens to have the same name as the dist array in main()'s scope, but is a completely different array, and it is never initialized.
EDIT: you asked how to make it work. The easiest way is to pass it as a parameter. After removing the global declaration:
void read_distances(double dist[n][n])
{
// ...
}
and then in your main():
read_distances(dist);
(technically, the parameter to read_distances() is actually double (*)[n], but that's going to be a topic for another day and I didn't want to make this too confusing).
How about this:
#include <iostream>
#include <cstdio>
using namespace std;
#define n 5
void read_distances(double dist[n][n])
{
for(int i = 0; i < n ; i++)
{
for (int j = 0 ;j < n; j++)
{
cout<<dist[i][j]<<" ";
}
cout<<"\n";
}
}
int main()
{
double dist[n][n] =
{
{0, 20, 30, 10, 11},
{15, 0, 16, 4, 2},
{3, 5, 0, 2, 4},
{19, 6, 18, 0, 3},
{16, 4, 7, 16, 0}
};
read_distances(dist);
}
Your code doesn't work because you overshadowed the global version of dist with the local one you created at main. So you either not use a global one, like I do here, and pass the one you create at main() to your printing function; or you fill that array without creating a new array in main().

Passing a reference to an offset position in an STL vector

I'm trying to convert some old C functions to C++. My original programme stores a matrix in a single array, and I just pass a pointer to the first element to a function so that I am working on the correct row, e.g.
double f1(int *a){
return a[0] + a[1];
}
int main(void){
int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(i = 0; i < 5; i++){
printf("%d\n", f1(&x[2 * i]));
}
I would like to be able to do something similar using the STL without copying. So my programme would look something like this
double f1(vector<int>& a){
return a[0] + a[1];
}
int main(void){
int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int> y(x, x + 10);
for(i = 0; i < 5; i++){
cout << f1(y) << endl; // This is clearly wrong
}
How would I do this? I could change my function to receive a reference to a vector::iterator I guess, but is there another way?
You could simply pass an iterator to the function. Random access iterators are very similar to pointers (in fact, pointers qualify as random access iterators.) For example,
#include <vector>
double f1(std::vector<int>::const_iterator a)
{
return a[0] + a[1];
}
#include <iostream>
int main()
{
vector<int> y{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto it = y.cbegin();
for(int i = 0; i < y.size()/2; ++i)
std::cout << f1(it + 2*i) <<std::endl;
}
Write array view. An array view is a pair of pointers with begin end size empty, operator[], front and back methods, and constructors from C arrays, std::array<T,N>&, std::vector<T,A>&, std::vector<non_const_T,A>const&, std::array<non_const_T,N>const&, std::initializer_list<non_const_T>, etc.
Oh, and T*,size_t and T*,T* ctors, which are great for slicing (use forwarding ctors: T*,size_t->T*,T*, and everything else to those 2).
It does not own its data, so all of its methods are const except operator=. (non-const methods would be methods that change the view range -- changing the elements is a const operation on a view).
Then
double f1(array_view<const int> a){
return a[0] + a[1];
}
You don't need to make so many changes:
double f1(int *a)
{
return a[0] + a[1];
}
int main(void)
{
vector<int> y = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 0; i < 5; i++) {
cout << f1(&y[2 * i]) << endl;
}
}

How to get distinct values from an arrays of different sizes?

Q:
arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9}
Ans:
values[]={1,2,5,6,7,9}
Q:
arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9,101,1502,1502,1,9}
Ans:
values[]={1,2,5,6,7,9,101,1502}
here is what i tried but not working
for(int i=0;i<(index-1);i++) {
if(data[i].age != data[i+1].age) {
c=new list;
c->value=data[i].age;
c->next=NULL; clas++;
if(age_head==NULL) {
p=c; age_head=c;
}
for(c=age_head;c!=NULL,c->next!=NULL;p=c,c=c->next) {
if(data[i].age!=c->value)
found=false;
else
found=true;
}
if((age_head!=NULL)&& (found=false)) {
p->next=c; c->next=NULL;
}
}
}
This is not the most efficient, but it has some values:
It uses STL objects
It uses a cool little known template trick for knowing at compile time the size of your C-like arrays
...
int a[] = {1,1,1,2,5,5,6,6,6,6,8,7,9} ;
int b[] = {1,1,1,2,5,5,6,6,6,6,8,7,9,101,1502,1502,1,9} ;
// function setting the set values
template<size_t size>
void findDistinctValues(std::set<int> & p_values, int (&p_array)[size])
{
// Code modified after Jacob's excellent comment
p_values.clear() ;
p_values.insert(p_array, p_array + size) ;
}
void foo()
{
std::set<int> values ;
findDistinctValues(values, a) ;
// values now contain {1, 2, 5, 6, 7, 8, 9}
findDistinctValues(values, b) ;
// values now contain {1, 2, 5, 6, 7, 8, 9, 101, 1502}
}
Another version could return the set, instead of taking it by reference. It would then be:
int a[] = {1,1,1,2,5,5,6,6,6,6,8,7,9} ;
int b[] = {1,1,1,2,5,5,6,6,6,6,8,7,9,101,1502,1502,1,9} ;
// function returning the set
template<size_t size>
std::set<int> findDistinctValues(int (&p_array)[size])
{
// Code modified after Jacob's excellent comment
return std::set<int>(p_array, p_array + size) ;
}
void foo()
{
std::set<int> valuesOne = findDistinctValues(a) ;
// valuesOne now contain {1, 2, 5, 6, 7, 8, 9}
std::set<int> valuesTwo = findDistinctValues(b) ;
// valuesTwo now contain {1, 2, 5, 6, 7, 8, 9, 101, 1502}
}
The first thing I spot in your code is
if((age_head!=NULL)&& (found=false)) {
you use assignment (=) instead of equality (==). The expression should be
if((age_head!=NULL)&& (found==false)) {
Then, in this loop
for(c=age_head;c!=NULL,c->next!=NULL;p=c,c=c->next) {
you are looking for a value in the list. However, in its current form, when the loop terminates, found will show whether the last element in the list equals to c->value. You need to check for found in the loop condition (and you need to AND the expressions instead of listing them separated by comma!):
for(c=age_head, found = false; !found && c!=NULL && c->next!=NULL; ...) {
The result of the comma operator is the result of the last subexpression inside - this is definitely not what you want. Moreover, with comma all subexpressions are evaluated, which results in dereferencing a null pointer if c == NULL - whereas the && operator is evaluated lazily, thus c->next!=NULL is evaluated only if c != NULL.
The next thing is that you need to search for the value in the list before you add it to the list! Also note that you are trying to check for two different things: that the actual data element is different from the next one, and that its value is not yet added to the list. The second condition is stronger - it will always work, while the first only works if the input data is ordered. So you can omit the first check altogether. The result of all the above, plus some more simplifications and clarifications, is
for(int i=0;i<index;i++) {
for(list* c=age_head, found=false; !found&&c&&c->next; p=c,c=c->next) {
if(data[i].age==c->value)
found=true;
}
if(!found) {
list* newc=new list;
newc->value=data[i].age;
newc->next=NULL;
clas++;
if(age_head==NULL) {
p=newc; age_head=newc;
} else {
p->next=newc; newc->next=NULL;
}
}
}
I still don't guarantee that your linked list handling logic is right though :-) In its current form, your code is hard to understand, because the different logical steps are not separated. With a bit of refactoring, the code could look a lot clearer, e.g.
for(int i=0;i<index;i++) {
if(!foundInList(data[i].age)) {
addToList(data[i].age);
}
}
Of course the simplest and most efficient would be using STL containers/algorithms instead, as shown in other answers. But I think there is much more educational value in improving your first attempt :-)
If the output need not to be sorted, you can use a Hashtable.
E.g. something like this:
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH
#include <boost/unordered_set.hpp>
#include <vector>
using namespace std;
using namespace boost;
int main() {
int arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9};
size_t n = sizeof(arr1)/sizeof(int);
unordered_set<int> h;
for (size_t i = 0; i < n; ++i)
h.insert(arr1[i]);
vector<int> values;
foreach(int a, h)
values.push_back(a);
return 0;
}
The runtime is then in O(n).
An alternative to that is sorting the array and then to eliminate neighboring identical elements (advantage only STL is needed). But then the runtime is in O(n log n):
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9};
size_t n = sizeof(arr1)/sizeof(int);
sort(arr1, arr1+n);
int *end = unique(arr1, arr1+n);
vector<int> values(arr1, end);
return 0;
}
Easily done using STL.
int array[] = { 1, 1, 2, 2, 1, 3, 3, 4, 5, 4, 4, 1, 1, 2 };
int nElements = sizeof(array)/sizeof(array[0]);
std::sort(&array[0], &array[nElements]);
int newSize = std::unique(&array[0], &array[nElements]) - &array[0];
first you need to sort the array and than do something like this:
for(int i = 0; i < size -1; i++)
{
if(array[i]!=array[i+1])
unique++;
// store it wherever you want to.
stored.push(array[i]);
}
#include <vector>
#include <algorithm>
#include <iostream>
int
main ()
{
int array[] = { 1, 1, 2, 2, 1, 3, 3, 4, 5, 4, 4, 1, 1, 2 };
std::vector < int >values;
values.push_back (array[0]);
for (int i = 1; i < sizeof (array) / sizeof (int); ++i)
{
std::vector < int >::iterator it =
std::find (values.begin (), values.end (), array[i]);
if (it == values.end ())
values.push_back (array[i]);
}
std::cout << "Result:" << std::endl;
for (int i = 0; i < values.size (); i++)
std::cout << values[i] << std::endl;
}
This seems to be a duplicate of Removing duplicates in an array while preserving the order in C++
While the wording of the question is different, the result is the same.
Based on above ideas/codes, I am able to accomplish my job on finding distinct values in C++ array. Thanks every one who replied on this thread.
#include <set>
#include <iostream>
using namespace std;
// function setting the set values
template<size_t size>
void findDistinctValues(std::set<int> & p_values,int (&p_array)[size])
{
// Code modified after Jacob's excellent comment
p_values.clear() ;
p_values.insert(p_array, p_array + size) ;
}
void findDistinctValues2( int arr[],int size)
{
std::set<int> values_1 ;
std::set<int>::iterator it_1;
values_1.clear();
values_1.insert(arr,arr+size);
for (it_1=values_1.begin(); it_1!=values_1.end(); ++it_1)
std::cout << ' ' << *it_1<<endl;
}
int main()
{
int arr[] = {1,6100,4,94,93,-6,2,4,4,5,5,2500,5,4,5,2,3,6,1,15,16,0,0,99,0,0,34,99,6100,2500};
std::set<int> values ;
std::set<int>::iterator it;
int arr_size = sizeof(arr)/sizeof(int);
printf("Total no of array variables: %d\n",arr_size);
printf("Output from findDistinctValues (function 1)\n ");
findDistinctValues(values, arr) ;
for (it=values.begin(); it!=values.end(); ++it)
std::cout << ' ' << *it<<endl;
std::cout<<endl;
std::cout<<values.size()<<endl; //find the size of distict values
printf("Output from findDistinctValues (function 2) \n ");
findDistinctValues2(arr,arr_size);
getchar();
return 0;
}