The C++ version seems to only give unique permutations.
Here’s a function that achieves the same thing, translated from C++ algorithm.h (which is GPL licensed, but I doubt people would sue me for making a julia port available. Nevertheless, don’t put it in a MIT licensed package if you’re careful about this stuff. Or do, I’m not a lawyer ): Here be GPL dragons.
This does require the input to be indexable, but that’s not too much of a problem since general iterators in julia may not even have a defined order of elements you could swap, like the C++ Iter thing seems to guarantee. Too much pointer fiddling…
Now for those who don’t want to read GPL code, here’s a verbatim explanation so some brave soul can reimplement it and make it MIT compatible:
The algorithm is fairly simple, but still achieves O(n) (with constant factor 2 in the worst case that the list is already in reverse sorted order). We basically check trivial cases first (e.g. is the list empty or only has one element?). After that we can just go through the list in reverse, looking for an element that’s smaller than the one after it (i.e. with a higher index). So e.g. in [1,2,4,3]
we’d do our first real work once we hit the element 2
(index 2). Our last element was a 4
(index 3). Since we hit a smaller element, we know that some element between index 2 and the last index (4 in this case) has to be bigger than 2, but it may still be smaller than the last element we looked at. So we go looking for the first element between our the last index and our current index that’s still larger than our current element. Once we find it, we just swap the two elements. Finally, we have to reverse all elements between our last element (index 3) and the last index, since we have put the smallest known element at the end of our list, even though we want to have it at the front of the tail part of our list.
If the list is sorted in reverse order, we just reverse it in place instead (this is where the factor 2 in the worst case comes from, since we have to run through the list once to check if it is sorted in reverse order, and run through again to reverse it).