C++ permutation using std::list produces infinite loop - c++

I'm trying to generate all permutations of a vector v using backtracking.
The basic idea of my algorithm is:
at each recursive step, iterate through the remaining elements of v, and pick one to add the resulting permutation. I then delete it from the vector v. I'm trying to speed up the deletion operation by using a std::list. However, this seems to produce an infinite recursive loop that outputs only the first possible permutation.
I can only suspect that it's some problem with my handling of the iterator, but I'm not sure how to fix it.
Here's my code below:
#include <vector>
#include <list>
#include <iostream>
using namespace std;
vector<int> res;
list<int> v = {1, 2, 3, 4};
void permute() {
if (v.empty()) {
for (int d : res) cout << d << " ";
cout << endl;
return;
}
for (auto it = v.begin(); it != v.end(); it ++) {
int d = *it;
res.push_back(d);
it = v.erase(it);
permute();
v.insert(it, d);
res.pop_back();
}
}
int main() {
permute();
}
This piece of code just prints "1 2 3 4" forever.
Any help is appreciated. Thanks!!

The problem is here: v.insert(it, d);
You will need to insert the value d back where it was, but you are not doing it.
list is not suitable for what you're trying to do. Use a vector, and instead of deleting, use swaps.

Related

Get number of same values in arrays in C++

I need a function int countDifferentNumbers(int v[], int n) which counts how many different values the array v with n entries contains.
Example:
It should return the result 3 for the array v = {1, 5, 5, 8, 1, 1} because the array contains only 3 different values.
This is how the code looks like so far:
int countDifferentNumbers(int v[], int n)
{
int counter = 0;
for(int i = 0; i < n; ++i)
{
for(int j = i; j < n; ++j)
{
if(v[i] == v[j + 1])
{
cout << "match" << endl;
counter++;
cout << v[i] << endl;
}
}
}
return counter;
}
I would appreciate an explanation of what is wrong in my function and how I need to redesign it.
Note: Unfortunately, I have not found a suitable thread for this either. All threads with my problems were solved in Java and Python languages.
Recently I see more and more answers here on SO that lead users in the wrong direction by giving bad answers.
Also, for C++, the question has already been answered in the comment by Igor Tandetnik, and that should finally be used.
But let me answer the question of the OP as asked. What is wrong with my function? OK, there are several aspects. Let us first look at the style.
You have 0 lines of comments, so the code quality is 0. If you would write comments, then you would already find most bugs by yourself, because then, you need to explain your own wrong statements.
Then please see your source code with my amendments. I added the problems as comment.
// This is just a dumped function and not a minimum reproducible example
// All header files are messing
// Obviously "using namespace std;" was used that should NEVER be done
// The function should retrun an unsigned value, best size_t, because a count can never be negative
// Same for n, that is the size of an array. Can also never be negative
// C-sytle arrays should NEVER be used in C++. NEVER. Use std::vector or std::array instead
int countDifferentNumbers(int v[], int n)
{
int counter = 0; // Now in C++ we can use braced initialzation instead of assignement
for (int i = 0; i < n; ++i)
{
for (int j = i; j < n; ++j)
{
if (v[i] == v[j + 1]) // Accessing out of bounds element
{
cout << "match" << endl; // Now endl needed here. Can all be done in one cout statement in one line
counter++; // Always counting up the same counter for all kind of double numbers.
cout << v[i] << endl;
}
}
}
return counter;
That was one point of the answer. But now the second point. Evene more important. The algorithm or the design is wrong. And finding the correct solution, this thinking before codingt, you need to do, before you write any line of code.
You obviously want to find the count of unique numbers in an array.
Then you could look what is already there on Stackoverflow. You would probaly find 20 answers already that coud give you a hint.
You could use std::unique. Please see here for a description. This function sounds like it does what you want, right? Some example implementation:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
// If you want to keep the original data, remove the reference-specifier &
size_t countDifferentNumbers(std::vector<int>& v) {
std::sort(v.begin(), v.end()); // Sorting is precondition for std::unique
v.erase(std::unique(v.begin(), v.end()), v.end()); // Erase all non-unique elements
return v.size(); // Return the result
}
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << countDifferentNumbers(test) << '\n'; // SHow result to user
return 0;
}
Then, we could count the occurence of each number in a std::map or std::unordered_map. And the number of counters will be the result. Example:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
// If you want to keep the original data, remove the reference-specifier &
size_t countDifferentNumbers(std::vector<int>& v) {
std::unordered_map<int, size_t> counter{}; // Here we will count all occurences of different numbers
for (const int i : v) counter[i]++; // Iterate over vector and count different numbers
return counter.size(); // Count of different numbers
}
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << countDifferentNumbers(test) << '\n'; // Show result to user
return 0;
}
But, then, thinking further, about what conatiners we could use, we will find out the answer from Igor Tandetnik. There are 2 containers that can hold unique values only. No double values. And these are: std::set and std::unordered_set., So, we can simply copy the data into one of those containers, and, only unique values will be stored there.
There are many ways to get the data into a set. But the simplest one is to use its range constructor. Then, we have unique elements, and, the containers size function will give the result:
See here: Constructor Number 2.
The result will be a function with one line like this
#include <iostream>
#include <unordered_set>
#include <vector>
// If you want to keep the original data, remove the reference-specifier &
size_t countDifferentNumbers(std::vector<int>& v) {
return std::unordered_set<int>(v.begin(), v.end()).size();
}
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << countDifferentNumbers(test) << '\n'; // Show result to user
return 0;
}
And since functions with one line are often not so usefull, we can also write the final solution:
#include <iostream>
#include <unordered_set>
#include <vector>
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << std::unordered_set<int>(test.begin(), test.end()).size() << '\n'; // Show result to user
return 0;
}
So, by analyzing the problem and choosing the right algorithm and container and using C++, we come to the most easy solution.
Please enable C++17 for your compiler.
first sort the array v. if n >0 then initially there must be one number which is unique so just increment the value of counter once. then with loop check if the two consecutive number are same or not. if same do nothing else increment the value of counter.
if you are writing code in c then use qsort. #include <stdlib.h> add this in header and. use qsort() func
here is the code:
#include <bits/stdc++.h>
using namespace std;
int countDifferentNumbers(int v[] , int n)
{
int counter = 0;
sort(v, v+ n); // if you are writing code in c then just write a decent sort algorithm.
if (n>0 ){
printf("%d\n", v[0]);
counter ++;
}
for(int i = 0; i < n-1; ++i)
{
if(v[i] == v[i+1]){
continue;
} else {
printf("%d\n", v[i+1]);
counter++;
}
}
return counter;
}
int main()
{
int v[] = {1, 5, 5, 8, 1, 1};
int result = countDifferentNumbers(v,6);
printf("unique number %d", result );
return 0;
}

