Troubleshooting a nested FOR loop that increments two variables - c++

I am trying to solve the apartments problem on CSES. VERY new to coding and not looking for a solution.. just help with troubleshooting.
https://cses.fi/problemset/task/1084/.
I want to match n applicants to m apartments based on cost, given a list of each. It works with sample inputs, but many tests still fail. I think the issue is with my vector manipulation in the nested for loop.
Example of a test that fails
n 10
m 10
k 10
n integers 90 41 20 39 49 21 35 31 74 86
m integers 14 24 24 7 82 85 82 4 60 95
Expected result for aptsMatched: 6, my result: 3
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, k, aptfill, aptsize;
int aptsMatched = 0;
vector<int> desiredSize;
vector<int> apts;
int b=0;
cin >> n;
cin >> m;
cin >> k;
I'm sure there's a better way to do this.. but I'm brand new and attempted to do this in an intuitive manner. Was able to successfully fill my vectors with the inputs below.
for (int i = 0; i < n; i++) {
cin >> aptfill;
desiredSize.push_back(aptfill);
sort(desiredSize.begin(), desiredSize.end());
reverse(desiredSize.begin(), desiredSize.end());
}
for (int i = 0; i < m; i++) {
cin >> aptsize;
apts.push_back(aptsize);
sort(apts.begin(), apts.end());
reverse(apts.begin(), apts.end());
}
I'm attempting to iterate through the apts vector 3x, each time holding the apts index value constant while iterating through the desiredSize vector indices. Suspect something is wrong with the nested loop - either j<desiredSize.size(); or flawed logic in the if statement... or even with the erase function. My questions are: how can I test what's going wrong here? is there possibly a better container?
for (int i = 0; i < m; i++) {
for (int j = 0; j < desiredSize.size(); j++) {
if (abs(apts[b] - desiredSize[j]) <= k) {
desiredSize.erase(desiredSize.begin() + j);
b++;
aptsMatched++;
break;
}
else {
continue;
}
}
}
cout << aptsMatched;
}
I realize this code is pretty hideous, and that there are much faster ways to achieve the same idea. I'd first like to understand this methodology (if it's not completely flawed to start with), but am open to more effective ways to approach this problem too.
Thanks

One way could be to sort both the desired sizes and the appartment sizes and start matching from the smallest and upwards.
Example:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
int max_diff = 10;
std::vector<int> desired{90, 41, 20, 39, 49, 21, 35, 31, 74, 86};
std::vector<int> apts{14, 24, 24, 7, 82, 85, 82, 4, 60, 95};
std::sort(desired.begin(), desired.end());
std::sort(apts.begin(), apts.end());
int aptsMatched = 0;
auto dit = desired.begin(); // iterator to the desired sizes
auto ait = apts.begin(); // iterator to appartment sizes
// loop until one of them reaches the end
while(dit != desired.end() && ait != apts.end()) {
// do we have a good fit?
if(*dit + max_diff >= *ait // the maximum size is >= appartment size
&&
*dit - max_diff <= *ait ) // the minimum size is <= appartment size
{
++aptsMatched;
++dit;
++ait;
} else // not a good fit, step the iterator to the smallest size
if(*dit < *ait) ++dit;
else ++ait;
}
std::cout << aptsMatched << '\n';
}

I want to match n applicants to m apartments based on cost
But there is no cost; you mean desired size, right? ... but even then - how do you want to match applicants to apartments?
Since you're a beginner, consider writing down your algorithm in your own words, in English - both for yourself, before you write your C++ code, and for us if you want help understanding what' going wrong.
Also, here are some red flags for you:
You're sorting your (partial) data repeatedly - n and m times respectively! That's almost certainly the wrong thing to do.
You're reversing your (partial) data repeatedly. This too seems quite redundant.
Other issues with your code:
You really should not include internal library headers which are not defined by the standard, like <bits/whatever>. See here.
Your shorthand names are confusing. First, n and m are quite opaque. Also, aptfill, b? No idea what that's supposed to mean.
Why bother sorting in one direction, then reversing? Just sort in the opposite direction. Or, alternatively, you can iterate the sorted array backwards.

