How to find matching elements in a single vector - c++

I would like to produce the number of times an element is NOT seen again in the vector. The elements in the vector must be randomized by a seed, in this case, 3.
For example, if numbers 2, 6, and 4 are shown again in the vector with the size of 30, the totalComplete should be 27 since 3 numbers repeat themselves.
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
vector<int> seats;
int totalComplete = 0;
srand(3);
seats.resize(30);
for(int k = 0; k < 20; k++){
seats.at(k)=(rand()%30);
cout << seats.at(k);
cout <<" ";
totalComplete++;
for(int j = 0; j < 20; j++){
if(j != k)
if(seats.at(k) == seats.at(j))
totalComplete--;
}
cout<<endl;
}
cout << totalComplete;
return 0;
}
So in my code, the numbers randomly placed in the vector is 6 25 18 0 15 10 12 16 1 4 28 4 3 19 22 21 24 25 1 15. The numbers 25, 15, 1, and 4 repeat themsevles so the totalComplete should be 16. However, my code produces 0. I believe the region where I check if number is repeated is wrong.

My immediate advice would be to separate the code into small pieces, and test each one separately. I'd start with a function to just fill the array with random numbers. Then I'd write a function to just count unique entries. Test each one in isolation, and check that you're getting what you expect. Then when each one works by itself, put them together to get a complete program that does what you really want.

Related

O(n^2) algorithm to find largest 3 integer arithmetic series

The problem is fairly simple. Given an input of N (3 <= N <= 3000) integers, find the largest sum of a 3-integer arithmetic series in the sequence. Eg. (15, 8, 1) is a larger arithmetic series than (12, 7, 2) because 15 + 8 + 1 > 12 + 7 + 2. The integers apart of the largest arithmetic series do NOT have to be adjacent, and the order they appear in is irrelevant.
An example input would be:
6
1 6 11 2 7 12
where the first number is N (in this case, 6) and the second line is the sequence N integers long.
And the output would be the largest sum of any 3-integer arithmetic series. Like so:
21
because 2, 7 and 12 has the largest sum of any 3-integer arithmetic series in the sequence, and 2 + 7 + 12 = 21. It is also guaranteed that a 3-integer arithmetic series exists in the sequence.
EDIT: The numbers that make up the sum (output) have to be an arithmetic series (constant difference) that is 3 integers long. In the case of the sample input, (1 6 11) is a possible arithmetic series, but it is smaller than (2 7 12) because 2 + 7 + 12 > 1 + 6 + 11. Thus 21 would be outputted because it is larger.
Here is my attempt at solving this question in C++:
#include <bits/stdc++.h>
using namespace std;
vector<int> results;
vector<int> middle;
vector<int> diff;
int main(){
int n;
cin >> n;
int sizes[n];
for (int i = 0; i < n; i++){
int size;
cin >> size;
sizes[i] = size;
}
sort(sizes, sizes + n, greater<int>());
for (int i = 0; i < n; i++){
for (int j = i+1; j < n; j++){
int difference = sizes[i] - sizes[j];
diff.insert(diff.end(), difference);
middle.insert(middle.end(), sizes[j]);
}
}
for (size_t i = 0; i < middle.size(); i++){
int difference = middle[i] - diff[i];
for (int j = 0; j < n; j++){
if (sizes[j] == difference) results.insert(results.end(), middle[i]);
}
}
int max = 0;
for (size_t i = 0; i < results.size(); i++) {
if (results[i] > max) max = results[i];
}
int answer = max * 3;
cout << answer;
return 0;
}
My approach was to record what the middle number and the difference was using separate vectors, then loop through the vectors and search if the middle number minus the difference is in the array, where it gets added to another vector. Then the largest middle number is found and multiplied by 3 to get the sum. This approach made my algorithm go from O(n^3) to roughly O(n^2). However, the algorithm doesn't always produce the correct output (and I can't think of a test case where this doesn't work) every time, and since I'm using separate vectors, I get a std::bad_alloc error for large N values because I am probably using too much memory. The time limit in this question is 1.4 sec per test case, and memory limit is 64 MB.
Since N can only be max 3000, O(n^2) is sufficient. So what is an optimal O(n^2) solution (or better) to this problem?
So, a simple solution for this problem is to put all elements into an std::map to count their frequencies, then iterate over the first and second element in the arithmetic progression, then search the map for the third.
Iterating takes O(n^2) and map lookups and find() generally takes O(logn).
include <iostream>
#include <map>
using namespace std;
const int maxn = 3000;
int a[maxn+1];
map<int, int> freq;
int main()
{
int n; cin >> n;
for (int i = 1; i <= n; i++) {cin >> a[i]; freq[a[i]]++;} // inserting frequencies
int maxi = INT_MIN;
for (int i = 1; i <= n-1; i++)
{
for (int j = i+1; j <= n; j++)
{
int first = a[i], sec = a[j]; if (first > sec) {swap(first, sec);} //ensure that first is smaller than sec
int gap = sec - first; //calculating difference
if (gap == 0 && freq[first] >= 3) {maxi = max(maxi, first*3); } //if first = sec then calculate immidiately
else
{
int third1 = first - gap; //else there're two options for the third element
if (freq.find(third1) != freq.end() && gap != 0) {maxi = max(maxi, first + sec + third1); } //finding third element
}
}
}
cout << maxi;
}
Output : 21
Another test :
6
3 4 5 7 7 7
Output : 21
Another test :
5
10 10 9 8 7
Output : 27
You can try std::unordered_map to try and reduce the complexity even more.
Also see Why is "using namespace std;" considered bad practice?
The sum of a 3-element arithmetic progression is 3-times the middle element, so I would search around a middle element, and would start the search from the "upper" end of the "array" (and have it sorted). This way the first hit is the largest one. Also, the actual array would be a frequency-map, so elements are unique, but still track if any element has 3 copies, because that can become a hit (progression by 0).
I think it may be better to create the frequency-map first, and sort it later, simply because it may result in sorting fewer elements - though they are going to be pairs of value and count in this case.
function max3(arr){
let stats=new Map();
for(let value of arr)
stats.set(value,(stats.get(value) || 0)+1);
let array=Array.from(stats); // array of [value,count] arrays
array.sort((x,y)=>y[0]-x[0]); // sort by value, descending
for(let i=0;i<array.length;i++){
let [value,count]=array[i];
if(count>=3)
return 3*value;
for(let j=0;j<i;j++)
if(stats.has(2*value-array[j][0]))
return 3*value;
}
}
console.log(max3([1,6,11,2,7,12])); // original example
console.log(max3([3,4,5,7,7,7])); // an example of 3 identical elements
console.log(max3([10,10,9,8,7])); // an example from another answer
console.log(max3([1,2,11,6,7,12])); // example with non-adjacent elements
console.log(max3([3,7,1,1,1])); // check for finding lowest possible triplet too