Seek item within vector

I have a vector of real values, sorted by increasing order.
These values can be within the range [0, 1]. Then I pick a value x within this range and I need to find which is the index of the smaller value greater or equal to x.
I can solve this problem by iterating over the whole array:
vector<double> values;
double x;
for (auto val : values)
{
if (x <= values)
{
// found
break;
}
}
Is there a faster way to get the same result? I was thinking about a binary search, but how to implement it?
Use std::lower_bound:
#include <iterator>
#include <algorithm>
std::distance(begin(values)
, std::lower_bound(begin(values), end(values), x));
If the item doesn't exist, it'll give you an index one greater than that of the last element.
DEMO
The function lower_bound might meet your demand,and you can use it like below:
iter =lower_bound(values.begin(),values.end(),x);
You can use operator[] to directly access the items in a vector just like an array, instead of using an iterator to start from the begin. I assume you already know Binary Search. Implement it in an array is something you can find anywhere, so I won't explain it to you here. Just treat the vector as an array.
You know SO is not a site that you request someone to write you the code, so take this example of std::binary_search and make your way:
// binary_search example
#include <iostream> // std::cout
#include <algorithm> // std::binary_search, std::sort
#include <vector> // std::vector
bool myfunction (int i,int j) { return (i<j); }
int main () {
int myints[] = {1,2,3,4,5,4,3,2,1};
std::vector<int> v(myints,myints+9); // 1 2 3 4 5 4 3 2 1
// using default comparison:
std::sort (v.begin(), v.end());
std::cout << "looking for a 3... ";
if (std::binary_search (v.begin(), v.end(), 3))
std::cout << "found!\n"; else std::cout << "not found.\n";
// using myfunction as comp:
std::sort (v.begin(), v.end(), myfunction);
std::cout << "looking for a 6... ";
if (std::binary_search (v.begin(), v.end(), 6, myfunction))
std::cout << "found!\n"; else std::cout << "not found.\n";
return 0;
}
As Piotr said, this will not give you the index, but a yes/no answer. However, is should be the simplest approach, thus the fastest.