Related

Error in saving degrees of polynomial for Polynomial Calculator

I am creating a polynomial calculator for 2 polynomials in C++. For different operations, I have created different functions. Below is my approach for the function for multiplication. For multiplying, first I must save all the possible degrees. This should mean a max of highest degree of polynomial1+polynomial2, and least of smallest degree of either. I am first just saving all the possible degree options taking into consideration polynomial1 and polynomial 2. I will then sort the degrees in descending order, perform calculations on coefficients, and save the coefficient according to the degree calculated.
However I am unable to properly save all the possible degree options, and can't spot the error. The values that are actually being saved, I can't seem to understand, why they are being saved, and where is the error. I am writing this program without utilising external libraries like for performing calculations. Kindly spot the error, and how I can successfully save all the possible degree options correctly. The comments are my understanding of what is happening/ should be happening. Thanks.
The ideal output should be:
"99, 97, 95, 93, 91, 89, 98, 96, 94, 92, 90, 88...."
The current output is:
"99 96 93 90 87 84 81 78 75 72 688904896 32629 119 114 109 104 97 94 89 84 79 74 1377809792 65258 218 210 202 194 184 178"
#include <iostream>
using namespace std;
void multiply(int degree_poly1[], int terms_poly1, int degree_poly2[], int terms_poly2, int degree_result[])
{
int temp=0;
for(int a=0; a<terms_poly1*terms_poly2; a++)
{//this is first term
//degrees
for(int b=0; b<=a; b++)
{//this is 2nd term
if(degree_result[b]==0){
//checks if location is empty or not
//dr[0]=0, so go on
temp=degree_poly1[a]+degree_poly2[b];
for(int c=0; c<=b; c++)
{
if(temp==degree_result[c]){
//checks if there is already a value temp in previous array throughout. yes means stop
break;
}
if(temp!=degree_result[c]){
//checks
degree_result[b]=temp;
}
}
temp=0;
}
}
}
for(int a=0; a<terms_poly1*terms_poly2; a++)
{
cout<<degree_result[a]<<" ";
}
}
int main()
{
int degree_poly11[10]={79,78,77,76,75}, terms_poly11=5, degree_poly22[10]={20,18,16,14,12}, terms_poly22=6, degree_resultt[100]={};
/*
The whole program saves a polynomial 5x^9 + 7x^3 + 2x^2 as coefficients 5,7,2 in coefficient1[0], coefficient1[1], coefficient1[2] AND the degrees 9,3,2 in degree_poly11[0], degree_poly11[1], degree_poly11[2]. terms_poly11 gives the no. of total terms in the equation i.e. 3.
This array is currently not present here but is present in complete program.
Similarly for another polynomial2 in coefficient22[] and degree_poly22[].
*/
multiply(degree_poly11, terms_poly11, degree_poly22, terms_poly22, degree_resultt);
return 0;
}
One problem in your code is
temp=degree_poly1[a]+degree_poly2[b];
both a and b loop till 30, but both arrays have only 10 elements. You are accessing the arrays out of bounds and your code has undefined behavior. Even if all the rest would be ok, the output of the code could be anything because of this out-of-bounds access.
It is hard to understand the intended logic of your multiply function. Naming variables is a big issue in your code. a, b and c are completely meaningless to the reader of the code. Though already in main names are confusing.
You have
int degree_poly11[10]={79,78,77,76,75}, terms_poly11=5, ...;
I suppose degree_poly11 are the coefficients of the first polynome. Further, I guess that terms_poly11=5 is the degree of the polynome. If thats the case then name them like that.
When you need arrays of variable size you should think: std::vector.
I suggest to take pen and paper and calculate some examples (not one, but some). When you multiply two polynomials, their degrees add up and the coefficients are:
( poly1 * poly2)_{i} = sum_{j,k,j+k==i} ( poly1_{j} * poly2_{k} )
ie, the i-th coefficient is a sum of all products of coefficients from the input polynomials, such that their indices add up to i. Frankly, I don't see anything like that in your code.
Just this directly translated to code can look like this:
#include <vector>
#include <iostream>
std::vector<double> mult(const std::vector<double>& a,const std::vector<double>& b) {
std::vector<double> result(a.size() + b.size() - 1);
for (int i=0; i< result.size(); ++i) {
for (int j = 0; j <= i && j < a.size(); ++j) {
int k = i-j;
if (k >= b.size()) continue;
result[i] += a[j] * b[k];
}
}
return result;
}
int main(){
auto res = mult( {-1,1},{1,1});
for (int i=0;i<res.size();++i){
std::cout << res[i] << "*x^" << i << " + ";
}
}
Output is:
-1*x^0 + 0*x^1 + 1*x^2 +
Seems to be correct, because (x+1)*(x-1) == (x^2 -1). I didn't test more yet.
(x+1) and (x-1) are of degree 1, thats one less than they have coefficients, and the result has one coefficient more than its degree (a polynomial of degree 0 is a constant, it has 1 coefficient). Hence the size of the output vector a.size() + b.size() - 1.
The outer loop is to calculate i-th coefficient. Loop counters are choosen such that all combinations of j and k that add up to i are passed and included in the sum. Because I know my first attempt is off by one somewhere I have additional checks to be sure that j < a.size() and k < b.size().