Bubble sort the numbers from a file in descending order for the first number

I want to sort using the "Bubble Sort" algorithm of the 2d array. My array size will be about array[100000][100000]. my input number will be n=100,000.
For now we can use a small size of the array to fix the sorting issue.
I need to sort them in descending order for the first number(first number's line).
If the first number of 2 values are the same, then I have to sort them according to their second number.
Finally I have to output the result into a txt file
Let's' understand using an example. Here, my input looks like this
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
above our input example and we have a couple of inputs. Now I need to sort them descending orders for the first number. But if the first number of 2 values are the same, then sort them according to their second number.
Example output below,
81 3
78 6
69 4
62 8
41 4
34 4
5 10
5 5
If anyone can please help me.
I am a beginner so I am trying to input the file manually to solve this sorting problem. I can solve the sorting problem then I will try to input and out the text.
Something I have tried but not worked. I am still trying to solve it.
#include<bits/stdc++.h>
#include <algorithm>
using namespace std;
int main ()
{
int arr[100][100];
int n,j;
cin >>n;
cout << "Please enter a number: " << endl;
for(int i=0;i<n;i++)
{ for (int j=i; j<n; j++)
{
cin>>arr[i][j];
}
}
cout << "Unsorted array:" << endl;
for (int i=0; i<n; i++)
{
for (int j=i; j<n; j++)
{
cout<<arr[i][j]<<"\t";
}
}
for (int i=0; i<=n; i++)
{
for (int j=i+1; j<=n-1; j++)
{
int temp;
if(arr[i]>arr[j])
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
return 0;
}
Use a std::vector<std::array<int,2>>for your base container. The dynamic growth capabilities of std::vector solves your stack space issue, and the std::array use gives you tied cell comparison. I.e. you can do this:
std::array<int, 2> ar1{1,2}, ar2{1,3};
if (ar1 < ar2) ...
and it will do the right thing. The result then boils down to effectively this:
#include <iostream>
#include <array>
#include <vector>
#include <utility>
int main()
{
std::vector< std::array<int,2> > v;
std::size_t n;
if (std::cin >> n && n > 0)
{
std::array<int,2> row;
while (n-- && std::cin >> row[0] && std::cin >> row[1])
v.emplace_back(row);
// bubblesort the content
std::size_t len = v.size();
while (len-- > 0)
{
bool swapped = false;
for (std::size_t i=0; i<len; ++i)
{
// std::array support multi-cell comparison.
if (v[i] < v[i+1])
{
// use library swap to swap entire row.
std::swap(v[i], v[i+1]);
swapped = true;
}
}
// early exit if no swaps happened on the last pass
if (!swapped)
break;
}
// report final output.
for (auto const& row : v)
std::cout << row[0] << ' ' << row[1] << '\n';
}
}
Input
8
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
Output
81 3
78 6
69 4
62 8
41 11
34 4
5 10
5 5

Finding the number of occurences of an integer in multidimensional array in C++

I wish to find the number of occurrences of a number taken as input in the given multidimensional array defined by the logic below:
...
int n,x,count=0;
cin>> n >> x;
int a[n][n] ;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
a[i][j]= i*j ;
}
}
for( int i=1;i<=n;i++)
{
for( int j=1;j<=n;j++)
{
if(a[i][j] == x)
++count;
}
}
cout<< count ;
...
For eg., if I give input as 6(n) and 12(to find its number of occurrences, x here). The multidimensional array looks something like this:
1 2 3 4 5 6
2 4 6 8 10 12
3 6 9 12 15 18
4 8 12 16 20 24
5 10 15 20 25 30
6 12 18 24 30 36
Now, the number of occurences of 12 here is 4(count).
But when I give n as 10 and x as 5, the program stops working. I can't seem to find what is happening. Can someone help me on this?
Also in what way can I modify my code?
How can I handle the case when n is as large as 1000 or 10k without changing the logic of the program?
Indices in C/C++ starts at 0. If an array is declared to have size n as in int a[n] the only valid indices are: 0,1,...,n-1 i.e. [0,n[
If you go out of bound undefined behaviour is expected. That should be your case.
Fix the loops as follows (note the new bounds and the +1 in i and j)
int a[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
a[i][j]= (i+1)*(j+1) ;
#include <algorithm>
// ...
for(int i = 0; i < n; ++i) {
count += std::count(a[i], a[i] + n, x);
}
or a more simpler version:
std::cout << std::count(a[0], a[0] + n*n, x);

Why am I getting two outputs in place of a single one?

I'm writing a simple program and I am getting 2 outputs of the same data with a single cout statement. I think something went wrong with my loop, but I am not able to find where the problem is. If possible, please show me what I need to change; otherwise, I'd at least like to know why my logic is wrong.
My code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int n ;
cin >> n;
vector<int> arr(n);
vector<int> a(n);
for(int arr_i = 0;arr_i < n;arr_i++){
cin >> arr[arr_i];
a[arr_i]=1;
}
int i,least,flag,count=n;
do{
cout<<count<<endl;
count=0;
flag=1;
for(i=0;i<n;i++){ //for getting least number
if(a[i]){
if(flag){
least=arr[i];
flag=0;
}
if(arr[i]<least){
least=arr[i];
}
}
}
for(i=0;i<n;i++){ // for actual logic
if(arr[i]<=0||!a[i]){
a[i]=0;
//continue;
}
else{
arr[i]-=least;
count++;
}
}
}while(count);
return 0;
}
Sample input:
6
5 4 4 2 2 8
Expected output
6
4
2
1
Actual output:
6
6
4
4
2
2
1
1
Problem statement
You are given N sticks, where the length of each stick is a positive integer. A cut operation is performed on the sticks such that all of them are reduced by the length of the smallest stick.
Suppose we have six sticks of the following lengths:
5 4 4 2 2 8
Then, in one cut operation we make a cut of length 2 from each of the six sticks. For the next cut operation four sticks are left (of non-zero length), whose lengths are the following:
3 2 2 6
The above step is repeated until no sticks are left.
Given the length of N sticks, print the number of sticks that are left before each subsequent cut operations.
Note: For each cut operation, you have to recalculate the length of the smallest sticks (excluding zero-length sticks).
One noticed error: when substracting least from arr[i] and arr[i] becoming <=0 a[i] still stays non-zero, and at next iteration you getting least number the same as at previous iteration.
Other problem: your count is count of previous turn. At first iteration it equals 6, because condition if(arr[i]<=0||!a[i]) dont fulfill for any number from input.
After fixing this part:
// for actual logic
if (a[i]) {
arr[i] -= least;
if (arr[i] <= 0)
a[i] = 0;
else
count++;
}
it looks working nice.

Iterated Difference

This is an spoj problem. It works, but It's too slow.
Here is the question:
Iterated Difference
You are given a list of N non-negative integers a(1), a(2), ... ,
a(N). You replace the given list by a new list: the k-th entry of the
new list is the absolute value of a(k) - a(k+1), wrapping around at
the end of the list (the k-th entry of the new list is the absolute
value of a(N) - a(1)). How many iterations of this replacement are
needed to arrive at a list in which every entry is the same integer?
For example, let N = 4 and start with the list (0 2 5 11). The successive iterations are:
2 3 6 11
1 3 5 9
2 2 4 8
0 2 4 6
2 2 2 6
0 0 4 4
0 4 0 4
4 4 4 4
Thus, 8 iterations are needed in this example.
Input
The input will contain data for a number of test cases. For each case,
there will be two lines of input. The first line will contain the
integer N (2 <= N <= 20), the number of entries in the list. The
second line will contain the list of integers, separated by one blank
space. End of input will be indicated by N = 0.
Output
For each case, there will be one line of output, specifying the case
number and the number of iterations, in the format shown in the sample
output. If the list does not attain the desired form after 1000
iterations, print 'not attained'.
Sample Input
4
0 2 5 11
5
0 2 5 11 3
4
300 8600 9000 4000
16
12 20 3 7 8 10 44 50 12 200 300 7 8 10 44 50
3
1 1 1
4
0 4 0 4
0
Sample Output
Case 1: 8 iterations
Case 2: not attained
Case 3: 3 iterations
Case 4: 50 iterations
Case 5: 0 iterations
Case 6: 1 iterations
I'm not sure of what to do to make it faster. I tried using arrays, but I get all sorts of problems trying to allocate the memory and set one array to another.
How can I make it faster? Here's my code:
#include <iostream>
#include <vector>
#include <cmath>
#include <sstream>
#include <string>
using namespace std;
bool checker(vector<int>& nums2) {
int n = nums2[0];
for (int i = 1; i < nums2.size(); i++)
{
if (n != nums2[i])
return false;
}
return true;
}
vector<int> iterate(vector<int>& nums, int& iter, bool& attained) {
if (iter == 1000) {
attained = false;
return nums;
}
vector<int> nums2;
for (int i = 0; i < nums.size(); i++) {
if (i == nums.size() - 1)
nums2.push_back((int)abs((double)nums[i] - (double)nums[0]));
else
nums2.push_back((int)abs((double)nums[i] - (double)nums[i + 1]));
}
iter++;
return nums2;
}
int main()
{
int N = -1, count = 1;
while (1) {
int num = 0;
vector<int> nums;
string List = "";
stringstream ss;
cin >> N;
if (N == 0)
break;
cin.ignore();
cin.clear();
getline(cin, List);
ss << List;
while (ss >> num) {
nums.push_back(num);
}
int iterations = 0;
bool attained = true;
while (!checker(nums)) {
nums = iterate(nums, iterations, attained);
}
if (!attained)
cout << "case " << count << ": not attained";
else
cout << "case " << count << ": " << iterations << " iterations" << endl;
count++;
}
}
I fixed it. It was a problem with the while loop in the main function. The condition was:
while (!checker(nums)) { ... }
It would stay in the loop and repeatedly call the iterate function because if it is not attainable, then the checker will always be false. So changing the condition to:
while (!checker(nums) && attained) { ... }
would break the loop if it was not attainable.
Basically, it was just getting stuck on doing the same thing over and over; it wasn't actually slow.
Thanks, xan, for your answer.
If you want it to be a little faster you should work on debugging your array variation to avoid the vector allocations. If you want it to be a lot faster you need to do some analysis of the problem to find a better algorithm. For instance, if you see the same list twice you're in a loop and will exceed 1000 iterations. And the result will be the same if you rotate the list, which you can consider when checking for a repeated list.
Your implementation executes 1000 iterations in 25ms on my mainstream lapton. Fixed one, because there's a bug and case 2 will execute forever.
To do faster you can reuse the same vector and modify it in place, your iterator() function signature would look like:
void iterate(vector<int>& nums);
This version takes 7ms on my machine, because it doesn't allocate memory in loop.