how can I find repeated elements in a vector [duplicate]

This question already has answers here:
Checking for duplicates in a vector [duplicate]
(5 answers)
Closed 9 years ago.
I have a vector of int which can include maximum 4 elements and minimum 2, for example :
std::vector<int> vectorDATA(X); // x means unknown here
What I want to do is to erase the elements that are repeated for example :
vectorDATA{1,2,2} to vectorDATA{1,2}
vectorDATA{1,2,3} to nothing changes
vectorDATA{2,2,2} to vectorDATA{2}
vectorDATA{3,2,1,3} to vectorDATA{3,2,1}
vectorDATA{1,2,1,2} to vector{1,2}
and so on
here a code simple :
cv::HoughLines(canny,lineQ,1,CV_PI/180,200);
std::cout << " line Size "<<lineQ.size()<< std::endl;
std::vector<int> linesData(lineQ.size());
std::vector<int> ::iterator it;
if(lineQ.size() <=4 && lineQ.size() !=0 ){
if(lineQ.size()==1){
break;
}else {
for ( int i = 0; i<lineQ.size();i++){
linesData[i] = lineQ[i][1]; // my comparison parameter is the lineQ[i][1]
}
// based on the answer I got I'm trying this but I really don't how to continue ?
std::sort(lineQ.begin(),lineQ.end(),[](const cv::Vec2f &a,const cv::Vec2f &b)
{
return ????
}
I tried use a for and do while loop, but I didn't get it, and the function std::adjacent_find this has a condition that the elements should be consecutive.
Maybe it's easy but I just don't get it !
thanks for any help !
The easy way is sort then unique-erase, but this changes order.
The c++11 order preserving way is to create an unordered_set<int> s; and do:
unordered_set<int> s;
vec.erase(
std::remove_if( vec.begin(),vec.end(), // remove from vector
[&](int x)->bool{
return !std::get<1>(s.insert(x)); // true iff the item was already in the set
}
),
vec.end() // erase from the end of kept elements to the end of the `vec`
);
which is the remove-erase idiom using the unordered_set to detect duplicates.
I didn't see a sort-less source code in the already mentioned answers, so here it goes. Hash table for checking duplicates, shifting unique elements towards the front of the vector, note that src is always >= dst and dst is the number of copied, i.e. unique elements at the end.
#include <unordered_set>
#include <vector>
#include <iostream>
void
uniq (std::vector<int> &a) {
std::unordered_set<int> s;
size_t dst = 0;
for (size_t src = 0; src < a.size(); ++src) {
if (s.count (a[src]) == 0) {
s.insert (a[src]);
a[dst++] = a[src];
}
}
a.resize (dst);
}
int
main () {
std::vector<int> a = { 3, 2, 1, 3, 2, 1, 2, 3, 4, 5 ,2, 3, 1, 1 };
uniq (a);
for (auto v : a)
std::cout<< v << " ";
std::cout << std::endl;
}
If you want to realy remove repeated elements, you may try something like this:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
int data[] = {1,2,3,2,1};
vector<int> vectorDATA = (&data[0], &data[0] + 5);
sort(vectorDATA.begin(),vectorDATA.end());
for(int i = 0; i < vectorDATA.size()-1; ++i)
{
if(vectorDATA[i] == vectorDATA[i+1])
vectorDATA.erase(vectorDATA.begin()+i+1);
}
for(int i = 0; i < vectorDATA.size();++i)
{
cout << vectorDATA[i] << " ";
}
cout << endl;
return 0;
}
Lack of of this method is then elements lost his order.

Assign int value to vector using iterator

I'm sitting on a small exercise in C++ Primer (3.23) for almost 2 days. I've tried many ways of assigning a value to vector<int>. I'll give you an actual exercise on which I work and code with which I came so far, but its totally wrong. I did a lot of research but found nothing useful.
Write a program to create a vector with 10 int elements. Using an iterator, assign each element a value that is twice its current value. Test the program by printing vector
And this is my code
int main(){
vector<int> num(10);
for (auto it=num.begin();it != num.end() ;++it)//iterating through each element in vector
{
*it=2;//assign value to vector using iterator
for (auto n=num.begin() ;n!=num.end();++n)//Iterating through existing elements in vector
{
*it+=*n;// Compound of elements from the first loop and 2 loop iteration
}
cout<<*it<<" ";
}
keep_window_open("~");
return 0;
}
My problem is I don't know how to assign an int value to each vector element using an iterator (I did to 1 but not to the five elements)! In addition I was breaking my head on how to do this exercise with 10 elements in vector, to each element must be a different value and an iterator must do the assignment.
Thank you for your time.
Here's a much cleaner version of the accepted answer, using the concept of incrementing the iterator instead of a for loop:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> num(10);
int n = 1;
vector<int>::iterator it = num.begin();
vector<int>::iterator itEnd = num.end();
while (it != itEnd)
{
*it = n = n*2;
cout << *it << " ";
it++;
}
}
You can do like this:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> num(10);
int initial_value = 2;
*num.begin() = initial_value;
cout<<*num.begin()<<" ";
for (std::vector<int>::iterator it=num.begin()+1; it != num.end() ;++it)//iterating thru each elementn in vector
{
*it=*(it-1) * 2;//assign value wtih 2 times of previous iterator
cout<<*it<<" ";
}
return 0;
}
You just need to give some initial value to the first iterator and the rest is calculated in a for loop

