Spent all night trying to do this.

I'm at my limit, I feel as if the teacher shoved way too much material for an intro course to Programming. I just started learning how to program C++ and for our team assignment we have to create a Matrix with 3 functions using 2D dynamic arrays with double pointers (automatic 0 if we use fixed arrays).

One function, MostFreqInt() has to detect the most repeated elements in the 2-dimensional array. Second function, AveMatrix(), is prompted if there's no repeated value or the most repeated value is zero. Third function, AvgRepeated() is prompt if there are equal amount of most repeated value. Finally, to make things worst, the matrix must be able to rotate even if it's a rectangle.

I'm really at my wit's end, my team is planning to drop the course so they don't even care about the team assignment anymore. Now I'm left alone to finish it before today. The most frequent repeated Algorithm really trumps me and I have no idea what to do; I could figure out how to rotate the matrix if it was a square but not a rectangle. (If I fail my this 10% team assignment I fail my course). Should I drop the class instead of plowing through this massacre?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#include <array>

#include <vector>
class Matrix
{
private:
	std::vector<int> rewrite;
	int userinput;
	unsigned int matrixrow;
	unsigned int matrixcolumn;
	bool confirmzero = false;
	bool confirmrepeat = false; // allows the confirmation if there is a repeat
	int equalrepcounter;
	float sumofequals;
	float AvgNum;
	int AvgDivisor;
	int **dMatrixPtr = NULL;
	//Figure out double pointers
public:
	Matrix();
	void inputMatrix();
	void inputLoop(unsigned int,unsigned int, int **);
	float mostFreqInt();
	void AvgMatrix(); //First case: Calculates average of whole matrix
	float AvgRepeated(unsigned int, unsigned int, int **);//Second case: Calc
	float divideMatrix();
	int rotateMatrix(); //Assign new values to Matrix
	void printMatrix(); //Print the Matrix to find out what's up.
	void deleteMemory(); //deletes the memory before program ends.


};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//matrix.cpp
float Matrix::mostFreqInt()
{
	int maxrepcounter = 0;

	//rewrite into a vector
	for (size_t i = 0; i < matrixrow; i++)
	{

		for (size_t j = 0; j < matrixcolumn; j++)
			 rewrite.push_back(*(*(dMatrixPtr + i) + j));
	}
	//sort the vector into increasing order
	sort(rewrite.begin(), rewrite.end());
	//iterate through loop
	for (size_t i = 0; i < rewrite.size(); i++)
	{
		int checkcounter = 1;//Resets after every comparison
		for (size_t j = i + 1; j < rewrite.size(); j++)
			if (rewrite[i] == rewrite[j])
			{
				checkcounter++;	
				if (checkcounter > maxrepcounter)
				{
					//confirmrepeat = false;
					maxrepcounter = checkcounter;
					if (!rewrite[j] == 0)
					{
						AvgNum = rewrite[j];
						confirmzero = false;
					}
				}
				if (checkcounter == maxrepcounter)
				{
					//confirmrepeat = true;
					equalrepcounter = checkcounter;
					AvgNum = AvgRepeated(matrixrow, matrixcolumn, dMatrixPtr);
				}
			}
	}
	
	std::cout << AvgNum;

	return AvgNum;
}

void Matrix::AvgMatrix()
{
	int sumofmatrix = 0;
	for (int sum : rewrite)
	{
		sumofmatrix += sum;
	}
	
	AvgNum = sumofmatrix / rewrite.size();
}
float Matrix::AvgRepeated(unsigned int row, unsigned int column, int **dMatrix)
{
	for (size_t i = 0; i < rewrite.size(); i++)
	{
		int checkcounter = 1;//Resets after every comparison
		for (size_t j = i + 1; j < rewrite.size(); j++)
		{
			if (rewrite[i] == rewrite[j])
			{
				checkcounter++;
				if (checkcounter == equalrepcounter)
					sumofequals += rewrite[i] * equalrepcounter;
			}
		}
		AvgNum = sumofequals / equalrepcounter;
		return AvgNum;
	}
} 


various failure attempts on debugging my program:

input : 
1 2 3
3 3 3
4 5 6

Output of average: 0

input:
4 4 4 
4 4 4
4 4 4

Output of Average: 19.556


