I am trying to write a code that find the sum of all the possible numbers in a 2d matrix.
But the catch is that you must choose one element from one row.
#include <algorithm>
#include <iostream>
#include <vector>
#include <climits>
#include <math.h>
using namespace std;
int main() {
int n;
cin>>n;
int array[n][n]={0};
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>array[i][j];
}
}
int power=pow(n,n);
int sum[power]={0};
for(int i=0;i<power;i++){
for(int j=0;j<n;j++){
for(int l=0;l<n;l++){
sum[i]=sum[i]+array[j][l];
}
}
}
for(int i=0;i<power;i++){
cout<<sum[i]<<" ";
}
return 0;
}
this code only brings out the sum of all the elements in the 2d array. So i need help trying to find all the possible sum given one element from each row is chosen for each sum.
2
1 1
1 2
2, 3, 2, 3
this should be the output but it only gives out 5
Your core loop is all wrong. If you want sum[i] to contain the values for a given path, you need to treat i as if it were a path through the matrix.
In general, treat i as a number in base n (=2 for your example).
That means
i = idx_1 * n^(n-1) + idx_2 * n^(n-2) + ... + idx_n
You can recover the various indexes by repeatedly dividing by n and taking the remainder:
for(uint64_t i=0;i<power;i++){
sum[i] = 0;
uint64_t encoded_index = i;
for (size_t j = 0; j < n; j++) {
uint64_t index_j = encoded_index % n;
encoded_index /= n;
sum[i] += hist[j][index_j];
}
}
And of course this trick only works if n*n < 2**64 (as uint64_t is 64 bits).
For a more general approach see my answer to your other question.
Related
This question already has answers here:
How to find the minimum number of operation(s) to make the string balanced?
(5 answers)
Closed 1 year ago.
I'm trying to write this program that asks for user input of string, my job is to print out the minimum number of steps required to equalize the frequency of distinct characters of the string.
Example
Input
6
aba
abba
abbc
abbbc
codedigger
codealittle
Output
1
0
1
2
2
3
Here is my program:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<char, int >m;
vector<int> vec1, vec2;
string s;
int n;
cin >> n;
cin.ignore();
for (int i = 0; i < n; ++i)
{
m.clear();
vec1.clear();
getline(cin, s);
for (int i = 0; i < s.size(); i++)
m[s[i]]++;
for (auto itr : m)
vec1.push_back(itr.second);
sort(vec1.begin(), vec1.end());
int mid = vec1[vec1.size() / 2];
int ans = 0;
for (auto itr : vec1)
ans += abs(mid - itr);
vec2.push_back(ans);
}
for (int i = 0; i < vec2.size(); ++i)
cout << vec2[i] << endl;
}
What I tried to do is for each test case:
Using an unordered_map to count the frequency of the characters of the string.
Push the key values of the map to a vector.
Sort the vector in ascending order.
Calculate the middle element of the vector to equalize the distinct characters with as least steps as possible.
The result will add the difference between the middle element with the current element.
Push the result to another vector and print it.
But my result is wrong at test case number 5:
1
0
1
2
3 // The actual result is 2
3
I don't understand why I get the wrong result, can anyone help me with this? Thanks for your help!
The issue is that your algorithm is not finding the optimal number of steps.
Consider the string you obtained an incorrect answer for: codedigger. It has 4 letters of frequency 1 (coir) and 3 letters of frequency 2 (ddeegg).
The optimal way is not to convert half the letters of frequency 2 into some new character (not present in the string) to make all frequency 1. From my understanding, your implementation is counting the number of steps that this would require.
Instead, consider this:
c[o]dedigge[r]
If I replace o with c and r with i, I obtain:
ccdediggei
which already has equalized character frequencies. You will note that I only performed 2 edits.
So without giving you a solution, I believe this might still answer your question? Perhaps with this in mind, you can come up with a different algorithm that is able to find the optimal number of edits.
Your code correctly measures the frequencies of each letter, as the important information.
But then, there were mainly two issues:
The main target value (final equalized frequency) is not necessarily equal to the median value. In particular, this value must divide the total number of letters
For a given targeted height value, your calculation of the number of steps is not correct. You must pay attention not to count twice the same mutation. Moreover, the general formula is different, depending the final number of different letters is equal, less or higher than the original number of letters.
The following code focuses on correctness, not on efficiency too much. It considers all the possible values of the targeted height (frequency), i.e. all the divisors of the total number of letters.
If efficiency is really a concern (not mentioned in the post), then for example one could consider that the best value is unlikely to be very far from the initial average frequency value.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <unordered_map>
// calculates the number of steps for a given target
// This code assumes that the frequencies are sorted in descending order.
int n_steps (std::vector<int>& freq, int target, int nchar) {
int sum = 0;
int n = freq.size();
int m = nchar/target; // new number of characters
int imax = std::min (n, m);
for (int i = 0; i < imax; ++i) {
sum += std::abs (freq[i] - target);
}
for (int i = imax; i < n; ++i) {
sum += freq[i];
}
if (m > n) sum += m-n;
sum /= 2;
return sum;
}
int main() {
std::unordered_map<char, int >m;
std::vector<int> vec1, vec2;
std::string s;
int n;
std::cin >> n;
std::cin.ignore();
for (int i = 0; i < n; ++i)
{
m.clear();
vec1.clear();
//getline(cin, s);
std::cin >> s;
for (int i = 0; i < s.size(); i++)
m[s[i]]++;
for (auto itr : m)
vec1.push_back(itr.second);
sort(vec1.begin(), vec1.end(), std::greater<int>());
int nchar = s.size();
int n_min_oper = nchar+1;
for (int target = 1; target <= nchar; ++target) {
if (nchar % target) continue;
int n_oper = n_steps (vec1, target, nchar);
if (n_oper < n_min_oper) n_min_oper = n_oper;
}
vec2.push_back(n_min_oper);
}
for (int i = 0; i < vec2.size(); ++i)
std::cout << vec2[i] << std::endl;
}
I am writing a code where 2d matrix array is given and by choosing 1 element from each row you must output the smallest sums. Sums as in you must give n number of minimum sums
#include<iostream>
#include<math.h>
using namespace std;
int main() {
int n;
cin>>n;
int hist[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>hist[i][j];
}
}
int num=pow(n,n);
int sum[num];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
sum[i]=sum[i]+hist[i][j];
}
}
for(int i=0;i<n;i++){
cout<<sum[i]<<" ";
}
return 0;
}
example input would be:
3
1 8 5
9 2 5
10 7 6
The output will be
9 10 12
since 1+2+6=9; 1+2+7=10; 1+2+10
The main problem I am facing would be that I can't find the lowest sum or even the sums I tried to brute force it put it won't work.
Could you help me fix the code so that at least I could find the sums?
Many problems with your code (it's not even legal C++). But the problem that is causing your current question is that you must initialise sum to zero. at the moment you have garbage values in sum.
int sum[num] = {0};
Some other issues
int num=pow(n,n);
This calculates n to the power of n, but there are only n squared sums. So this would be better
int sum[n*n] = {0};
But the big issue, the issue that makes your code illegal C++, is that in C++ array dimensions must be compile time constants not variables. So this
int hist[n][n];
and this
int sum[num];
are not legal C++. They are legal in C, which is why your compiler is accepting them, but not every C++ compiler would. Since you are trying to write C++ code you should use a vector. Here's your code rewritten to use vectors.
#include <vector>
using std::vector;
...
vector<vector<int>> hist(n, vector<int>(n));
...
vector<int> sum(num, 0);
...
That's it nothing else needs to change.
Instead of brute forcing, why not realize that the smallest path is simply the smallest element of each row and the second smallest path is the smallest element of the first n-1 rows, and the second smallest element of n.
You can elegantly express this by sorting the rows of the matrix first and then keeping a counter of where you are at each row:
#include <algorithm>
#include <iostream>
#include <vector>
struct path {
path(int n) : n(n), indexes(n) {}
// Add one to last row index, then carry over to previous rows.
path& operator ++() {
indexes.back()++;
for (int i = n-1; i >= 0; i--) {
if (indexes[i] == n) {
indexes[i] = 0;
indexes[i-1]++;
} else {
break;
}
}
return this;
}
int n;
std::vector<int> indexes;
};
Now your problem is as simple as:
int main() {
int n;
cin>>n;
std::vector<std::vector<int>> hist(n, std::vector<int>(n));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>hist[i][j];
}
// sort each row after reading
std::sort(hist[i].begin(), hist[i].end());
}
int num_minimum_sums = n;
path p(n);
while (num_minimum_sums-- > 0) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += hist[i][p.indexes[i]];
}
std::cout << sum << std::endl;
++p;
}
}
I am trying to output 9 random non repeating numbers. This is what I've been trying to do:
#include <iostream>
#include <cmath>
#include <vector>
#include <ctime>
using namespace std;
int main() {
srand(time(0));
vector<int> v;
for (int i = 0; i<4; i++) {
v.push_back(rand() % 10);
}
for (int j = 0; j<4; j++) {
for (int m = j+1; m<4; m++) {
while (v[j] == v[m]) {
v[m] = rand() % 10;
}
}
cout << v[j];
}
}
However, i get repeating numbers often. Any help would be appreciated. Thank you.
With a true random number generator, the probability of drawing a particular number is not conditional on any previous numbers drawn. I'm sure you've attained the same number twice when rolling dice, for example.
rand(), which roughly approximates a true generator, will therefore give you back the same number; perhaps even consecutively: your use of % 10 further exacerbates this.
If you don't want repeats, then instantiate a vector containing all the numbers you want potentially, then shuffle them. std::shuffle can help you do that.
See http://en.cppreference.com/w/cpp/algorithm/random_shuffle
When j=0, you'll be checking it with m={1, 2, 3}
But when j=1, you'll be checking it with just m={2, 3}.
You are not checking it with the 0th index again. There, you might be getting repetitions.
Also, note to reduce the chances of getting repeated numbers, why not increase the size of random values, let's say maybe 100.
Please look at the following code to get distinct random values by constantly checking the used values in a std::set:
#include <iostream>
#include <vector>
#include <set>
int main() {
int n = 4;
std::vector <int> values(n);
std::set <int> used_values;
for (int i = 0; i < n; i++) {
int temp = rand() % 10;
while (used_values.find(temp) != used_values.end())
temp = rand() % 10;
values[i] = temp;
}
for(int i = 0; i < n; i++)
std::cout << values[i] << std::endl;
return 0;
}
I'm trying to make a c++ program that finds the maximum non perfect square in an array and print it, perfect square i.e. x = y^2 => 4 = 2^2.
Here is what I've tried and doesn't work for me, don't know why:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n;
cin >> n;
int arr[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
sqrt(arr[i]);
if ((arr[i] * 10) % 10 == 0)
arr[i] = arr[1];
else
arr[i] = arr[0];
}
for (int i = 0; i < n; i++)
{
if (arr[0] < arr[i])
arr[0] = arr[i];
}
cout << arr[0] << endl;
return 0;
}
My logic is to take the square root of each array element and check if it's non-perfect or perfect. If we multiply the element by 10, then take modulus of 10, then we know whether it is an integer or decimal. For example: 2*10 = 20, 20%10 = 0 (perfect square), otherwise it is not perfect. Then, I stored each non-perfect square in arr[0], in the next loop I'm supposed to find the largest non perfect square and print it. What am I doing wrong?
PS:
Consider arr[variable] is valid, because it works in CodeBlocks. Thank you!
You lost the result of sqrt. sqrt(arr[i]) does not change arr[i]).
You improperly check if a square root is an integral. You should cast a result of sqrt to int, multiply it by itself and compare with arr[i].
I left you free to update your code properly yourself.
You can use this logic to find if a number is perfect-square or not, this is one way to find largest non perfect square of an array of positive numbers, initialize answer=-1 before you enter the loop, n is the size of the array
double answer = -1,temp;
for(int i=0;i<n;i++){
if((temp = array[i]) != (sqrt(array[i])*sqrt(array[i]))){
if(temp > answer){
answer = temp;
}
}
}
#include <iostream>
#include <cmath>
using namespace std;
int main () {
int n;
cin>>n;
int k[n];
double arr[n];
for (int i = 0 ; i < n ; i++){
cin>>k[i];
arr[i]=sqrt(k[i]);
int j = arr[i];
if (arr[i]==j){
arr[i]=0;
}
}
double m=0;
int index = 0;
for (int i = 0; i < n; i++){
if (arr[i]>m){
m=arr[i];
index = i;
}
}
cout << k[index];
}
Here is a code. We introduce a double, such that it can store the decimals. Then we introduce an integer. If the square root of the number is a decimal, it is not a perfect square. However, when I introduce this integer j, it will convert arr[i] to an integer. If the number is a perfect square, then arr[i] is an integer, and j==arr[i]. We do not want that, so we put that equal 0. We find the largest array, and mark the index. Then we print out the original number in the original array with that index. i have added this as float does not store every single decimal point.
To clarify: lets say arr[i]=4.55556. Then j=4. arr[i]!=j. If arr[i]=5, j=5, arr[i]=j, and then arr[i] is set to 0.
repeating of a number is allowed but the probability is limited
for example:
giving a number sequence 0-8,i want to generate a 25 number random sequence,the max repeate time of a digit is 3.
One relatively foolproof method is rejection sampling. Generate 25 numbers independently. If any number appears more than 3 times, throw them all away and try again. This method has poor worst-case performance, but it's so simple that you won't have to worry that you've accidentally introduced unwanted correlations.
As far as I understand you need something like this (Reworked according to comment below):
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <iostream>
using std::vector;
using std::cout;
vector<int> Generate(const vector<int> & numbers, int generateN, int maxRepeatN)
{
vector<int> longList(numbers.size() * maxRepeatN);
for(int i = 0; i < numbers.size(); i++)
for(int j = 0; j < maxRepeatN; j++)
longList[i * maxRepeatN + j] = numbers[i];
vector<int> result(generateN);
for(int i = 0; i < generateN; i++)
{
int id = rand() % longList.size();
result[i] = longList[id];
longList.erase(longList.begin() + id);
}
return result;
}
int main()
{
srand((unsigned)time(0));
vector<int> numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8}
vector<int> result = Generate(numbers, 25, 3);
for(int i = 0; i < result.size(); i++)
cout << result[i] << " ";
return 0;
}
Idea of algorithm is that you create long list of all possible digits to get (it guarantees that you won't get more than a max digits of one type). Then you get digits one by one from it (removing digits after getting from long list guarantees distribution).
*This code is for example only and such use of std::vector is not optimal at all.