Iros
 
Loading...
Searching...
No Matches
next_permutation.h
Go to the documentation of this file.
1#pragma once
2
9
10namespace di::container {
11namespace detail {
13 template<concepts::BidirectionalIterator It, concepts::SentinelFor<It> Sent, typename Comp = function::Compare,
14 typename Proj = function::Identity>
16 constexpr auto operator()(It first, Sent last, Comp comp = {}, Proj proj = {}) const -> InFoundResult<It> {
17 // If there are 0 or 1 elements, just return without doing anything.
18 if (first == last) {
19 return { util::move(first), false };
20 }
21 auto last_it = container::next(first, last);
22 auto it = container::prev(last_it);
23 if (first == it) {
24 return { util::move(last_it), false };
25 }
26
27 // Get to the next permutation.
28 for (;;) {
29 auto current = it;
30 if (function::invoke(comp, function::invoke(proj, *--it), function::invoke(proj, *current)) < 0) {
31 // The previous element (note it was decremented) is less than the current. Since this check is in a
32 // loop, it means that the range [it, last_it) is sorted in reverse order. Our goal in next
33 // permutation is to permuate the range such that the range is the lexicographic successor.
34
35 // Find the insertion point for *it, which will be the last element which will be
36 // the first element is is less than. Since this range is sorted, this is operation
37 // should binary search instead of a linear scan (assuming the range is large).
38 auto insertion_point = last_it;
39 while (function::invoke(comp, function::invoke(proj, *it),
40 function::invoke(proj, *--insertion_point)) >= 0) {}
41
42 // Swap it with the insertion point, which now means that [current, last_it)
43 // is still sorted in reverse order.
44 container::iterator_swap(it, insertion_point);
45
46 // Since we've generated the next permutation, reverse the range [current, last_it]
47 // so it is not sorted properly.
48 container::reverse(current, last_it);
49 return { util::move(last_it), true };
50 }
51
52 if (it == first) {
53 // The range is sorted in reverse order, so there are no more permutations.
54 // Reverse the range to get back to a sorted range, and return false.
55 container::reverse(first, last_it);
56 return { util::move(last_it), false };
57 }
58 }
59 }
60
61 template<concepts::BidirectionalContainer Con, typename Comp = function::Compare,
62 typename Proj = function::Identity>
63 requires(concepts::Sortable<meta::ContainerIterator<Con>, Comp, Proj>)
64 constexpr auto operator()(Con&& container, Comp comp = {}, Proj proj = {}) const
67 }
68 };
69}
70
72}
73
74namespace di {
76}
Definition sortable.h:11
Definition sequence.h:13
Definition sequence.h:12
constexpr auto prev
Definition prev.h:28
constexpr auto next
Definition next.h:35
constexpr auto reverse
Definition reverse.h:28
constexpr auto next_permutation
Definition next_permutation.h:71
constexpr auto iterator_swap
Definition iterator_swap.h:49
constexpr auto end
Definition end.h:47
constexpr auto begin
Definition begin.h:44
constexpr auto invoke
Definition invoke.h:100
Conditional< concepts::BorrowedContainer< Con >, ContainerIterator< Con >, container::Dangling > BorrowedIterator
Definition borrowed_iterator.h:11
constexpr auto ref
Definition reference_wrapper.h:98
Definition zstring_parser.h:9
constexpr auto proj
Definition proj.h:59
Definition in_found_result.h:8
Definition next_permutation.h:12