Code for counting frequency of element in array not working - c++

I'm trying to find the frequency of elements in an array. I have found lots of programs on Google that can do just this, but I can't get them to count right for my array.
This is the code I use:
#include <iostrem>
#include <cmath>
const int nmax = 50;
int main() {
int afk[nmax], count;
const int N = 40;
int dn[N] = { 6, 1, 2, 1, 5, 3, 1, 0, 3, 1, 2, 3, 6, 2, 1, 1, 5, 5, 1, 5, 0, 1, 3, 0, 0, 1, 0, 2, 1, 0, 0, 3, 1, 5, 2, 1, 4, 1, 0, 3 };
for (int i = 0; i < N; i++) {
afk[i] = -1;
}
for (int i = 0; i < N; i++) {
count = 1;
for (int j = i + 1; j < N; j++) {
if (dn[i] == dn[j]) {
count++;
afk[j] = 0;
}
}
if (afk[i] != 0) afk[i] = count;
}
for (int i = 0; i <= 6; i++) {
if (afk[i] != 0) {
cout << endl << i << " | " << afk[i];
}
}
}
This gives the output:
0 | 2
1 | 13
2 | 5
4 | 5
5 | 6
But I know this is worng and the right answer is
0 | 8
1 | 13
2 | 5
3 | 6
4 | 1
5 | 5
6 | 2
So the code only gets the frequency of elemnet 1 and 2 right.
Can anyone tell what's wrong with this code?

You are counting the frequencies just fine (well, not as efficiently as you could be), but you are not displaying them correctly.
The afk[] array is storing each number's frequency at the same index as its first occurrence in the dn[] array.
In your final display loop, you are printing the loop counter i itself instead of printing the number at the i'th index of the dn[] array. So, if you change this:
cout << endl << i << " | " << afk[i];
To this:
cout << endl << dn[i] << " | " << afk[i];
Then you will get a more meaningful result:
6 | 2
1 | 13
2 | 5
5 | 5
3 | 6
Note that the frequencies of 0 and 4 are missing, though. The first occurrence of 0 in the dn[] array is at index 7, and the first occurrence of 4 is at index 36. But your display loop stops after index 6, which is why it does not display the frequencies of 0 and 4. You would need to loop over the entire afk[] array to fix that, then you will see the missing entries:
6 | 2
1 | 13
2 | 5
5 | 5
3 | 6
0 | 8
4 | 1
Demo
However, the results are not sorted by number, as you want. To fix that, you will have to either:
sort the dn[] array before counting its frequencies (which, incidentally, will help make counting easier).
change the afk[] array to hold a struct type that contains int number and int frequency members, and then you can sort afk[] on number after counting the frequencies.
if nmax is greater than the largest number in the dn[] array (ie, > 6 in this case), then your counting loop can simply use the number stored at dn[i] as the index into afk[] rather than using i as the index. Then your display loop can simply display the afk[] array as-is (I suspect this is what you originally meant to do). Demo
In which case, it would be far easier to count the frequencies using a std::map instead, and let it handle the counting and sorting for you, eg:
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, int> afk;
int dn[40] = {6, 1, 2, 1, 5, 3, 1, 0, 3, 1, 2, 3, 6, 2, 1, 1, 5, 5, 1, 5, 0, 1, 3, 0, 0, 1, 0, 2, 1, 0, 0, 3, 1, 5, 2, 1, 4, 1, 0, 3};
for(auto number : dn){
afk[number]++;
}
for(auto &p : afk){
cout << p.first << " | " << p.second << endl;
}
}
0 | 8
1 | 13
2 | 5
3 | 6
4 | 1
5 | 5
6 | 2
Demo

Related

How can i remove the duplicate element in output / arrays?

