find the frequency of a multi array - c++

problem:
Given a matrix of integers, count the amount of times each number 0-9 appears. Print out your results on one line in the following form:
0:number of zeros;1:number of ones;2:number of twos;3:number of threes;4:number of fours;5:number of fives;6:number of sixes;7:number of sevens;8:number of eights;9:number of nines;
For example, if you are passed an identify matrix, it contains 12 zeros and 4 ones and no other numbers from 0 to 9, your output would be:
0:12;1:4;2:0;3:0;4:0;5:0;6:0;7:0;8:0;9:0;
So far I have been created some codes:
#include<bits/stdc++.h>
using namespace std;
void printfrequency(int array[][4])
{
int c=0;
for(int a=0; a<10; a++){
for (int i=0; i<4; i++)
for ( int j=0;j<4;j++)
if(array[i][j] == a){
c++;
}
cout << a << ":" << c <<";" ;
}
}
int main()
{
int array[4][4] = { {3,5,7,9}, {2,4,8,9},{1,1,1,1},{3,6,9,2} };
printfrequency(array);
return 0;
}
and here is the ouput:
0:0;1:4;2:6;3:8;4:9;5:10;6:11;7:12;8:13;9:16;
How can I achieve 0:12;1:4;2:0;3:0;4:0;5:0;6:0;7:0;8:0;9:0; ?

