I created a matrix[10][10] with random numbers
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
matrix[i][j] = rand() % 100 ;
}
}
But I need to use bool function for check duplicate numbers and if its same use random again.How can i do it?
An efficient way to test for duplicates is to store the elements that have been inserted into the matrix in a std::vector and to use to std::find. This allows to check whether a newly generated random number is already included in the previously stored elements or not. If it is found, then another random number should be generated and the test repeated.
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
bool alreadySelected(int n, int nvalues, int values[][10]) {
std::vector<int> v(&values[0][0], &values[0][0] + nvalues );
return (std::find(v.begin(), v.end(), n) != v.end());
}
int main() {
int matrix[10][10];
for (int i = 0; i < 10; i++) {
int n;
bool dupe;
for (int j = 0; j < 10; j++) {
int nvalues = i * 10 + j;
do {
n = std::rand() % 100 ;
dupe = alreadySelected( n, nvalues, matrix );
} while ( dupe );
matrix[i][j] = n;
std::cout << matrix[i][j] << " ";
}
std::cout << "\n";
}
}
A much simpler way to generate such a matrix would be to use std::random_shuffle.
There are multiple ways to achieve this.
Write a function which returns bool and takes 10*10 matrix size. Compute sum of all numbers. Compare this result with the sum of numbers from 1...99. If both matches then no duplicate return true, otherwise duplicate return false. Sum of 1..99 can be calculated using n(n+1)/2, where n = 99.
In function create array of size 100. Initialize all array elements with 0. Iterate over matrix, use matrix element as index of array. If array contains 1 at that position you got duplicate element otherwise make array element at that index 0.
Implementation of first approach
#include <iostream>
#include <cstdlib>
#include <iomanip>
#define ROW 10
#define COL 10
#define MOD 100
int main()
{
int mat[ROW][COL];
int sum = 0;
int range_sum = ((MOD-1)*(MOD))/2; // n = MOD-1, sum = n(n+1)/2
while(true){
sum = 0;
for(int i = 0; i < ROW; i++){
for(int j = 0; j < COL; j++){
mat[i][j] = rand()%MOD;
sum += mat[i][j];
}
}
if(sum==range_sum){
break;
}
}
for(int i = 0; i < ROW; i++){
for(int j = 0; j < COL; j++){
std::cout << std::setw(2) << mat[i][j] << " ";
}
std::cout << std::endl;
}
return 0;
}
Related
How can I change my code to get a count for every element?
With my code everything is okay. And it works, but how can I change only that part?
#include <iostream>
#include <vector>
void countFreq(int arr[], int n)
{
// Mark all array elements as not visited
std::vector<bool> visited(n, false);
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++) {
// Skip this element if already processed
if (visited[i] == true)
continue;
// Count frequency
int count = 1;
for (int j = i + 1; j < n; j++) {
if (arr[i] == arr[j]) {
visited[j] = true;
count++;
}
}
std::cout<<count<<" ";
}
}
int main()
{
int n;
std::cin>>n;
int arr[n];
for(int i = 0; i < n; i++){
std::cin>>arr[i];
}
countFreq(arr, n);
return 0;
}
And about the result`
input 10
1 1 2 2 3 3 4 4 5 5
output 2 2 2 2 2
but I want to get
output 2 2 2 2 2 2 2 2 2 2
(for every element)
Your function contains extra code that ends up confusing you. The visited variable is essentially unnecessary. Start the count at 0 and make no special case for the "current" cell and you'll find that some very simple code will do what you need:
void countFreq(int arr[], int n)
{
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++) {
// Count frequency
int count = 0;
for (int j = 0; j < n; j++) {
if (arr[i] == arr[j]) {
count++;
}
}
std::cout << count << " ";
}
}
You need to save the result to an array for each number. Then when you find any processed number then print counter from the saved array.
#include <iostream>
#include <vector>
#include <unordered_map>
void countFreq(int arr[], int n)
{
// Mark all array elements as not visited
std::vector<bool> visited(n, false);
std::unordered_map<int, int> counter;
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++)
{
// Skip this element if already processed
if (visited[i] == true)
{
std::cout << counter[arr[i]] << " ";
continue;
}
// Count frequency
int count = 1;
for (int j = i + 1; j < n; j++)
{
if (arr[i] == arr[j])
{
visited[j] = true;
count++;
}
}
counter[arr[i]] = count;
std::cout<<count<<" ";
}
}
int main()
{
int n;
std::cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
std::cin>>arr[i];
}
countFreq(arr, n);
return 0;
}
The issue is that you discard the values already visited.
One possibility is instead to memorize the count when the value is visited the first time,
and to memorize the index value of the first value appearance, when a value is visited the 2nd, 3rd ... time.
#include <iostream>
#include <vector>
void countFreq(const std::vector<int>& arr) {
int n = arr.size();
// Mark all array elements as not visited
std::vector<int> mem_count(n, n);
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++) {
// Skip this element if already processed
if (mem_count[i] != n) {
std::cout << mem_count[mem_count[i]] << " ";
continue;
}
// Count frequency
int count = 1;
for (int j = i + 1; j < n; j++) {
if (arr[i] == arr[j]) {
mem_count[j] = i;
count++;
}
}
mem_count[i] = count;
std::cout << count << " ";
}
}
int main() {
int n;
std::cin>>n;
std::vector<int> arr(n);
for(int i = 0; i < n; i++){
std::cin >> arr[i];
}
countFreq(arr);
return 0;
}
You can find the frequencies of numbers this way if you know the what is your maximum element in the input array. lets say m is maximum number in your array.
so you have to create a new array of size m. you can simply co-relate them as m buckets. from 0 to m. And each bucket will hold the count of each element in the input array. The index of each bucket will refer to element in the input array. This has time complexity O(1) if we know what is the max element the array.
You can do this way:
std::vector<int> frequencey(std::vector<int>& nums){
auto max = *(std::max_element(nums.begin(), nums.end()));
std::vector<int> frequencies(max + 1, 0);
for(int i = 0; i < nums.size(); ++i){
frequencies[nums[i]] +=1;
}
return frequencies;
}
This is very simple
#include <vector>
#include <map>
#include <iostream>
void main()
{
std::vector<int> v { 1,1,2,2,3,3,4,4,5,5 }; // Your input vector
// Count "frequencies"
std::map<int, int> m;
for (auto i : v)
m[i]++;
// Print output
for (auto i : v)
std::cout << m[i] << " ";
}
We can define the term 'value of a name' as the average position of
the letters in the name, calculating 'A' as 1, 'B' as 2, 'C' as 3, and
so on. The value of "BOB" would be (2 + 15 + 2)/ 3 = 6. According to
this value, the names will be arranged from the smallest towards the
biggest in the output. When two or more names have the same value,
the name which is in the first position in the original list (the
first one the user inputs) should show up first in the sorted list
(the output).
Input In the first line we have an integer N (1 <= N <= 100), which is
the number of names. In every of the N lines we have one name ([A-Z],
no empty spaces). Names contain 1 - 200 letters.
Output Print out the sorted list (one name in a line).
Test-case
Input: 3 BOB AAAAAAA TOM Output: AAAAAAA BOB TOM
I tried something, and the code seemed to work, I just had a problem with the output. I couldn't find a way to arrange the names with the same value, according to their position in the original list. Here's the other test-case I tried, but didn't figure out:
Input:
10
COSOPYILSPKNKZSTUZVMEERQDL
RRPPNG
PQUPOGTJETGXDQDEMGPNMJEBI
TQJZMOLQ
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
YNWEPZKNBOOXNZVWKIUS
LV
CJDFYDMYZVOEW
TMHEJLIDEHT
KGTGFIFWYTKPWTYQQPGKRRYFXN
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
My output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
CJDFYDMYZVOEW // these two
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM // should be arranged with their places switched
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
#include <iostream>
#include <string>
using namespace std;
int main() {
int N;
cin >> N;
string words[N];
int res[N];
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> words[i];
word = words[i];
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res[i] = value;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
for (int i = 0; i < N; i++) {
cout << words[i] << endl;
}
return 0;
}
string words[N];
int res[N];
This here is not valid C++, you can not size a stack array using a runtime variable, although some compilers might support such a feature. You might use say std::vector instead, which behaves much like an array.
vector<string> words;
vector<int> res;
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> word;
words.push_back(word);
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res.push_back(value);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
The ordering is because your sorting algorithm is not stable. Stable means that items with equal values will maintain the same order relative to each other.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
What you have is very close to bubble sort, which is stable.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N - i - 1; j++) { // i elements sorted so far
if (res[j] > res[j + 1]) {
swap(res[j], res[j + 1]);
swap(words[j], words[j + 1]);
}
}
}
C++ also provides a stable sort in <algorithm>, but it can't function directly on two arrays like this unfortunately, one option is to compute the value on the fly, another could be to make a class holding both items and sort that, or another to sort the indices.
std::stable_sort(words.begin(), words.end(), [&](auto &a, auto &b)
{
int suma = 0, sumb = 0; // better yet, make a "int value(const string &str)" function.
for (int j = 0; j < a.length(); j++) {
suma += (int)a[j] - 64;
}
for (int j = 0; j < b.length(); j++) {
sumb += (int)b[j] - 64;
}
int valuea = suma / a.length();
int valueb = sumb / b.length();
return valuea < valueb;
});
A class containing both items is pretty straight forward, for indices, make a 3rd array and sort that.
vector<size_t> indices;
...
string word;
cin >> word;
indices.push_back(words.size());
words.push_back(word);
...
std::stable_sort(indices.begin(), indices.end(), [&](auto a, auto b){ return res[a] < res[n]; });
for (int i = 0; i < N; i++) {
cout << words[indices[i]] << endl;
}
A possible solution could be order the result array during construction.
When you add the words in the result array, use the result obtained to add the word in the right place. In this way you can check if exist already the same value and add the new word after the previous with the same value.
After reading the next word use insertion sort (wiki) which is stable
read word
calculate value
insert in a right place in the array
go to 1 until i < N otherwise print out
Doesn't require additional sorting procedure.
in python:
def sort_list(list1, list2):
zipped_pairs = zip(list2, list1)
z = [x for _, x in sorted(zipped_pairs)]
return z
times = int(input())
entries = []
ordered = []
for x in range(times):
entries.append(input())
for x in entries:
chars = []
for y in x:
chars.append(ord(y) - 96)
ordered.append(sum(chars))
print(sort_list(entries,ordered))
If you use a std::multimap<int, std::string>, there would be no need to sort, as the key would already serve as the sorting criteria.
Here is a solution using std::multimap:
#include <string>
#include <numeric>
#include <iostream>
#include <sstream>
#include <map>
// Test data
std::string test = "10\n"
"COSOPYILSPKNKZSTUZVMEERQDL\n"
"RRPPNG\n"
"PQUPOGTJETGXDQDEMGPNMJEBI\n"
"TQJZMOLQ\n"
"BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM\n"
"YNWEPZKNBOOXNZVWKIUS\n"
"LV\n"
"CJDFYDMYZVOEW\n"
"TMHEJLIDEHT\n"
"KGTGFIFWYTKPWTYQQPGKRRYFXN\n";
int main()
{
std::istringstream strm(test);
// Read in the data
std::multimap<int, std::string> strmap;
int N;
strm >> N;
std::string word;
for (int i = 0; i < N; ++i)
{
strm >> word;
// get the average using std::accumulate and divide by the length of the word
int avg = std::accumulate(word.begin(), word.end(), 0,
[&](int total, char val) { return total + val - 'A' + 1; }) / word.length();
// insert this value in the map
strmap.insert({ avg, word });
}
// output results
for (auto& w : strmap)
std::cout << w.second << "\n";
}
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
The std::accumulate is used to add up the values to get the average.
Or just order them in the end (You won't need the 2nd array):
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
int sumA = 0, sumB = 0;
for (int k = 0; k < words[i].size(); k++)
sumA += words[i][k] - 'A' + 1;
for (int k = 0; k < words[j].size(); k++)
sumB += words[j][k] - 'A' + 1;
if (sumA / words[i].size() > sumB / words[j].size())
swap(words[i], words[j]);
}
}
As they shown above, it's way better to use a vector to store your data.
I need to Write a program that takes in a square matrix of integers and outputs the largest sub-SQUARE-matrix sum. The first line of input is an integer which indicates the dimension of the square matrix(n*n), followed by the actual matrix row-by-row.
I have a program working however, it outputs the largest sum of a rectangle and not a square which is required.
Example input:
3
1 2 3
4 5 6
-7 -8 -9
Output:
Should be 16 (2+3+5+6) however it is outputting 21 (1+2+3+4+5+6)
As you can see, it is taking the sum of the rectangle but I need it to find a square
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int n;
int mat[100][100];
cin >> n;
int sum = 0;
int maxSum = 0;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
cin>>mat[i][j];
}
}
for (int k = 0; k<n; k++)
{
for (int l = 0; l<n; l++)
{
sum = sum + mat[k][l];
if (sum < 0)
{
sum = 0;
}
if (sum > maxSum)
{
maxSum = sum;
}
}
}
cout << maxSum;
return 0;
}
You were close with your loops. But you have to sum the square for each iteration if that is what you are looking for. Here I'll assume an input and go from there.
Edit: So the summing is clearer.
#include <iostream>
#include <vector>
int main()
{
//initalize(using std::cin here) You can size then load the vectors
std::vector<std::vector<int>> mat = { {1,2,3},{4,5,6},{-7,-8,-9,} };
// then do the work...
int max = std::numeric_limits<int>::min();
//assuming 'square' is 2x2, adjust 'size()-1` if not
for (size_t i = 0; i < mat.size() - 1; ++i)
for( size_t j = 0; j < mat.at(0).size() - 1; ++j)
{
int sum =
mat[i][j] +
mat[i][j+1] +
mat[i+1][j] +
mat[i+1][j+1];
if (sum > max)
max = sum;
}
std::cout << max << std::endl;
}
int temp;
for (int j = 0; j < vecsize - 1; ++j) {
int min = sort.at(j);
for (int i = j+1; i < vecsize; ++i) {
if (min > sort.at(i)) {
min = sort.at(i);
temp = i;
}
}
swap(sort.at(j), sort.at(temp));
}
I am trying to sort (in ascending order) the vector of: 23 42 4 16 8 15
However, my attempt at using selection sort outputs: 4 8 15 23 16 42
What am I doing wrong?
When you define min, you seem to be assigning it the value of the array sort at jth index. Yet, you are using an extra variable tmp to swap the elements, and you seem to fail to initialize it before the inner for loop, similar to how you initialize min. And if all the other elements in the array are smaller than the element at sort[j], tmp will be uninitialized for that iteration of the outer loop, possibly causing it to have an incorrect value in it.
int temp;
for (int j = 0; j < vecsize - 1; ++j) {
int min = sort.at(j);
temp = j; # HERE'S WHAT'S NEW
for (int i = j+1; i < vecsize; ++i) {
if (min > sort.at(i)) {
min = sort.at(i);
temp = i;
}
}
swap(sort.at(j), sort.at(temp));
}
You may see this code at work here. It seems to produce the desired output.
Try this : corrected-code
#include <iostream>
#include <vector>
using namespace std;
void print (vector<int> & vec) {
for (int i =0 ; i < vec.size(); ++i) {
cout << vec[i] << " ";
}
cout << endl;
}
int main() {
int temp;
vector<int> sort;
sort.push_back(23);
sort.push_back(42);
sort.push_back( 4);
sort.push_back( 16);
sort.push_back( 8);
sort.push_back(15);
print(sort);
int vecsize = sort.size();
for (int j = 0; j < vecsize - 1; ++j) {
int min = j;
for (int i = j+1; i < vecsize; ++i) {
if (sort.at(min) > sort.at(i)) {
min = i;
}
}
if (min != j)
swap(sort.at(j), sort.at(min));
}
print(sort);
return 0;
}
If you can use C++11, you can also solve sorting (as in your example) with lambdas. It's a more powerful and optimized way. You should try it maybe in the future.
[EDITED]:
A short example:
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> myVector;
myVector.emplace_back(23);
myVector.emplace_back(42);
myVector.emplace_back(4);
myVector.emplace_back(16);
myVector.emplace_back(8);
myVector.emplace_back(15);
std::sort(myVector.begin(), myVector.end(),
[](int a, int b) -> bool
{
return a < b;
});
}
I'm new to C++ programming. I need to sort this matrix:
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
int main(int argc, char** argv) {
Mat10 a;
fillRand(a, 5, 5);
prnMat(a, 5, 5);
cout << endl;
return 0;
}
void fillRand(Mat10 m, int n, int k) {
for (int i = 0; i < n; i++)
for (int j = 0; j < k; j++)
m[i][j] = rand() % 1000;
}
void prnMat(Mat10 a, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
cout << setw(8) << a[i][j];
cout << endl;
}
}
I need to sort the matrix from the beginning from the beginning. The smallest value must be at the beginning of the of the first column. The next must be below it and so on. The result must be sorted matrix - the smallest number must be at the beginning of the left column - the biggest value must be at the end of the matrix. Would you please help to solve the problem?
EDIT
Maybe I found possible solution:
void sort(int pin[10][2], int n)
{
int y,d;
for(int i=0;i<n-1;i++)
{
for(int j=0; j<n-1-i; j++)
{
if(pin[j+1][1] < pin[j][1]) // swap the elements depending on the second row if the next value is smaller
{
y = pin[j][1];
pin[j][1] = pin[j+1][1];
pin[j+1][1] = y;
d = pin[j][0];
pin[j][0] = pin[j+1][0];
pin[j+1][0] = d;
}
else if(pin[j+1][1] == pin[j][1]) // else if the two elements are equal, sort them depending on the first row
{
if(pin[j+1][0] < pin[j][0])
{
y = pin[j][1];
pin[j][1] = pin[j+1][1];
pin[j+1][1] = y;
d = pin[j][0];
pin[j][0] = pin[j+1][0];
pin[j+1][0] = d;
}
}
}
}
}
But since I'm new to programming I don't understand is this the solution?
Here is a simple example for you:
#include <vector>
#include <algorithm>
using namespace std;
//This is the comparation function needed for sort()
bool compareFunction (int i,int j)
{
return (i<j);
}
int main()
{
//let's say you have this matrix
int matrix[10][10];
//filling it with random numbers.
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
matrix[i][j] = rand() % 1000;
//Now we get all the data from the matrix into a vector.
std::vector<int> vect;
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
vect.push_back(matrix[i][j]);
//and sort the vector using standart sort() function
std::sort( vect.begin(), vect.end(), compareFunction );
//Finally, we put the data back into the matrix
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
matrix[i][j] = vect.at(i*10 + j);
}
After this, the matrix will be sorted by rows:
1 2
3 4
If you want it to be sorted by cols:
1 3
2 4
You need to replace matrix[i][j] in the last cycle only with matrix[j][i]
If you need to read about the the sort() function, you can do it here
Hope this helps.
You can simply call std::sort on the array:
#include <algorithm> // for std::sort
int main() {
int mat[10][10];
// fill in the matrix
...
// sort it
std::sort(&mat[0][0], &mat[0][0]+10*10);
}