#include <iostream>
using namespace std;
int main()
{
const int ARRAY_SIZE = 10;
int value[ARRAY_SIZE] = { 1, 2, 3, 4, 3, 4, 2, 3, 5, 6};
int value2[100];
for (int i = 0; i < ARRAY_SIZE; i++)
{
for (int j = i + 1; j <= ARRAY_SIZE; j++)
{
if (value[i] == value[j])
{
cout << value[i] << " ";
}
}
}
return 0;
}
The output is
2 3 3 4 3
How can I make the output become 2 3 4 ?
Edit: I'm trying to print all numbers appearing more than once in the value array
I think I should create one more array to store value, but I stuck with it and don't know how to do it.
It helps considerably to sort your array. Then you only need two indices:
a write index, starting at 0
a read index, starting at 1
Loop over your array using the read index. For every array[read] that has a duplicate value at array[read-1], IFF that value also does not exist at array[write], then copy it over and increment your write index.
Finally, the new length of your data is equal to your write index.
The basic idea is this: if I have a sorted list of values:
1 3 3 4 5 5 5 7 7 9
Then I can easily see if a value is a duplicate or not by comparing the current (read) with the previous.
┌────┐
1 3 3 │4 5│ 5 5 7 7 9 -- not duplicates
└────┘
↑
┌────┐
1 3 3 4 │5 5│ 5 7 7 9 -- duplicate values
└────┘
↑
The only remaining trick is to make just a single copy of that value to the write index, which we can do by simply looking at the last thing we wrote.
You can use a std::map to count the number of times a value is in the array. If the number appears 2 or more times, then print it.
#include <iostream>
#include <map>
int main()
{
const int ARRAY_SIZE = 10;
int value[ARRAY_SIZE] = { 1, 2, 3, 4, 3, 4, 2, 3, 5, 6};
std::map <int, int> mp;
for(int i : value)
++mp[i];
for(const auto& p : mp)
if(p.second > 1)
std::cout << p.first << ' ';
}
Link.

How do I create a vector in c++ with different row size?

For example, if I take n=9 inputs from the user.
inputs are = {2 3 1 1 2 5 2 7 8}
My vector should look like this:-
2 3 1 1 2
2 7 8
that is, a vector with 2 rows with different no. of elements in the rows. I want to skip adding 5 to my vector.
How can this be done?
Ideally it should not have any empty row. Even if two consecutive 5's occur, or the sequence starts or ends with a 5, there should not an empty row.
Here are two solutions.
The first checks for the 5 and adds a row if certain criteria is met to determine if a new row is to be added.
The second solution adds a row if 5 is found, and at the end of the processing loop, erases all the blank rows.
Solution 1:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> test = {2, 5, 5, 5, 5, 3, 1, 1, 2, 5, 2, 7, 8};
// Always add an initial first row
std::vector<std::vector<int>> v2d(1);
for (auto v : test )
{
if ( v != 5 )
v2d.back().push_back(v); // add value to the current last row
else
{
// the value is a 5. Check if we need to skip adding this row
if ( !v2d.back().empty() )
// add a new blank row
v2d.push_back({});
}
}
// if last row is blank, remove it.
if ( v2d.back().empty() )
v2d.pop_back();
// output results
std::cout << "The number of rows is " << v2d.size() << "\n";
for ( auto& v1 : v2d )
{
for (auto v : v1 )
std::cout << v << " ";
std::cout << "\n";
}
}
Output:
The number of rows is 3
2
3 1 1 2
2 7 8
Solution 2:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> test = {2, 5, 5, 5, 5, 3, 1, 1, 2, 5, 2, 7, 8};
std::vector<std::vector<int>> v2d(1);
for (auto v : test )
{
// Add a new row if it is a 5
if ( v == 5 )
v2d.push_back({});
else
v2d.back().push_back(v); // add to current last row
}
// remove all the blank rows
v2d.erase(std::remove_if(v2d.begin(), v2d.end(), [&](const std::vector<int>& v) { return v.empty(); }), v2d.end());
// output results
std::cout << "The number of rows is " << v2d.size() << "\n";
for ( auto& v1 : v2d )
{
for (auto v : v1 )
std::cout << v << " ";
std::cout << "\n";
}
}
Output:
The number of rows is 3
2
3 1 1 2
2 7 8

Problem with iteration on array in For loop

I'm having a trouble for a long time in a problem related to array and loops.
Assume an array like:
int arr[] = {2, 3, 5, 3, 6, 8, 10, 1, 9};
The program should print the expected column as shown (note that the table is an idea for clarification of what I actually want to achieve):
max: expected arr[index] for max
------------------------------------
2 : 3 5 value of: arr[0]
3 : 6, 8, 10 value of: arr[3]
1 : 9 value of: arr[7]
This is what I've tried so far:
#include <iostream>
int main(void) {
int arr[] = {2, 3, 5, 3, 6, 8, 10, 1, 9};
int max = arr[0];
int i = 1, it = i;
for (; i <= max; i++) {
if (i == max) {
std::cout << arr[i] << std::endl;
max = arr[it + 1]; // when loop end has come, increment max to next element value
it = i + 2; // incrementing iterator by 2 next element position (after max)
} else {
std::cout << arr[i] << ' '; // when loop is executing
}
}
return 0;
}
What it actually prints which is unexpected V/S what it should print:
3 5 | 3, 5
3 6 8 | 6, 8, 10
10 1 9 | 1, 9
10 | <nothing>
The program is about to get max value and print the next elements until max value reaches the number of element position.
Where the problem's occurring and how to fix it? Please let me know.
So I rewrote your code, frankly I couldn't follow it, it seems a bit confused with variable names that seem a bit off.
Here's some working code. The two key concepts in the code are the place where each block starts (the variable start) and the size of each block (the variable count). Plus I use the size of the whole array sizeof(arr)/sizeof(arr[0]) to terminate the outer loop. Something that wasn't present in your code. If you are using C++17, you can use std::size(arr) instead of sizeof.
int main(void) {
int arr[] = {2, 3, 5, 3, 6, 8, 10, 1, 9};
size_t start = 0;
while (start < sizeof(arr)/sizeof(arr[0]))
{
int count = arr[start];
for (int i = 0; i < count; ++i)
{
std::cout << arr[start + i + 1] << ' ';
}
std::cout << std::endl;
start += count + 1;
}
}
The output is
3 5
6 8 10
9