The code you show gives output based on the frequencies for the specific array init visible in the shown code.
That array init contains no zeros, so the output should start with "0:0" and it does. (Actually required for the shown array init would be "zeros:0", but I stick with your codes basic concept of output and only discuss frequency values).
The output mentioned as example in the assignemnt is for an "identity" matrix, though you have a typo there. Such an identity matrix has a diagonal of "1"s in other wise all "0"s. Counting them gives the output of 4 ones and 12 zeros for a 4 by 4 matrix as shown.
The code is not correct, it fails to reset the count and the frequencies hence increase over the output.
To fix that mistake (but still get the frequencies for the array init, not the example output) change
int c=0;
for(int a=0; a<10; a++)
{
to
for(int a=0; a<10; a++)
{
int c=0;
That will reset the count for each digit your are counting and get you the output:
0:0;1:4;2:2;3:2;4:1;5:1;6:1;7:1;8:1;9:3;

All answers are given, correct and accepted.
But additionally I would like to give some hints for a "better" C++ programming style.
We can see in your code that you maybe try to learn from some "Hacker" or "competition" site. That will never work. If you really want to learn C+, then start with books or serious sites.
What we can see in your code:
#include<bits/stdc++.h> is not compliant C++ code. The header file is an extension available for some compilers.But you should never use it.
using namespace std; should never be used. Please use fully qualified names and to not pull in the complete std::namespace
Prefer pre-increment overpost-increment, whereever possible
Do not use C-Style arrays in C++. Use C++ instead.
Variable names should be expressive
Add comments. The more, the better.
Then, without changing any algorithm or structure of your original program and just modifying the names and adding comments, your code could look like the below:
#include <iostream>
#include <array>
// We want to have a square matrix with 4 rows and 4 coulmns
constexpr unsigned int MatrixSize = 4;
// Save some typing work and make array definition more readable
using SquareMatrix = std::array<std::array<int, MatrixSize>, MatrixSize >;
// Function to print thr frequency of interges in a matrix in the range 0..9
void printFrequencyOfNumbersIn(SquareMatrix& squareMatrix) {
// Check all interger digits in the range 0..9
for (int digit = 0; digit < 10; ++digit) {
// The initial counter value for this digit will always start with 0
int digitCounterForThisDigit = 0;
// Now, iterate over all rows
for (int row = 0; row < MatrixSize; ++row)
// And then iterate over all columns of that row
for (int column = 0; column < MatrixSize; ++column)
// CHeck, if the value in the matrix is equal to the current evaluated digit
if (squareMatrix[row][column] == digit)
// If so, then increment counter
++digitCounterForThisDigit;
// And show the frequency count for the digit under evaluation
std::cout << digit << ':' << digitCounterForThisDigit << ';';
}
}
int main() {
// Define and initialize our squre matrix
SquareMatrix matrix = { {{3,5,7,9}, {2,4,8,9},{1,1,1,1},{3,6,9,2}} };
// Let the subfunction analyze and print the frequencies
printFrequencyOfNumbersIn(matrix);
return 0;
}
This is by far more better understandbale than the original version. Functionality wise it is the same.
And, if you want a "more modern" C++ approach, then you would use a std::map or std::unordered_map. That is the idiomatic correct approach for frequency calculation.
This would then look like that:
#include <iostream>
#include <map>
#include <array>
#include <algorithm>
using MyTpe = int;
// Save some typing work. This will define a square matrix with data of type T
// and rows/columns size equal to template parameter MatrixSize
template <typename T, size_t MatrixSize >
using SquareMatrix = std::array<std::array<T, MatrixSize>, MatrixSize>;
// Here we make an abbreviation for our square matrtx that should consist of 4 rows and 4 columns of ints
using MySquareMatrix = SquareMatrix<MyTpe, 4u>;
// Print frequency of any interger in the matrix
void printFrequencyOfNumbersin(MySquareMatrix& mySquareMatrix) {
// Standard idiomatic approach for counting elements
std::map<MyTpe, size_t> counter{ {0,0u}, {1,0u}, {2,0u}, {3,0u}, {4,0u}, {5,0u}, {6,0u}, {7,0u}, {8,0u}, {9,0u} };
// Go through all rows and columns of the matrix
for (const auto& row : mySquareMatrix) for (MyTpe columnValue : row)
// Count occurence of cell value
counter[columnValue]++;
// Show result to user
for (const auto [number, count] : counter) std::cout << number << ':' << count << ';';
}
int main() {
// Test Data
MySquareMatrix matrix = { {{3,5,7,9}, {2,4,8,9},{1,1,1,1},{3,6,9,2}} };
// Evaluate and print
printFrequencyOfNumbersin(matrix);
return 0;
}

Here is a solution.
#include<bits/stdc++.h>
using namespace std;
int main(){
map<int,int>mp;
int array[4][4] = { {3,5,7,9},{2,4,8,9},{1,1,1,1},{3,6,9,2} };
mp[0]=0,mp[1]=0, mp[2]=0,mp[3]=0, mp[4]=0,mp[5]=0,mp[6]=0,mp[7]=0,mp[8]=0,mp[9]=0;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
int x=array[j][i];
mp[x]++;
}
}
for(auto it=mp.begin();it!=mp.end();it++){
cout<<it->first<<":"<<it->second<<";";
}
}

Related

Count the number of repeating elements in an array

