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
Related
here's a simple implementation of Dijskstra. I'm aware its very basic, just learning C++. I got it from another source, and can't understand why they have included this line of code:
&& distance[m]!=INT_MAX
which appears in the nested for loop in the Dijsktra function definition. I've compiled it with and without this line of code and it seems to work just fine both ways. I can't see any scenario where the minimum distance of an unvisited vertex would equal infinity. Any ideas why it might have been included? Is it superflous? Full code below.
#include<iostream>
#include<climits>
using namespace std;
int miniDist(int distance[], bool Tset[]) // finding minimum distance
{
int minimum=INT_MAX,ind;
for(int k=0;k<6;k++)
{
if(Tset[k]==false && distance[k]<=minimum)
{
minimum=distance[k];
ind=k;
}
}
return ind;
}
void DijkstraAlgo(int graph[6][6],int src) // adjacency matrix
{
int distance[6]; // // array to calculate the minimum distance for each node
bool Tset[6];// boolean array to mark visited and unvisited for each node
for(int k = 0; k<6; k++)
{
distance[k] = INT_MAX;
Tset[k] = false;
}
distance[src] = 0; // Source vertex distance is set 0
for(int k = 0; k<6; k++)
{
int m=miniDist(distance,Tset);
Tset[m]=true;
for(int k = 0; k<6; k++)
{
// updating the distance of neighbouring vertex
if(!Tset[k] && graph[m][k] && distance[m]!=INT_MAX && distance[m]+graph[m][k]<distance[k])
distance[k]=distance[m]+graph[m][k];
}
}
cout<<"Vertex\t\tDistance from source vertex"<<endl;
for(int k = 0; k<6; k++)
{
char str=65+k;
cout<<str<<"\t\t\t"<<distance[k]<<endl;
}
}
int main()
{
int graph[6][6]={
{0, 1, 2, 0, 0, 0},
{1, 0, 0, 5, 1, 0},
{2, 0, 0, 2, 3, 0},
{0, 5, 2, 0, 2, 2},
{0, 1, 3, 2, 0, 1},
{0, 0, 0, 2, 1, 0}};
DijkstraAlgo(graph,0);
return 0;
}
In older C++ standards, signed integer overflow is UB. When it's not (c++20), it's due to 2's complement arithmetics, which means that if you add to INT_MAX, you'll end up having negative numbers. Thus, distance[m]+graph[m][k]<distance[k] could actually succeed (be true) even if distance[m] == INT_MAX. The code is right to defend against this.
I'm a newbie programmer trying to solve the following problem: I need to initialize a matrix with all the combinations from a array of objects so I can extract the values and perform certain calculations afterwards for each set of objects, in this case I used a struct for X, Y coordinates to represent the data. The entire data set consists on 35 coordinates, for now I'm dealing with as few data as possible, an input array of size 4, meaning 4 (n) combinations of 3 (r) objects. The program seems to work fine until I print the 4x3 matrix and find out I was only able to store the first combination, and after tinkering with the program I got stuck since I didn't code this program entirely. Could someone suggest me a solution so the matrix gets initialized correctly? I'd highly appreciate it.
#include <iostream>
#define n 4 //data set size
#define r 3 // combination size
using namespace std;
struct Points{
double x, y;
};
void Combination(Points Data [n], Points CombinationMatrix [][r],int start, int currLen, bool check []) {
// Return if the currLen is more than the required length.
if(currLen > r)
return;
// If currLen is equal to required length then add the sequence.
else if (currLen == r){
for (int i = 0; i < n; i++){
for(int j = 0; j < r; j++){
if (check[i] == true){
CombinationMatrix[i][j] = Data[j];
}
}
}
return;
}
// If start equals to len then return since no further element left.
if (start == n)
{
return;
}
// For every index we have two options.
// First is, we select it, means put true in check[] and increment currLen and start.
check[start] = true;
Combination(Data, CombinationMatrix, start + 1, currLen + 1, check);
// Second is, we don't select it, means put false in check[] and only start incremented.
check[start] = false;
Combination(Data, CombinationMatrix, start + 1, currLen, check);
}
int main()
{
Points Data [n] = { {1, 1} , {2, 7} , {3, 6} , {4, 13}}; //, {5,9} ,
//{6, 7} , {7, 12} , {8, 14} , {9, 17} , {10, 23} ,
//{11,28} , {12, 63} , {13, 45} , {14, 68} , {15, 32} ,
//{16,98} , {17, 115} , {18, 116}, {19, 112}, {20, 115},
//{21, 88} , {22, 86} , {23, 106}, {24, 136}, {25, 158},
//{26, 198}, {27, 128} , {28, 187}, {29, 112}, {30, 149},
//{31, 279}, {32, 224} , {33, 222}, {34, 260}, {35, 166}};
Points CombinationMatrix [n][r];
bool check[n];
for(int i = 0; i < n; i++){
check[i] = false;
}
Combination(Data, CombinationMatrix, 0, 0, check);
for (int i = 0; i < n; i++){
for(int j = 0; j < r; j++){
cout << CombinationMatrix[i][j].x << "," << CombinationMatrix[i][j].y << " ";
}
cout << endl;
}
return 0;
}
I suggest that you have a look at std::prev_permutation.
If you have a std::vector<Data> points, then you can get all permutations via
do {
// Do something with the current permutation
for ( int i = 0; i < points.size(); ++i ) {
std::cout << points[i] << ' ';
}
std::cout << '\n';
} while ( std::prev_permutation(points.begin(),points.end()) );
Since this gives you points.size()! (Factorial) combinations, I would not store it in a matrix unless you have a very good reason to do so.
std::prev_permutation uses the lexicographically smaller. Thus, you need to overload the operator < for Data.
inline bool operator< (const Data& lhs, const Data& rhs){
/* do actual comparison e.g.*/
return ((lhs.x <rhs.x) && (lhs.y <rhs.y));
}
The following generates combinations of your array using std::prev_permutation.
Note that this is accomplished by using a bool vector that starts with r of those bits set to true, and on each iteration the bits in the bool vector have their positions changed.
The following uses std::vector<Point> instead of hard-coded arrays. This adds flexibility in that you don't have to guess how many combinations will be generated.
#include <iostream>
#include <vector>
#include <algorithm>
struct Points {
double x, y;
};
std::vector<std::vector<Points>> Combination(std::vector<Points>& Data, int n, int r)
{
// The returned vector
std::vector<std::vector<Points>> retVect;
// Array of bools
std::vector<bool> bits(n);
// Fill the first r positions of the bool array to true
std::fill(bits.begin(), bits.begin() + r, true);
// Our temporary 1 dimensional array we use when building a single combination
std::vector<Points> tempV;
do
{
tempV.clear();
for (int i = 0; i < n; ++i)
{
// for each item in the bool array that's true, add that to the vector
if (bits[i])
tempV.push_back(Data[i]);
}
// add this combination to vector of combinations
retVect.push_back(tempV);
// rearrange the bits
} while (std::prev_permutation(bits.begin(), bits.end()));
return retVect;
}
int main()
{
std::vector<Points> Data = { {1, 1}, {2, 7}, {3, 6}, {4, 13} };
auto CombinationMatrix = Combination(Data, 4, 3);
for (size_t i = 0; i < CombinationMatrix.size(); i++) {
for (size_t j = 0; j < CombinationMatrix[i].size(); j++) {
std::cout << "{" << CombinationMatrix[i][j].x << "," << CombinationMatrix[i][j].y << "} "; }
std::cout << std::endl;
}
}
Output:
{1,1} {2,7} {3,6}
{1,1} {2,7} {4,13}
{1,1} {3,6} {4,13}
{2,7} {3,6} {4,13}
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.
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.
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.