C++ check how many same elements in a row are in a vector

I have a big vector with 24.000 elements like :
(1,1,1,1,3,3,3,3,3,3,5,5,5,...etc)
and I want to check how many same elements are in a row like:
4-6-3..etc
I use this code :
static int counter=1;
vector<int>numbers;
for(int n=0;n<numbers.size()-1;n++)
{
if(numbers[n]==numbers[n+1])
{
counter++;
}
else if(numbers[n]!=numbers[n+1])
{
cout<<counter<<endl;
counter=1;
}
}
is there any algorithm that does the same faster;
#rhalbersma basically gave you the right answer. As an addendum, in case you want to rewrite your algorithm in a more standard fashion:
#include <algorithm>
#include <vector>
#include <iterator>
#include <functional>
#include <iostream>
int main()
{
std::vector<int> v { 1, 1, 2, 3, 3, 5, 5, 5 }; // or whatever...
auto i = begin(v);
while (i != end(v))
{
auto j = adjacent_find(i, end(v), std::not_equal_to<int>());
if (j == end(v)) { std::cout << distance(i, j); break; }
std::cout << distance(i, j) + 1 << std::endl;
i = next(j);
}
}
Here is a live example.
Also, when the vector is sorted, this will give you better best-case complexity:
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
int main()
{
std::vector<int> v { 1, 1, 2, 3, 3, 5, 5, 5 }; // must be sorted...
auto i = begin(v);
while (i != end(v))
{
auto ub = upper_bound(i, end(v), *i);
std::cout << distance(i, ub) << std::endl;
i = ub;
}
}
Here is a live example.
Your algorithm is O(N) in time, and that seems pretty optimal to me since you have to visit every unique element for comparison. You might still shave off a few cycles here and there e.g. by eliminating the condition inside the else() or by turning on some compiler settings, but algorithmically you are in good shape.
If the input were already sorted, you could do a series of binary searches. That would give you O(N lg N) worst-case complexity but the average case might be considerably lower depending on the average length of equal element sequences.
BTW, as #AndyProwl shows in his answer: the Standard Library is really awesome to do even this kind of low-level algorithmic stuff. The adjacent_find and upper_bound algorithms have well-documented complexities and the iterator conventions will guard you for edge cases that are present in your own code. Once you learn this vocabulary, you can easily use them in your own routines (and when Ranges come to C++, hopefully it'll also easier to compose them).
There is some litle optimization that may give you a few ms:
int size = numbers.size()-1;
static int counter=1;
static int *num1 = &numbers[0];
static int *num2 = &numbers[1];
for(int n=0;n<size;n++)
{
if(*num1==*num2) counter++;
else
{
cout << counter << "\n";
counter=1;
}
num1++;
num2++;
}
cout<<counter<<endl; //Caution, this line is missing in your code!!
Basicaly:
Avoid access to the vector by id: numbers[n] mean that the computer must multiply n*sizeof(int) and add this result to numbers. Is faster to use pointer and increment it, that mean just an add.