The question is to count the number of repeating elements in the given array:
Suppose the input is:
1
1 2 3 3 3
2
1 2 2 3 3 3 4 5
Then the output should be 3 for the first input and 5 for the second one.
I have written the code, according to logic its output should be 3 but I'm getting the output as 5 could anyone spot the error.
#include <bits/stdc++.h>
using namespace std;
int main() {
int a[5] = {
1,
4,
2,
4,
4
};
int b[101];
memset(b, 0, 101);
int cp = 0, i = 0;
b[a[i]] = 1;
for (int j = i + 1; j < 5; j++) {
if (b[a[j] > 0]) {
if (b[a[j]] == 1)
cp++;
cp++;
b[a[j]]++;
} else
b[a[j]] = 1;
}
cout << cp;
return 0;
}
There is a typo in your code - you wrote if(b[a[j]>0]) instead of if (b[a[j]] > 0), which produces completely different behavior.
To avoid such mistakes, you should format your code properly and give meaningful names to variables. For example, your main function could be rewritten as:
int main() {
const size_t SIZE = 5;
int a[SIZE] = {1, 4, 2, 4, 4};
const int MAX_VALUE = 100;
int count[1 + MAX_VALUE] = {};
int duplicates = 0;
for (int j = 0; j < SIZE; j++) {
if (count[a[j]] > 0)
duplicates++;
if (count[a[j]] == 1)
duplicates++;
count[a[j]]++;
}
cout << duplicates;
}
Note how I also removed a special case for the first array element - it is unnecessary and often prone to errors.
If I read something like
#include <bits/stdc++.h>
using namespace std;
and the variable names, then I assume that this question is related to some competetive programming site. So, my guess is that there are more constraints that we do not know. We see for example the magic number 101 here. Maybe there is a constraint that we have only integers in the range 0..100. Anyway, we do not know.
I would like to show a C++ solution. Basically this is using the standard approach for counting items, by using a std::map or std::unordered_map.
Please see the following code which basically consists of 2 lines. I will explain it afterwards:
#include <iostream>
#include <vector>
#include <unordered_map>
#include <numeric>
std::vector testData{ 1,4,2,4,4 };
int main() {
std::unordered_map<int, size_t> counter{};
// Count the occurence of each integer value
for (const int i : testData) counter[i]++;
// Accumulate repeating values and show result
std::cout << std::accumulate(counter.begin(), counter.end(), 0U, [](size_t c, const auto& p) { return c+(p.second > 1 ? p.second : 0U); });
return 0;
}
As said, we use the standard approach with maps. The important point here is to understand the index operator of a map. Please see here. And read:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
The important point is: It will either return a reference to a value, if it is already in the map. If not, it will create the value in the map and again return a reference to the value. And because we get a reference to the value in any way, we can simply increment it.
After we have done this for all source values from our "testData"-vector in a very simple for loop, we have the count of all values. If the count for one value is greater then 1, then it is a duplicate or "repeated".
Therefore, we just need to accumulate all counters that are greater than 1. And for this we use the dedicated function std::accumulate.
If you should have any questions, then please ask.

C++ Fill an array with random numbers without duplicates

I need to find a way to fill an array with random numbers without having duplicates,so i wrote this code and it works.My question is,is this code efficient and will it really have no duplicates? Thanks in advance!
#include <iostream>
#include <time.h>
#include <stdlib.h>
int main(void) {
srand(time(NULL));
std::size_t array_size=100;
int array[array_size];
for(int i=0;i<array_size;i++) {
array[i]=rand()%105+1;
for(int k=0;k<array_size;k++) { // Checks if there is a duplicate in the array //
if(i!=k) { // Don't check for the same array position //
if(array[i]==array[k]) { // If a duplicate is found,repeat the check process//
array[i]=rand()%105+1;
k=-1; // -1 so the for loop starts from zero //
}
}
}
}
return 0;
}
That approach works fine when the number of desired values is much less than the number of possible values. Most of time it won't produce a duplicate value, so it just keeps the one it produced. But when there isn't a lot of slack there are lots of duplicates; when this code gets close to the end it's generating a value between 1 and 106 when there are only six or seven or so acceptable values. So it ends up spinning its wheels.
Instead of doing all that looping, create an array that holds all of the possible values, randomly shuffle it, and throw out the extra ones:
int array[105];
for (int i = 0; i < 105; ++i)
array[i] = i + 1;
std::mt19937_64 mt;
std::shuffle(std::begin(array), std::end(array), mt);
for (int i = 0; i < 100; ++i)
std::cout << array[i] << '\n';

Sort Specific Column of 2D int array (C++)