In my main, I test the MostFreq function, and despite having return AvgNum, I have to put std::cout << AvgNum; in order to actually get the AvgNum. How is that even possible? Doesn't return display the value usually?
Last edited on
Are you allowed to use things like std::map and std::vector? They would make your life a lot simpler, you just need to spend a few minutes reading about them.

Rotating the array doesn't actually have to happen - you can just change the order you output the elements in so that it is output rotated but not actually rotated.
Wow I didn't think about the rotating the matrix that way. I did read a lot about vectors and I tried using sort and adjacent_find but it didn't work because of the type. Plus I read it only finds pairs, which in this case wouldn't help if I had 3 or more I'd have to count.
Last edited on
Well something to consider is that your matrix is storing floating point types - they are notorious for not being safe to use == on, so you have to have a bit of a looser definition of 'equals' for them.
https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Normally, you would be able to use a std::map<double, int> - the key is the number from the matrix, and the value is the number of time you found it. You would literally just loop through the matrix and increment the value in the map for each number.
The problem is I don't know what value to find. Say there's:
 input: 1 2 2 2 3 3 3 

How would your function recognize automatically that there's two numbers equally repeated and the average of them must be calculated. e.g (3+3+3+2+2+2)/6

Wouldn't the map just find the amounts of time one number would be found?

e.g 2 is repeated 3 times, but then digit 3 is disregarded. Also would there even be a point in filling up the parameters with arguments if I'll just end up testing the function in main? Every function I just save the values to the private member then I reuse them in the following function.

Last edited on
You could use a std::map initially and then swap key and value into a std::multimap, something like this:
http://ideone.com/CGp7is

BarelyOtaku wrote:
Also would there even be a point in filling up the parameters with arguments if I'll just end up testing the function in main? Every function I just save the values to the private member then I reuse them in the following function.
I disagree with the way your assignment is making you structure the functions - it's not how functions normally are. But, you should probably stick to the assignment despite knowing there's a better way.
Last edited on
Alright thank you so much LB! I'm going to take a small nap and then hopefully I'll have the energy to finish up the assignment by implementing the std::map you suggested. Just by looking at it I have no idea how iterators work since we only covered to chapter 8 up to pointer in Dietel C++
Once again, thanks a lot I appreciate the time and effort!!
You're welcome! It is unusual that you covered pointers before std::vector and iterators, but at least you can learn them now. The reference on this site is helpful and so is cppreference.com:
http://www.cplusplus.com/reference/map/
http://en.cppreference.com/w/cpp/container/map
http://www.cplusplus.com/reference/iterator/
Last edited on
It seems to me that the hard part here is mostFreqInt(). I'd code it like this:

1
2
3
4
// Find the most frequent value(s) in the matrix. Returns the number of
// times that it occurs. Upon exit, "values" contains the actual values that
// occur most frequently.
int Matrix::mostFreqInt(set<int> &values)


Once you have this working, the rest becomes relatively easy:
AveMatrix(), is prompted if there's no repeated value or the most repeated value is zero.
1
2
3
4
5
6
7
8
9
Matrix myMatrix;
...
set<int> maxValues;
int maxCount = myMatrix.mostFreqInt(maxValues);
if (maxCount == 1 // no repeated values
    || maxValues.size() == 1 && *maxValues.begin() == 0) // most repeated value is zero
{
    AveMatrix();
}


[quote]AvgRepeated() is prompt if there are equal amount of most repeated value. /quote]
1
2
3
if (maxValues.size() > 1) { // multiple repeated values
    cout << AvgRepeated(maxCount, maxValues);
}


Does AvgRepeated compute the average of the most repeated values? If so then you don't even need to go through the matrix again: you already have what you need:
1
2
3
4
5
6
7
8
double AvgRepeated(int maxCount, set<int> &maxValues)
{
    double sum = 0;
    for (double val : maxValues) {
	sum += val + maxCount;	// there were maxCount occurences of val
    }
    double average = sum / (maxCount * maxValues.size());
}


Lastly, if your teammates plan to drop the class then tell the prof and hand in the assignment as yours alone, or ask for an extension.
Hey I've run into a small problem. I'm nearly complete my assignment but my main problem is determining which 3 functions to use by using conditions.