Fastest way to find smallest missing integer from list of integers

I have a list of 100 random integers. Each random integer has a value from 0 to 99. Duplicates are allowed, so the list could be something like
56, 1, 1, 1, 1, 0, 2, 6, 99...
I need to find the smallest integer (>= 0) is that is not contained in the list.
My initial solution is this:
vector<int> integerList(100); //list of random integers
...
vector<bool> listedIntegers(101, false);
for (int theInt : integerList)
{
listedIntegers[theInt] = true;
}
int smallestInt;
for (int j = 0; j < 101; j++)
{
if (!listedIntegers[j])
{
smallestInt = j;
break;
}
}
But that requires a secondary array for book-keeping and a second (potentially full) list iteration. I need to perform this task millions of times (the actual application is in a greedy graph coloring algorithm, where I need to find the smallest unused color value with a vertex adjacency list), so I'm wondering if there's a clever way to get the same result without so much overhead?
It's been a year, but ...
One idea that comes to mind is to keep track of the interval(s) of unused values as you iterate the list. To allow efficient lookup, you could keep intervals as tuples in a binary search tree, for example.
So, using your sample data:
56, 1, 1, 1, 1, 0, 2, 6, 99...
You would initially have the unused interval [0..99], and then, as each input value is processed:
56: [0..55][57..99]
1: [0..0][2..55][57..99]
1: no change
1: no change
1: no change
0: [2..55][57..99]
2: [3..55][57..99]
6: [3..5][7..55][57..99]
99: [3..5][7..55][57..98]
Result (lowest value in lowest remaining interval): 3
I believe there is no faster way to do it. What you can do in your case is to reuse vector<bool>, you need to have just one such vector per thread.
Though the better approach might be to reconsider the whole algorithm to eliminate this step at all. Maybe you can update least unused color on every step of the algorithm?
Since you have to scan the whole list no matter what, the algorithm you have is already pretty good. The only improvement I can suggest without measuring (that will surely speed things up) is to get rid of your vector<bool>, and replace it with a stack-allocated array of 4 32-bit integers or 2 64-bit integers.
Then you won't have to pay the cost of allocating an array on the heap every time, and you can get the first unused number (the position of the first 0 bit) much faster. To find the word that contains the first 0 bit, you only need to find the first one that isn't the maximum value, and there are bit twiddling hacks you can use to get the first 0 bit in that word very quickly.
You program is already very efficient, in O(n). Only marginal gain can be found.
One possibility is to divide the number of possible values in blocks of size block, and to register
not in an array of bool but in an array of int, in this case memorizing the value modulo block.
In practice, we replace a loop of size N by a loop of size N/block plus a loop of size block.
Theoretically, we could select block = sqrt(N) = 12 in order to minimize the quantity N/block + block.
In the program hereafter, block of size 8 are selected, assuming that dividing integers by 8 and calculating values modulo 8 should be fast.
However, it is clear that a gain, if any, can be obtained only for a minimum value rather large!
constexpr int N = 100;
int find_min1 (const std::vector<int> &IntegerList) {
constexpr int Size = 13; //N / block
constexpr int block = 8;
constexpr int Vmax = 255; // 2^block - 1
int listedBlocks[Size] = {0};
for (int theInt : IntegerList) {
listedBlocks[theInt / block] |= 1 << (theInt % block);
}
for (int j = 0; j < Size; j++) {
if (listedBlocks[j] == Vmax) continue;
int &k = listedBlocks[j];
for (int b = 0; b < block; b++) {
if ((k%2) == 0) return block * j + b;
k /= 2;
}
}
return -1;
}
Potentially you can reduce the last step to O(1) by using some bit manipulation, in your case __int128, set the corresponding bits in loop one and call something like __builtin_clz or use the appropriate bit hack
The best solution I could find for finding smallest integer from a set is https://codereview.stackexchange.com/a/179042/31480
Here are c++ version.
int solution(std::vector<int>& A)
{
for (std::vector<int>::size_type i = 0; i != A.size(); i++)
{
while (0 < A[i] && A[i] - 1 < A.size()
&& A[i] != i + 1
&& A[i] != A[A[i] - 1])
{
int j = A[i] - 1;
auto tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
for (std::vector<int>::size_type i = 0; i != A.size(); i++)
{
if (A[i] != i+1)
{
return i + 1;
}
}
return A.size() + 1;
}

Performance optimization nested loops

I am implementing a rather complicated code and in one of the critical sections I need to basically consider all the possible strings of numbers following a certain rule. The naive implementation to explain what I do would be such a nested loop implementation:
std::array<int,3> max = { 3, 4, 6};
for(int i = 0; i <= max.at(0); ++i){
for(int j = 0; j <= max.at(1); ++j){
for(int k = 0; k <= max.at(2); ++k){
DoSomething(i, j, k);
}
}
}
Obviously I actually need more nested for and the "max" rule is more complicated but the idea is clear I think.
I implemented this idea using a recursive function approach:
std::array<int,3> max = { 3, 4, 6};
std::array<int,3> index = {0, 0, 0};
int total_depth = 3;
recursive_nested_for(0, index, max, total_depth);
where
void recursive_nested_for(int depth, std::array<int,3>& index,
std::array<int,3>& max, int total_depth)
{
if(depth != total_depth){
for(int i = 0; i <= max.at(depth); ++i){
index.at(depth) = i;
recursive_nested_for(depth+1, index, max, total_depth);
}
}
else
DoSomething(index);
}
In order to save as much as possible I declare all the variable I use global in the actual code.
Since this part of the code takes really long is it possible to do anything to speed it up?
I would also be open to write 24 nested for if necessary to avoid the overhead at least!
I thought that maybe an approach like expressions templates to actually generate at compile time these nested for could be more elegant. But is it possible?
Any suggestion would be greatly appreciated.
Thanks to all.
The recursive_nested_for() is a nice idea. It's a bit inflexible as it is currently written. However, you could use std::vector<int> for the array dimensions and indices, or make it a template to handle any size std::array<>. The compiler might be able to inline all recursive calls if it knows how deep the recursion is, and then it will probably be just as efficient as the three nested for-loops.
Another option is to use a single for loop for incrementing the indices that need incrementing:
void nested_for(std::array<int,3>& index, std::array<int,3>& max)
{
while (index.at(2) < max.at(2)) {
DoSomething(index);
// Increment indices
for (int i = 0; i < 3; ++i) {
if (++index.at(i) >= max.at(i))
index.at(i) = 0;
else
break;
}
}
}
However, you can also consider creating a linear sequence that visits all possible combinations of the iterators i, j, k and so on. For example, with array dimensions {3, 4, 6}, there are 3 * 4 * 6 = 72 possible combinations. So you can have a single counter going from 0 to 72, and then "split" that counter into the three iterator values you need, like so:
for (int c = 0; c < 72; c++) {
int k = c % 6;
int j = (c / 6) % 4;
int i = c / 6 / 4;
DoSomething(i, j, k);
}
You can generalize this to as many dimensions as you want. Of course, the more dimensions you have, the higher the cost of splitting the linear iterator. But if your array dimensions are powers of two, it might be very cheap to do so. Also, it might be that you don't need to split it at all; for example if you are calculating the sum of all elements of a multidimensional array, you don't care about the actual indices i, j, k and so on, you just want to visit all elements once. If the array is layed out linearly in memory, then you just need a linear iterator.
Of course, if you have 24 nested for loops, you'll notice that the product of all the dimension's sizes will become a very large number. If it doesn't fit in a 32 bit integer, your code is going to be very slow. If it doesn't fit into a 64 bit integer anymore, it will never finish.

What is the complexity of this program

I have solved a question on HackerEarth.
The question is
Phineas is Building a castle in his backyard to impress Isabella ( strange, isn't it? ). He has got everything delivered and ready. Even the ground floor has been finished. Now is time to make the upper part. This is where the things become interesting. As Ferb is sleeping in the house after a long day painting the fence (and you folks helped him, didn't ya!), Phineas has to do all the work himself. He is good at this, and all he wants you to do is operate the mini crane to lift the stones. Stones for the wall has been cut and ready waiting for you to lift them up.
Now we don't have Ferb to operate the mini crane, in which he is an expert, we got to do the job as quick as possible. We are given the maximum lifting capacity of the crane, and the weight of each stone. Since it's a mini crane, we cannot place more then 2 stones (of any possible size) at a time, or it will disturb the balance of the crane. we need to find out in how many turns we can deliver the stones to Phineas, who is building the castle.
INPUT: First line of input gives T, the number of test cases. For each test case, first line gives M, the maximum lifting capacity of the crane. first integer N of next line of each test case gives the number of stones, followed by N numbers, specifying the weight of individual stone X.
OUTPUT: For each test case, print the minimum number of turns the crane is operated for all stones to be lifted.
CONSTRAINTS:
1 <= T <= 50
1 <= M <= 1000
1 <= N <= 1000
Sample Input
1
50
3 28 22 48
Sample Output
2
Explanation
In first turn, 28 and 22 will be lifted together. In second turn 48 will be lifted.
Discard the stones with weight > max capacity of crane.
Now I have solved this question and I my source code is
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace std;
int main(void) {
int T = 0;
scanf("%d",&T);
while(T--) {
int i = 0,M = 0, N = 0,max = 0, res = 0, index = 0, j = 0, temp = 0;
vector<int> v1;
scanf("%d",&M);
scanf("%d",&N);
for(i = 0; i < N ;++i) {
scanf("%d",&temp);
if(temp <= M)
v1.push_back(temp);
}
for(i = 0; i < v1.size() ; ++i) {
max = 0;
index = 0;
if(v1[i] != -1) {
for(j = i + 1; j < v1.size(); ++j) {
if(v1[j] != -1) {
temp = v1[i] + v1[j];
if(temp > max && temp <= M) {
max = temp;
index = j;
}
}
}
++res;
v1[i] = -1;
v1[index] = -1;
}
}
printf("%d\n",res);
}
return 0;
}
Now here are my question
I want to know the average case time complexity of this code. Also I think worst case complexity of this code would be O(N^2).
This is a brute force approach or dynamic programming approach?
Is there any better approach then this?
This is a simplified version of Knapsack Prolblem
While the Knapsack problem is a typical dynamic programming question, this simplified question does not require dynamic Programming. Complexity of your solution is indeed O(n^2), the approach is more suitable described as Greedy As you tried to find a optimal pair for each stone, if there exist. The complexity can be further reduced to O(nlgn) if you sort the stones first and work on a sorted vector.

Picking random coordinates without duplicates?

I want to choose random coordinates on a 8x8 board. The x and y coordinates can only be -8. -6, -4, -2, 0, 2, 4, 6, and 8. I want to choose random coordinates for 20 objects but I don't want any 2 objects to have the same coordinates. Program away in C++!
You've only got 9 possible values for each coordinate, so that's 81 possible points in all. The simplest solution would be to just enumerate all possible points (eg: in an array or vector), and then randomly select 20.
You can randomly select 20 by picking an index from 0 to 80, swapping that element of the array with index 80, and then randomly picking an index from 0 to 79, swapping that with index 79, and so on 20 times. Then the last 20 elements of your array will be 20 distinct random points.
Take all of the coordinate pairs in your set, and toss them into a list, and generate a random permutation of the list (standard algorithms exist for this, such as the algorithm Laurence is suggesting). Take the first 20 elements of the permutation.
If you can enumerate all coordinates on the board, you can use any sampling algorithm. You're on a 9x9 grid; just pick 20 values out of the range [0,80] and then translate them into grid coordinates:
// Say the number picked is "n"
int x = ((n % 9) - 4) * 2;
int y = ((n / 9) - 4) * 2;
You can use any sampling algorithm to generate the ns; check out the answers to this question, for example.
The advantage of this approach over generating the points explicitly is that you can save quite a bit of memory (and processing time) on large grids. If they're really large and you're picking a small simple, the obvious algorithm works fine too: Just pick a random point and try again if you already picked it. The only problem with this algorithm is that it can end up doing quite many retries if you're selecting a large fraction of a set.
Putting Laurence's algorithm in program. Its working fine.
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
//To store x and y coordinate of a point
struct Point
{
int x, y;
};
int main()
{
vector<Point> v;
Point p;
//Populate vector with 81 combinations.
for(int i = -8; i < 10; i += 2)
{
for(int j = -8; j < 10; j += 2)
{
p.x = i;
p.y = j;
v.push_back(p);
}
}
srand(time(NULL));
int lastIndex = 80;
for(int i = 0; i < 20; i++)
{
int randNum = rand() % (81-i);
//Swap to isolate chosen points.
std::swap(v[randNum], v[lastIndex-i]);
}
//Print chosen random coordinates
cout<<"Random points chosen are "<<endl;
for(int i = 61; i < 81; i++)
{
Point p = v[i];
cout<<p.x<<"\t"<<p.y<<endl;
}
}
You could use std::random_shuffle for instance, since you have a finite number of integer coordinates. So just shuffle that set of vectors/positions around. You can also pass your own RNG to random_shuffle as a function object.
Example:
#include <algorithm> //for copy and random_shuffle
#include <utility> //for pair and make_pair
#include <vector>
...
std::vector<std::pair<int, int> > coords;
std::vector<std::pair<int, int> > coords20(20);
for(int y=-8; y<=8; y+=2)
for(int x=-8; x<=8; x+=2)
coords.push_back(std::make_pair(x,y));
std::random_shuffle(coords.begin(), coords.end());
std::copy(coords.begin(), coords.begin() + 20, coords20.begin());