0

I was trying to use a for loop to replace the recursion that I usually use, but I found it's harder than I thought. Can anyone tell me how to do it? Thanks!

For example, given a vector of 2, 1, 3. There should be six permutations:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

The vector is below...

vector<int> simple;
simple.push_back(2);
simple.push_back(1);
simple.push_back(3);

EDIT: changed the order from 1 2 3 to random order 2 1 3

Arch1tect
  • 4,128
  • 10
  • 48
  • 69
  • did you try anything? – Aswin Murugesh Apr 16 '13 at 21:43
  • Use [`std::next_permutation`](http://en.cppreference.com/w/cpp/algorithm/next_permutation). – Peter Wood Apr 16 '13 at 21:43
  • in case you want to use boost: http://www.boost.org/doc/libs/1_38_0/libs/iterator/doc/permutation_iterator.html – citykid Apr 16 '13 at 21:44
  • @PeterWood It seems next_permutation requires the input to be in order? – Arch1tect Apr 16 '13 at 21:49
  • @Arch1tect Yes, to get all permutations the easiest way, it needs to be sorted to start with. – Peter Wood Apr 16 '13 at 22:05
  • @PeterWood But it doesn't need to be sorted if I use recursion method, does this mean generating permutation should always be done by recursion, and that's what most people do? (since if sorting is needed , it's slower) I'm learning so I'd love to know the way people do in practice. Thanks – Arch1tect Apr 16 '13 at 22:10

1 Answers1

2

I guess you are looking for std::next_permutation():

#include <iostream>
#include <algorithm>
#include <vector>

int main()
{
    std::vector<int> simple{1, 2, 3};

    do
    {
        for (auto e : simple) { std::cout << e << " "; }
        std::cout << std::endl;
    }
    while (next_permutation(simple.begin(), simple.end()));
}

Here is a live example.

If you do not want to start with a sorted vector, you can use std::next_permutation() the following way:

#include <iostream>
#include <algorithm>
#include <vector>

constexpr int factorial(int i)
{
    return i == 0 ? 1 : i * factorial(i-1);
}

int main()
{
    std::vector<int> simple{3, 1, 2};

    for (int i = 0; i < factorial(simple.size()); i++)
    {
        std::next_permutation(simple.begin(), simple.end());
        for (auto e : simple) { std::cout << e << " "; }
        std::cout << std::endl;
    }
}

Here is a live example.

Notice, that if the size of the vector is known at compile-time, as seems to be the case from your example, you could use std::array instead of std::vector, as shown in this live example.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • it seems next_permutation requires the input to be in order? – Arch1tect Apr 16 '13 at 21:48
  • @Arch1tect: Kind of, you're right. If you want all permutations to be found before `next_permutation` returns `false`, then yes. – Andy Prowl Apr 16 '13 at 21:50
  • I was only using 1 2 3 as an example, the vector doesn't have to be in order. Any idea how to solve in this case? Thanks anyway.:) – Arch1tect Apr 16 '13 at 21:53
  • `factorial` won't be what you want if there are duplicates in the vector. – Peter Wood Apr 16 '13 at 21:58
  • @PeterWood: True, although that does not seem to be the OP's use case – Andy Prowl Apr 16 '13 at 22:04
  • Thank you, took me some time to understand the algorithm.. I feel this is slower than the recursion method(using a stack and queue), since next_next_permutation takes some time. Am I right? or it's the same complexity as recursion method? – Arch1tect Apr 16 '13 at 22:17
  • @Arch1tect: It may be slower, the link in my answer shows the complexity and a possible implementation. However, you should not be concerned with optimization unless you find out that performance is really an issue for your use case - most of the time, programmers tend to prematurely optimize their algorithms and data structures, compromising readability and elegance. Unless you have a real reason to worry about it, favor simplicity. – Andy Prowl Apr 16 '13 at 22:26