So far using what you wrote I got:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
for (size_t i = 0; i < rewrite.size(); i++)
		++counts[rewrite[i]]; //This is the single map that records how many times something is entered.

		for (auto const &v : counts)
			{
					mode.emplace(v.second, v.first);
				}
				auto mostFreq = mode.rbegin()->first; //Here a second declaration is made to see which one has the most repetition
				std::cout << "Number of matrix reps " << mostFreq << "   : ";
				for (auto it = mode.rbegin(); it != mode.rend() && it->first == mostFreq; ++it)
					//multimap iterates through and checks which matrix value is the highest
					//value and prints out. If there are similar most freq, a new iterator is created to accomodate;
				{
					std::cout << it->second << " "; //Allows user to see which values are repeated commonly.
					sumofequals += it->second;
					freqcounter++; //freqcounter was initialized at 1
					 //Checks how many times iterators loop in order to determine which AvgNumber function to use
				}
		
				std::cout << "Amount of different number is:  " << freqcounter;

				if (freqcounter == 1 && sumofequals == 0) //Can't seem to figure it out
				{
					AvgNum = AvgMatrix();
				}
				else if (freqcounter == 1)
				{
					AvgNum = sumofequals;
				}
				if (freqcounter > 1)
					AvgNum = AvgRepeated(sumofequals, freqcounter);
				
				std::cout << "\nAvgNum value is set to: " << AvgNum;
	return AvgNum;


The problem is that my value from the freqcounter changes if there's different types of numbers.

e.g.
 input: 5 5 5 5 2
Number of matrix reps 4  for the number 5
Amount of equal repetition number types is: 2
I don't how to make it so it only says 1 so that I could use 5 as AvgNum


Last edited on
Why was freqcounter initialized at 1?
I assumed that if it encounters something else that has just as many repetition it would increment by one.

e.g
1
2
3
4
5
6
input = 2 2 5 5

freqcounter++;
amount of equal repetition number types is: 2 since freqcounter would be 2

Last edited on
It should be initialized to zero. Also, I think your first if statement should be
if (sumofequals == 0 || freqcounter == rewrite.size())
Yeah my mistake I meant the whole section of loops. The first one wasn't a problem but the repeated and unique is a real pain.

I got it, it's extremely bad programming practice IMO but I don't have the time to figure it out.
I fixed all my if conditions to work but the only problem is the two more equally repeated case.
Basically the freqcounter goes off by one ONLY if there is repetition by adding one again.

To answer your suggestion fg109 it wouldn't work if it's initialized to zero since it'll just be Infinity if there are no repetition. However, you were right about the || and I don't know why I changed it to &&.

So the loop code i changed looks like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	for (size_t i = 0; i < rewrite.size(); i++)
		++counts[rewrite[i]]; //This is the single map that records how many times something is entered.

		for (auto const &v : counts)
			{
					mode.emplace(v.second, v.first);
				}
				auto mostFreq = mode.rbegin()->first; //Here a second declaration is made to see which one has the most repetition
				std::cout << "Number of matrix reps " << mostFreq << "   : ";
				for (auto it = mode.rbegin(); it != mode.rend() && it->first == mostFreq; ++it)
					//multimap iterates through and checks which matrix value is the highest
					//value and prints out. If there are similar most freq, a new iterator is created to accomodate;
				{
					std::cout << it->second << " "; //Allows user to see which values are repeated commonly.
					sumofequals += it->second;
					confirmsame= it->second;
					if (confirmrepeat != it->second) //checks for repetition
					{
						confirmrepeat = true;
						freqcounter++;
					}
						 //freqcounter was initialized at 1
					 //Checks how many times iterators loop in order to determine which AvgNumber function to use
				}
		

				if (sumofequals == 0 || freqcounter == rewrite.size()) //Can't seem to figure it out
				{
					AvgNum = AvgMatrix();
				}
				else if (confirmrepeat == false)
				{
					AvgNum = sumofequals;
				}
				else
					AvgNum = AvgRepeated(sumofequals, freqcounter-1); //Off by one error
				
				std::cout << "\nAvgNum value is set to: " << AvgNum;

	return AvgNum;
}

Last edited on
I realize this is marked solved already, but

it wouldn't work if it's initialized to zero since it'll just be Infinity if there are no repetition

That's where you're wrong. If there's no repetition, then mostFreq == 1 which means that the loop will go through every element, which in turn means freqcounter == rewrite.size().
Topic archived. No new replies allowed.