Related
I am trying to sort a c++ subarray by first element.
My code is currently set up like this:
int umbrellas[3][2] = {{5, 6}, {2, 7}, {9, 20}};
int n = sizeof(umbrellas) / sizeof(umbrellas[0]);
sort(umbrellas, umbrellas + n, greater<int>());
The sort function doesn't seem to be functioning properly and when I run the code it generates errors. Is there a way to sort the array from
{{5, 6}, {2, 7}, {9, 20}}
into
{{2, 7}, {5, 6}, {9, 20}}
?
Use a std::vector of std::vector as your container and the sort becomes much easier to do with. Not only is std::vector the preferred container for C++ but using STL functions on it is way simpler and direct , without any substantiable overhead.
Define your data as
std::vector<std::vector<int>> umbrellas{
{5, 6},
{2, 7},
{9, 20}
};
Now you can use a custom comparator lambda that takes in two vector element references and returns True when the first element of the above vector is smaller than that of the one below.
std::sort(umbrellas.begin(),
umbrellas.end(),
[](const std::vector<int> &above, const std::vector<int> &below)
{
return (above[0] < below[0]);
});
And the output :
for (auto &&row : umbrellas) {
for (auto element : row) {
std::cout<< element<< " ";
}
std::cout<< "\n";
}
2 7
5 6
9 20
Taking this to C++20 it's even easier:
std::ranges::sort(umbrellas, std::less(),
[](const auto &v) { return v[0];});
If time complexity doesn't matter, this code will achieve the desired with O(n^2) complexity
int arr[3][2] = {{5, 6}, {2, 7}, {9, 20}};
int n = sizeof(arr) / sizeof(arr[0]);
for(int i = 0 ; i < n - 1; i++){
for(int j = 0 ; j < n - 1 ; j++){
if(arr[j][0] > arr[j + 1][0])
swap(arr[j],arr[j + 1]);
}
}
int array[3][3][8] = {
{{3, 4, 5}, {3, 5, 7}, {5, 6, 7}},
{{1, 3, 5}, {0, 1, 2, 3, 4, 5, 6, 7}, {1, 5, 7}},
{{1, 2, 3}, {1, 3, 7}, {0, 1, 7}}
};
User inputs x,y coordinate and direction, at that location they can only move in 0-7 direction. However, each location can only move towards certain direction. Therefore I am making this array to see if that direction is in that x, y coordinate’s array. After I get the 3rd dimension array (becomes 1d array), I will see if user input direction is in that array.
For example:
{3,4,5} at 1x1 // then check if direction is in this array
I tried:
int new_array[8] = array[1][1];
Error: array must be initialized with a brace-enclosed initializer
int new_array = array[1][1][]; // {3,4,5}
Error: expected primary-expression before ']' token
So I know this syntax isn't valid, are there other ways to achieve such operation?
To copy the 3rd dimension array into a new array.
You could use std::copy:
#include <algorithm>
#include <iterator>
//...
int new_array[8];
std::copy(std::begin(array[1][1]),
std::end(array[1][1]),
new_array);
Done using std::array:
#include <array>
// ...
std::array<std::array<std::array<int, 8>, 3>, 3> array = {{
{{
{3,4,5},
{3,5,7},
{5,6,7}
}},
{{
{1,3,5},
{0,1,2,3,4,5,6,7},
{1,5,7}
}},
{{
{1,2,3},
{1,3,7},
{0,1,7}
}},
}};
std::array<int, 8> new_array = array[1][1];
// the same result but simpler:
auto new_array = array[1][1];
there is no way you can get the col or row of an array like that...
if you define a primitive array then you have to navigate the cells and asign the values
int main() {
int test[2][3][2] = {
{
{1, 2},
{3, 4},
{5, 6}
},
{
{7, 8},
{9, 10},
{11, 12}
}
};
int z[2];
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 2; ++k) {
z[k] = test[i][j][k];
}
}
}
for (int k = 0; k < 2; ++k)
{
cout << "z[" << k << "] = " << z[k] << endl;
}
return 0;
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.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a two dimensional array and I know:
The number of lines and the length of each line
Each line contains just positive numbers
Each line is sorted
not use with auxiliary array
-not use with data structures
Required Output
I need to return the number which appears max times in the the whole array in an efficient way.
I already tried to pass all over the array but it's not efficient.
This is an example of the array.
{
{5, 7, 8},
{6, 6},
{null},
{5, 6, 8, 9}
}
The expected return value for this example is 6.
I would like to get the explanation or code in c++
Thanks
Since a C/C++ solution is required then a 2D Array can be used.
All the missing values can be represented by -1 (or any number which is not expected in valid numbers involved in search).
So a empty row can be represented by all -1. See the code below.
Since in C/C++, 2D array is continuously represented in memory. So we can convert 2D array to 1D array.
Now we can sort the array. After sorting, all the '-1' will be at the beginning which can be discarded.
From the leftover elements we can find the max frequency of an element.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main()
{
int i, prev, max = -1, count = 0, maxvalue = -1;
int a[4][4] = {{5, 7, 8, -1}, {6, 6, -1, -1}, {-1, -1, -1, -1}, {5, 6, 8, 9}};
//int a[4][4] = {{-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}};
int *b = (int*)a;
int total = sizeof(a) / sizeof(int);
qsort(b, total, sizeof(int), compare);
for(i = 0; i < total; ++i)
{
if(b[i] != -1)
{
break;
}
}
//printf("\n");
i = i + 1;
prev = -1;
count = 0;
if(i < total)
{
prev = b[i];
count = 1;
}
for(i = i + 1; i < total; ++i)
{
//printf("prev=%d, b[i]=%d, max=%d, count=%d\n", prev, b[i], max, count);
if(prev == b[i])
{
count++;;
}
else
{
if(max < count)
{
max = count;
maxvalue = prev;
}
prev = b[i];
count = 1;
}
}
if(max != -1)
{
printf("Max Occurence of %d = %d\n", maxvalue, max);
}
else
{
printf("All the rows are of zero length\n");
}
return 0;
}
//Output:
Max Occurence of 6 = 3
For counting the number of times an element occurs in the array, a similar question using recursion is shown here.
Since you mentioned efficiency, it would help to sort the array in increasing or decreasing order prior to counting the number of times an element is present in the array (if unsorted). Although for a small input size as shown in your example, it wouldn't make much of a difference.
You could use map to keep track of the number of times its been repeated and a current max.
map<int, int> temp;
int currentMax= -999999,maxCount=0;
for(i=0; i< numberOflines ;i++)
{
for(j=0;j< array[i].length;j++)
{
int newCount = ++temp[array[i][j]];
if (maxCount < newCount) {
maxCount = newCount;
currentMax = array[i][j];
}
}
}
First off your input is illegal:
{
{5, 7, 8},
{6, 6},
{null},
{5, 6, 8, 9}
}
null is not defined by C++, and even if it was defined as 0 it would have to be interpreted as int(0), not an empty sub-array as I think that you intended.
I'm guessing that the input that you intend to imply should look something like this:
const initializer_list<int> a[] = {{5, 7, 8},
{6, 6},
{},
{5, 6, 8, 9}};
You'll need to maintain a total for each number in any array. The best way to do that is to use map<int, int> totals which will only be constructed with the exact number of pairs as there are unique elements in a. The second element of each pair will be the count of that element seen thus far. You can populate it by doing:
for(const auto& i : a) for_each(cbegin(i), cend(i), [&](const auto& it){ totals[it]++;});
Once totals is populated you need only find its largest value:
cout << max_element(cbegin(totals), cend(totals), [](const auto& lhs, const auto& rhs){return lhs.second < rhs.second;})->first << endl;
Live Example
I'm looking for some help on a problem that I vaguely inquired about before, which is solving 15-peg solitaire recursively. I keep getting strange errors when I compile and run it, most of them say "stack overflow" or that I'm getting a seg fault. This is what I have so far, where "board[15]" represents the 15 peg board, and "moves[36]" represents all of the possible moves that can be made. The recursion is supposed to spot when there is only one peg left.
#include <iostream>
using namespace std;
void solveGame(int a[15], int b[36][3], int c[15][4]);
void chooseMove (int a[15], int b[36][3], int openSpace, int c[15][4]);
int findEmpty (int a[15]);
int pegCount (int a[15]);
bool isPeg (int peg, int a[15]);
int usedVals[15] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
int d = 0;
int index = 0;
int main ()
{
int openSpace = 5;
int board[15]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
board[openSpace] = 0;
int alreadyMoved[15][4];
int moves[36][3] = {{0, 1, 3},
{0, 2, 5},
{1, 3, 6},
{1, 4, 8},
{2, 4, 7},
{2, 5, 9},
{3, 6, 10},
{3, 7, 12},
{3, 1, 0},
{3, 4, 5},
{4, 7, 11},
{4, 8, 13},
{5, 9, 14},
{5, 8, 12},
{5, 2, 0},
{5, 4, 3},
{6, 3, 1},
{6, 7, 8},
{7, 4, 2},
{7, 8, 9},
{8, 4, 1},
{8, 7, 6},
{9, 5, 2},
{9, 8, 7},
{10, 6, 3},
{10, 11, 12},
{11, 7, 4},
{11, 12, 13},
{12, 7, 3},
{12, 8, 5},
{12, 11, 10},
{12, 13, 14},
{13, 8, 4},
{13, 12, 11},
{14, 9, 5},
{14, 13, 12}};
solveGame(board, moves, alreadyMoved);
for (int i = 0; i < 13; i++)
cout << alreadyMoved[i][0] << " " << alreadyMoved[i][1] << " " < <alreadyMoved[i][2] << endl;
return 0;
}
// main recursive function
void solveGame (int a[15], int b[36][3], int c[15][4]
{
int empSpace;
int moveIndex;
if (pegCount(a) < 2) {
cout<<"game over"<<endl;
} else {
empSpace = findEmpty(a);
chooseMove(a, b, empSpace, c);
solveGame(a, b, c);
}
}
// supposed to pick a move that is applicable to the board otherwise it find a new move
void chooseMove (int a[15], int b[36][3], int openSpace, int c[15][4])
{
int i = 0;
while (1) {
if (i < 36 && b[i][2] == openSpace && isPeg(b[i][0],a) && isPeg(b[i][1],a)) {
a[b[i][0]] = 0;
a[b[i][1]] = 0;
a[b[i][2]] = 1;
c[d][0] = b[i][0];
c[d][1] = b[i][1];
c[d][2] = b[i][2];
c[d][3] = i;
d++;
index = 0;
for (int v = 0; v < 15; v++)
usedVals[v] = -1;
break;
} else if (i > 35) {
a[b[c[d-1][3]][0]] = 1;
a[b[c[d-1][3]][1]] = 1;
a[b[c[d-1][3]][2]] = 0;
c[d-1][0] = 0;
c[d-1][1] = 0;
c[d-1][2] = 0;
c[d-1][3] = 0;
usedVals[index] = openSpace;
index++;
int newOpen = findEmpty(a);
chooseMove(a, b, newOpen, c);
}
i++;
}
}
// counts the pegs on the board in order to cancel recursion
int pegCount (int a[15])
{
int count = 0;
for (int i = 0; i < 15; i++)
if (a[i] == 1)
count++;
return count;
}
// finds an empty space that hasn't already been found faulty
int findEmpty (int a[15])
{
for (int i = 0; i < 15; i++) {
for(int j = 0; j < 15; j++) {
if(a[i] == 0 && i != usedVals[j] && usedVals[j] > -1)
return i;
}
}
}
// tests if current index is a peg
bool isPeg (int peg, int a[15])
{
return a[peg] == 1;
}
A quick glance shows a lot of potential problems, but I think it probably boils down to the way you are passing arrays. Arrays are passed by reference and not by value, so the recursive function is working with a single copy of the array, which I don't think is what you want. Therefore you are never finding the ending move, which will get you a stackoverflow from unlimited recursion.
Try allocating a new copy of the arrays at each level of recursion. Some people will want you to use new or malloc for this, because they feel an introduction to C++ should be a trial by fire where you have to master memory management to do anything useful. Instead, I would advise you not to use arrays at all; use a collection class that will work properly when passed by value (I think std::vector of POD will do this) and the collection class will create copies of your arrays the way your code seems to expect.
You may also be having a problem of doing a depth-first search in chooseMove, when you really want a breadth-first search.
Stack overfow when using recursivity is pretty common. This is due to the fact that return values for function calls are stored into the stack, and the stack keeps filling as long as function does not return. If the recursivity goes too deep, you end up filling your whole stack and overflowing it, which also causes SEGV.
Usually you get a stack overflow when your exit condition does not work, but here you are also passing your parameters by value, which might overflow your stack even in normal operation.
I suggest you pass your arrays by reference or better in a std::vector. An std::vector is a small object that holds the real data in a heap allocated space. You can even return those.
I also suggest that you start your program in a debugger, that is the simplest and most effective way to find out what exactly is going wrong.