I've got a bit of a conundrum. I'm currently trying to create a user-defined function to sort a column (in ascending order) of a 2D int array I created and populated in the main function. I feel like I'm close, but for some reason the final output is incorrect, it provides a number for the final value that isn't even in the array. Judging from the value provided and the extra few seconds it takes to compile, I'm assuming I've messed up my bounds/ gone beyond them at some point within the code, but I've been fighting this thing for hours to no avail and I feel fresh (and likely more experienced) eyes would be-be of some use. I'm still in my "Intro to" class for programming, so ripping me a new one for obvious errors is encouraged as my final is this Thursday and any and all pointers/tips are appreciated. Cheers!
#include <iostream>
using namespace std;
void sort2D(int arr[3][5], int rows, int columns) //the problem child
{
int userCol;
cout<<"Please enter the number of the column you'd like to sort: "<<endl;
cin>>userCol; //ask for appropriate column
for (int row_index=0; row_index<rows; row_index++) //start with first row and continue for all values in code
{
int temp;
if ((arr[row_index][userCol-1]<arr[row_index+1][userCol-1]))//if first value of selected column is less than next value
{
temp = arr[row_index+1][userCol-1];//create copy of second value
arr[row_index+1][userCol-1]=arr[row_index][userCol-1]; //replace second value with first value
arr[row_index][userCol-1]=temp;//set first equal to second's original value
}
}
for(int i=0; i<rows; i++)//print that shiz
{
for(int j=0; j<columns; j++)
{
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
const int rows = 3;
const int columns = 5;
int arr[rows][columns];
for (int row_index=0; row_index<rows; row_index++)
{
for (int column_index=0; column_index<columns; column_index++)
{
arr[row_index][column_index] = (50+rand()%51);
cout << arr[row_index][column_index]<<" ";
}
cout << endl;
}
findMaxandIndex(arr, rows, columns);//i left my code for this out because it's working and isn't utilized in the problem code
cout << endl;
sort2D(arr, rows, columns);
return 0;
Your sort function is very close to bubble sort, one of the simplest sorting algorithms to understand and implement. With a little modification, your code will work :
void sort2D(int arr[3][5], int rows, int columns) //the problem child
{
//input userCol ...
//sorting start here ...
bool found = true; //we can quit the loop if the array is already sorted.
for (int bubble = 0; bubble < rows-1 && found ; bubble++)
{
found = false;
for (int row_index=0; row_index < rows - bubble - 1; row_index++)
{
int temp;
if ((arr[row_index][userCol-1] < arr[row_index+1][userCol-1]))//if first value of selected column is less than next value
{
//swap two elements.
temp = arr[row_index+1][userCol-1];//create copy of second value
arr[row_index+1][userCol-1]=arr[row_index][userCol-1]; //replace second value with first value
arr[row_index][userCol-1]=temp;//set first equal to second's original value
found = true; //we found something, continue to sort.
}
}
}
//print out the result ...
}
As you start in C++, an advice is to use C++ facilities if possible : std::vector for your array and std::qsort for sorting elements.
Issue 1: The int arr[3][5]; you declared in sort2D() is NOT the same as the int arr[rows][columns]; you declared in main().
lesson : check (or web search) on "pass by reference" & "pass by value" . For simplicity, I recommend pass by value.
Issue 2: The sort only compare 2 values and only run for 1 pass.. so {2,1,4,3} may get sorted to {1,2,3,4} but {1,4,3,2} will only get to {1,3,2,4} with 1 pass. #ZDF comment is helpful for this part.
Issue 3: at this line.. temp = arr[row_index+1][userCol-1]; when row_index is 2, this will refer to a location that is not in the arr[][] array. arr are only defined for row = 0,1,2 .. not 3 (when row_index is 2, row_index+1 is 3). This may answer :
it provides a number for the final value that isn't even in the array.
Solution.. hurm. I suggest you have a look and try.. and share where you stuck at. you may also test the sort2D in the main function before doing it as separate function. IMHO, you can start by 1st looking for the sorting algorithm that works (with sample data).. Then work on making it work in this project. ( :
p/s: I don't see my post as an answer.. more like a correction guide.

Why is my randomly generated array outputting only zeroes?

I am writing a code that is supposed to act as a lottery. The lottery numbers available are 1-50, and there are 10 of them. The user is supposed to input one number and the program returns if the user's number matches one of the 10 random lottery numbers. I have gotten all of these parts down, but there is one problem; all 10 of the lottery numbers must be unique. I have gotten 10 unique numbers 1-50, but they weren't very random. The code I have written up to this point seems correct to me, except I know there is something missing (along with the fact that I can clean my code up a lot, but I'm focusing on the objective right now). Right now if I run the program it will return ten zeroes. I need each element in the lottery array to be a unique number from 1-50, and produce different sets of numbers each time i run the program. Any help would be appreciated.
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using std::cout; using std::cin; using std::endl;
void printOut(int[]);
void draw(int[]);
bool check();
int fillFunc[10];
int main()
{
const int arraySize = 10;
int win[arraySize] = {};
srand((unsigned)time(NULL));
draw(win);
cout << "Your lottery numbers are: ";
printOut(win);
}
void draw(int fillFunc[])
{
int i;
for (i = 0; i < 10; i++)
{
if (check() == true)
continue;
fillFunc[i] = 1 + rand() % 50;
}
}
void printOut(int fillFunc[])
{
for (int i = 0; i < 10; i++)
{
cout << " " << fillFunc[i];
}
cout << "\n";
}
bool check()
{
for (int i = 0; i < 10; ++i)
{
if (fillFunc[i] == i)
return true;
}
return false;
}
(also don't ask me why the array has the name "win", this is what my prof wants me to call it)
Because check() always return true. At the start, the array is filled with zeroes so check returns true as win[0]==0 and that remains true forever as nothing changes that value. So in draw you always branch to continue and never modify anything.
To solve the problem one way could be to shuffle the sequence of 1-50 and extract the first 10 values of the shuffled array. You can use the very simple Fisher-Yates algorithm.
To answer your question that you updated in the comments you need to consider a shuffling algorithm.
I will give you an idea of how to do this that is O(n) so you don't have to "loop" thru your current list of numbers and keep checking to see if the new number was already picked...
your lottery max number is 50 so make an array of size 50 that is as follows:
lotteryNumber[0]=1
lotteryNumber[1]=2
...
lotteryNumber[49]=50
to pick a number to put into your "selected" numbers array...
indexToLotteryNumbers = rand() % 50 - numbersPickedSoFar;
randomLotteryNumber[i++] = lotteryNumber[ indexToLotteryNumbers ];
// this is the key "trick"
swap(&lotteryNumber[ indexToLotteryNumbers ], &lotteryNumber[49-numbersPickedSoFar]);
numbersPickedSoFar++;
Theory
The random numbers are the indexes and not the actual values
By swapping the number you picked with the outer element you don't care if your random number generator picks the same index because it will be different the next time.
look at a small example...say you have 1 2 3 4
rand() generates "2"
so your first # is 2 (assume 1-based indexing here) now you swap the (4th) element for the (2nd) element now you have 1 4 3 |2
(here |2 means you can't pick that number again because it's outside the
random # generator range) but you reduce the random # generation from
1-4 to 1 thru 3
rand() generates "1" so your number is "1" and you swap that with the "outer" unpicked number 3 4 |1 2
rand() generates
"2" again! your lottery number is 4 this time... and so on.
I hope this makes sense.
This is what I would do, given your constraints. Rather than check if a number is unique while you are filling the array, just pass the array into the function that chooses the number so it can return a unique value.
I also removed the redundant global array. It could be a source of bugs if you forgot to pass the local array you were working with to any of the functions.
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int getUniqueNumber(int fillFunc[])
{
while(true)
{
//pick number
int val = 1 + rand() % 50;
//assume it's unique
bool unique = true;
for (int i = 0; i < 10; ++i)
{
//if another number matches, it isn't unique, choose again
if (fillFunc[i] == val)
{
unique = false;
break;
}
}
//if it is unique, return it.
if (unique)
{
return val;
}
}
//never reached, but avoids an all control paths must return a value warning.
return -1;
}
void draw(int fillFunc[])
{
for (int i = 0; i < 10; i++)
{
fillFunc[i] = getUniqueNumber(fillFunc);
}
}
void printOut(int fillFunc[])
{
for (int i = 0; i < 10; i++)
{
cout << " " << fillFunc[i];
}
cout << "\n";
}
int main()
{
srand((unsigned)time(NULL));
const int arraySize = 10;
int win[arraySize] = {};
draw(win);
cout << "Your lottery numbers are: ";
printOut(win);
return 0;
}
There are other, perhaps better, ways to select unique numbers in a range, but I went for simple to implement and explain. You can read about some other methods in these questions:
Unique random numbers in an integer array in the C programming language
Unique (non-repeating) random numbers in O(1)?
You only assign a value to fillFunc[i] when i is 10, which is an out of bounds access. Move the assignment to inside the loop.
You have other problems too. If you do continue, you just leave an entry in the array unset.
You should try adding a lot of output statements to your program so you can more easily understand what it's doing. If you prefer, use a debugger to step through it.

Basic obfuscation program

#include<iostream>
#include<conio.h>
#include<math.h>
#include<vector>
#include<iterator>
#include<string>
using namespace std;
int main() {
int k=0;
string s;
cout<<"string ";
getline(cin,s); //taking in a string from the user
float n=s.size(); //storing size of string
int f=floor((sqrt(n))); //floor of square root of input string
int c=ceil((sqrt(n))); //ceiling
int m=f*c; //storing product of f and c
vector< vector<string> > vec(n<=m?f:++f, vector<string>(c)); //makes a 2d vector
//depending on user's
//string length
for(int i=0;n<=m?i<f:i<++f;i++) //looping acc to user's input and assigning
{
for(int j=0;j<c;j++) //string to a matrix
{
if(k<s.size())
{
vec[i][j]=s[k];
k++;
}
}
}
for(int j=0;j<c;j++) //printing the vector
{
{
for(int i=0;n<=m?i<f:i<++f;i++)
cout<<vec[i][j];
}cout<<" ";
}
getch();
}
It's not working for n>m as for a string of length 8 characters it makes a vector of 2*3 thus failing to enclose the whole string in the matrix and which is why I am using ternary so as to make a vector of bigger size when it encounters cases like these.
.So what am I doing wrong?
I'll just write the whole question.
One classic method for composing secret messages is called a square code. The spaces are removed from the english text and the characters are written into a square (or rectangle). The width and height of the rectangle have the constraint,
floor(sqrt(word)) <= width, height <= ceil(sqrt(word))
The coded message is obtained by reading down the columns going left to right. For example, the message above is coded as:
imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau
Sample Input:
chillout
Sample Output:
clu hlt io
This won't fix your entire problem, but I still feel it is important. You seem to misunderstand how the ternary works. Let's observe one of its uses here:
for (int i = 0; n <= m ? i < f : i < ++f; i++) {}
// ^^^^^^^^^^^^^^^^^^^^^^^^ <--- not the intended outcome
This will not work because the returned side of the ternary does not "stick" itself in-place. In other words, neither i < f nor i < ++f will be put directly into the for-loop. Instead, it'll give you a value.
To see what it's really doing, you'll first need to understand that the ternary is just another way to do an if-else. The ternary above, put into if-else form, looks like this:
if (n <= m)
i < f; // left side of the ":"
else
i < ++f; // right side of the ":"
Let's break it down further:
i < f
This is doing a less-than comparison of i and f. So, depending on the individual values, you'll receive either a 0 (false) or a 1 (true).
So, in your for-loop, this will occur:
for (int i = 0; 1; i++) {}
// ^ <--- if comparison returns true
for (int i = 0; 0; i++) {}
// ^ <--- if comparison returns false
So, for your example, you'll need to find the value of f before the loop. You can use a ternary for that part, but only if you understand it. Otherwise, use another method to find f (the intended numerical value). Once you find it, then you can put i < f into the for-loop.