8 #ifndef INCLUDE_MOLASSEMBLER_TEMPLE_PERMUTATIONS_H
9 #define INCLUDE_MOLASSEMBLER_TEMPLE_PERMUTATIONS_H
18 namespace Molassembler {
29 template<
class Container>
31 const std::size_t size = container.size();
33 std::size_t index = 0;
34 std::size_t position = 2;
35 std::size_t factor = 1;
37 for(std::size_t p = size - 2; p != std::numeric_limits<std::size_t>::max(); --p) {
38 std::size_t largerSuccessors = 0;
40 for(std::size_t q = p + 1; q < size; ++q) {
41 if(container[q] < container[p]) {
46 index += (largerSuccessors * factor);
58 template<
typename Container>
64 auto intermediate = std::move(data.at(b));
65 data.at(b) = std::move(data.at(a));
66 data.at(a) = std::move(intermediate);
73 template<
typename Container>
76 const std::size_t indexFrom,
77 const std::size_t indexTo
79 std::size_t a = indexFrom;
80 std::size_t b = indexTo;
81 while(a != b && a != --b) {
94 template<
typename Container>
97 const std::size_t
first,
98 const std::size_t last
100 std::size_t size = data.size();
106 throw "Call parameters to inPlaceNextPermutation make no sense!";
109 std::size_t i = last - 1;
118 && data.at(--i) < data.at(j)
124 && !(data.at(i) < data.at(--k))
140 template<
typename Container>
153 template<
typename Container>
156 const std::size_t
first,
157 const std::size_t last
159 unsigned size = data.size();
165 throw "Call parameters to inPlaceNextPermutation make no sense!";
168 std::size_t i = last - 1;
177 && data.at(j) < data.at(--i)
183 && !(data.at(--k) < data.at(i))
199 template<
typename Container>
206 template<
class Container>
209 std::begin(container),
215 template<
class Container>
218 std::begin(container),
238 template<
class Container>
243 assert(toPermute.size() == limits.size());
244 const unsigned cols = toPermute.size();
248 for(
unsigned i = 0; i < cols; ++i) {
249 if(toPermute[i] != limits[i]) {
260 for(
int i = cols - 1; i >= 0; --i) {
261 if(toPermute[i] == limits[i]) {
288 using Sigma = std::vector<unsigned>;
295 template<typename T, std::enable_if_t<std::is_convertible<T, unsigned>::value,
int>* =
nullptr>
296 explicit Permutation(std::initializer_list<T> vs) {
297 sigma.reserve(vs.size());
305 std::vector<std::size_t> factorials(N);
306 factorials.at(0) = 1;
307 for(std::size_t k = 1; k < N; ++k) {
308 factorials.at(k) = factorials.at(k - 1) * k;
311 for(std::size_t k = 0; k < N; ++k) {
312 const std::size_t fac = factorials.at(N - 1 - k);
313 sigma.at(k) = i / fac;
317 for(
int k = static_cast<int>(N) - 1; k > 0; --k) {
318 for(
int j = k - 1; j >= 0; --j) {
330 for(
unsigned i = 0; i < N; ++i) {
337 template<
typename Container>
340 std::is_convertible<Traits::getValueType<Container>,
unsigned>::value,
341 "Value type of container must be convertible to unsigned!"
345 sigma.emplace_back(static_cast<unsigned>(v));
350 template<
typename Container>
356 template<
typename OtherContainer>
362 [&](
const auto i,
const auto j) {
363 return unordered.at(i) < unordered.at(j);
377 unsigned index()
const {
381 unsigned indexOf(
unsigned v)
const {
382 const auto begin = std::begin(
sigma);
383 const auto end = std::end(
sigma);
384 const auto findIter =
std::find(begin, end, v);
386 if(findIter == end) {
387 throw std::out_of_range(
"Item not found");
390 return findIter - begin;
393 Permutation inverse()
const {
394 const unsigned size =
sigma.size();
397 for(
unsigned i = 0; i < size; ++i) {
398 inv.at(
sigma.at(i)) = i;
400 return Permutation {inv};
403 auto at(
const unsigned i)
const -> decltype(
auto) {
407 auto operator() (
const unsigned i)
const -> decltype(
auto) {
419 unsigned size()
const {
430 template<
typename OtherContainer>
431 OtherContainer apply(
const OtherContainer& other)
const {
432 const unsigned otherSize = other.size();
433 if(otherSize > size()) {
434 throw std::invalid_argument(
"Container of elements to apply permutation to larger than permutation itself");
436 OtherContainer result(otherSize);
437 for(
unsigned i = 0; i < otherSize; ++i) {
438 result.at(
sigma.at(i)) = other.at(i);
449 if(size() != other.size()) {
450 throw std::invalid_argument(
"Mismatched permutation sizes!");
456 return std::tie(
sigma);
void sort(Container &container)
Calls std::sort on a container.
Definition: Functional.h:261
bool next_permutation(Container &container)
Calls std::next_permutation.
Definition: Permutations.h:207
static Permutation ordering(const OtherContainer &unordered)
Discover on ordering permutation of an unordered container.
Definition: Permutations.h:357
Container-abstracted permutation.
Definition: Permutations.h:287
bool nextCombinationPermutation(Container &toPermute, const Container &limits)
For when you have to implement variable-depth for loops, each with different limits.
Definition: Permutations.h:239
Generates all operators using a method returning a tuple.
Definition: OperatorSuppliers.h:78
Operator-supplying CRTP base classes.
static std::enable_if_t<!std::is_same< Container, Sigma >::value, Permutation > from(const Container &p)
Construct a permutation from data (unchecked!)
Definition: Permutations.h:338
constexpr std::size_t permutationIndex(const Container &container)
Calculate the index of permutation of elements in a container.
Definition: Permutations.h:30
constexpr void inPlaceReverse(Container &data, const std::size_t indexFrom, const std::size_t indexTo)
Index-based in-place reversal of elements in an array-like container.
Definition: Permutations.h:74
Sigma sigma
The permutation in 'one-line' representation.
Definition: Permutations.h:460
Permutation compose(const Permutation &other) const
Compose two permutations.
Definition: Permutations.h:448
bool prev_permutation(Container &container)
Calls std::prev_permutation.
Definition: Permutations.h:216
static Permutation identity(unsigned N)
Construct the identity permutation of size N.
Definition: Permutations.h:327
constexpr bool inPlaceNextPermutation(Container &data, const std::size_t first, const std::size_t last)
In-place next permutation.
Definition: Permutations.h:95
Provides a few basic function and container traits.
constexpr void inPlaceSwap(Container &data, const std::size_t a, const std::size_t b)
Index-based in-place swapping of elements in an array-like container.
Definition: Permutations.h:59
constexpr Get< 0 > first
Calls std::get<0> on any argument it is invoked with.
Definition: Functor.h:123
constexpr bool inPlacePreviousPermutation(Container &data, const std::size_t first, const std::size_t last)
In-place previous permutation.
Definition: Permutations.h:154
Permutation(const std::size_t N, std::size_t i)
Construct the i-th permutation of size N.
Definition: Permutations.h:304
auto find(const Container &container, const T &needle)
std::find shorthand
Definition: Functional.h:346