Product modulo random numbers

A prime p is fixed. A sequence of n numbers is given, each from 1 to p - 1. It is known that the numbers in the sequence are chosen randomly, equally likely and independently from each other. Choose some numbers from the sequence so that their product, taken modulo p, is equal to the given number x. If no numbers are selected, the product is considered equal to one.
Input:
The first line contains three integers separated by spaces: the length of the sequence n, the prime number p and the desired value x
(n=100, 2<=p<=10^9, 0<x<p)
Next, n integers are written, separated by spaces or line breaks: the sequence a1, a2,. . ., an
(0 <ai <p)
Output:
Print the numbers from the sequence whose product modulo p is equal to x. The order in which numbers are displayed is not important. If there are several possible answers, print any of them
Example:
INPUT:
100 11 4
9 6 1 1 10 4 9 10 3 1 10 1 6 8 3 3 9 8
10 3 7 7 1 3 3 1 5 2 10 4 1 5 6 7 2 6
2 8 3 3 6 7 6 3 1 5 10 2 2 10 9 6 8 6
2 10 3 2 7 4 3 2 8 6 4 1 7 2 10 8 4 9
7 9 8 7 4 7 3 2 8 2 3 7 1 5 2 10 7 1 8
6 4 10 10 3 6 10 2 1
OUTPUT:
4 6 10 9
My solution:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n,p,x,y,m,k,tmp;
vector<int> v;
cin >> n >> p >> x;
for (int i = 0; i<n; i++){
cin >> tmp;
v.push_back(tmp);
}
sort(v.begin(), v.end());
v.erase(v.begin(), upper_bound(v.begin(), v.end(), 1));
k=-1;
while(1){
k++;
m = 1;
y = x+p*k;;
vector<int> res;
for (int i = 0; i<n; i++){
if (y == 1) break;
if ( y%v[i] == 0){
res.push_back(v[i]);
m*=v[i];
m%=p;
y = y/v[i];
}
}
if (m==x) {
for (int i = 0; i<res.size(); i++){
cout << res[i] << " ";
}
break;
}
}
return 0;
}
In my solution, I used condition (y=x+k*p, where y is the product of numbers in the answer, and k is some kind of natural number). And also iterated over the value k.
This solution sometimes goes beyond the allotted time. Please tell me a more correct algorithm.
I would consider a backtracking routine over the hashed multiset of the input list. Since p is a prime, at any point we can consider if the current multiple, m, has (multiplicative_inverse(m, p) * x) % p in our multiset (https://en.wikipedia.org/wiki/Multiplicative_inverse). If it exists, we're done. Otherwise, try multiplying either by the same number we are currently visiting in the multiset, or by the next one (keep the result of the multiplication modulo p).
Please see comment below for a link to example code in Python. The example you gave has trivial solutions so it would be helpful to have some non-trivial, as well as challenging examples to test and refine on. Please also clarify if more than one number is expected in the output.
You can use dynamic programming approach. It requires O(p) memory cells and O(p*n) loop iterations. There is possible several optimization (to exclude processing input duplicates, or print longest/shortest selection chain). Following is simplest and basic DP-program, demonstrating this approach.
#include <stdio.h>
#include <stdlib.h>
int data[] = {
9, 6, 1, 1, 10, 4, 9, 10, 3, 1, 10, 1, 6, 8, 3, 3, 9, 8,
10, 3, 7, 7, 1, 3, 3, 1, 5, 2, 10, 4, 1, 5, 6, 7, 2, 6,
2, 8, 3, 3, 6, 7, 6, 3, 1, 5, 10, 2, 2, 10, 9, 6, 8, 6,
2, 10, 3, 2, 7, 4, 3, 2, 8, 6, 4, 1, 7, 2, 10, 8, 4, 9,
7, 9, 8, 7, 4, 7, 3, 2, 8, 2, 3, 7, 1, 5, 2, 10, 7, 1, 8,
6, 4, 10, 10, 3, 6, 10, 2, 1
};
struct elm {
int val; // Value
int prev; // from which elemet we come to this
int n; // add loop cound for prevent multiple use same val
};
void printsol(int n, int p, int x, const int *in) {
struct elm *dp = (struct elm *)calloc(p, sizeof(struct elm));
int i, j;
for(i = 0; i < n; i++) // add initial elements into DP array
dp[in[i]].val = in[i];
for(i = 0; i < n; i++) { // add elements, one by one, to DP array
if(dp[in[i]].val <= 1) // skip secondary "1" multipliers
continue;
for(j = 1; j < p; j++)
if(dp[j].val != 0 && dp[j].n < i) {
int y = ((long)j * in[i]) % p;
dp[y].val = in[i]; // current value, for printout
dp[y].prev = j; // reference to prev element
dp[y].n = n; // loop num, for prevent double reuse
if(x == y && dp[x].n > 0) {
// targed reached - print result, by iterate linklist
int mul = 1;
while(x != 0) {
printf(" %d ", dp[x].val);
mul *= dp[x].val; mul %= p;
x = dp[x].prev;
}
printf("; mul=%d\n", mul);
free(dp);
return;
}
} // for+if
} // for i
free(dp);
}
int main(int argc, char **argv) {
printsol(100, 11, 4, data);
return 0;
}

Modifying iterator inside for loop

I have a problem like this:
I got size of array and the array itself (all the elements) and i need to sort the array in the way that first item in array (lets call it key item) is placed so all items smaller then key item go left from key item and all items larger then key item go right form key item, but the items need to be i a same order as they was in declaration like so:
array input:
4 7 3 5 6 2 9 1 10 8
array output:
3 2 1 4 7 5 6 9 10 8
so i thought i can just go one time through array and if value is smaller then key item swap them and if value is larger then key item, place that value (item ) at the end (if there is n items in array place it on n+1 place) and then to shift all items from current index one place to the left like:
| 4 | 7 | 3 | 5 | 6 | 2 | 9 | 1 | 10 | 8 |
| 4 | | 3 | 5 | 6 | 2 | 9 | 1 | 10 | 8 | 7 |
| 4 | 3 | 5 | 6 | 2 | 9 | 1 | 10 | 8 | 7 |
but like that i would need to after every shifting make iterator stay same (so it can check that place again.
I have a code like this :
int u=1;
for (int i=1;i<n;i++){
if (x[i]<x[u]){
swap(x[i],x[u]);
u+=1;
}else {
x[i]=x[n];
for (int k=i;k<n-1;k++){x[k]=x[k+1];}
i--;
}
}
i think i made a mistake in the swapping part but i cant figure it out.
What you are looking for can be done using the STL's std::stable_partition() algorithm:
divides elements into two groups while preserving their relative order
Let it do the hard work for you, eg:
#include <iostream>
#include <algorithm>
struct doPartitionOn
{
int m_key;
doPartitionOn(int key) : m_key(key) {}
bool operator()(int a)
{
return (a < m_key);
}
};
int main()
{
int arr[] = {4, 7, 3, 5, 6, 2, 9, 1, 10, 8};
for(int i = 0; i < 10; ++i)
std::cout << arr[i] << ' ';
std::cout << std::endl;
std::stable_partition(arr, arr+10, doPartitionOn(arr[0]));
for(int i = 0; i < 10; ++i)
std::cout << arr[i] << ' ';
std::cout << std::endl;
std::cin.get();
return 0;
}
4 7 3 5 6 2 9 1 10 8
3 2 1 4 7 5 6 9 10 8
Live demo
Or, if using C++11 or later, you can use a lambda instead of a manual functor:
#include <iostream>
#include <algorithm>
int main()
{
int arr[] = {4, 7, 3, 5, 6, 2, 9, 1, 10, 8};
for(int value: arr)
std::cout << value << ' ';
std::cout << std::endl;
std::stable_partition(arr, arr+10, [&arr](int a){ return (a < arr[0]); });
for(int value: arr)
std::cout << value << ' ';
std::cout << std::endl;
std::cin.get();
return 0;
}
4 7 3 5 6 2 9 1 10 8
3 2 1 4 7 5 6 9 10 8
Live demo