Iros
Loading...
Searching...
No Matches
next_permutation.h
Go to the documentation of this file.
1
#pragma once
2
3
#include "
di/container/algorithm/in_found_result.h
"
4
#include "
di/container/algorithm/reverse.h
"
5
#include "
di/container/concepts/prelude.h
"
6
#include "
di/container/iterator/prelude.h
"
7
#include "
di/container/meta/prelude.h
"
8
#include "
di/function/compare.h
"
9
10
namespace
di::container
{
11
namespace
detail
{
12
struct
NextPermutationFunction
{
13
template
<concepts::B
id
irectionalIterator It, concepts::SentinelFor<It> Sent,
typename
Comp = function::Compare,
14
typename
Proj = function::Identity>
15
requires
(
concepts::Sortable<It, Comp, Proj>
)
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
65
->
InFoundResult
<
meta::BorrowedIterator<Con>
> {
66
return
(*
this
)(
container::begin
(
container
),
container::end
(
container
),
util::ref
(comp),
util::ref
(
proj
));
67
}
68
};
69
}
70
71
constexpr
inline
auto
next_permutation
=
detail::NextPermutationFunction
{};
72
}
73
74
namespace
di
{
75
using
container::next_permutation
;
76
}
reverse.h
di::concepts::Sortable
Definition
sortable.h:11
compare.h
in_found_result.h
prelude.h
prelude.h
prelude.h
di::container::detail
Definition
sequence.h:13
di::container
Definition
sequence.h:12
di::container::prev
constexpr auto prev
Definition
prev.h:28
di::container::next
constexpr auto next
Definition
next.h:35
di::container::reverse
constexpr auto reverse
Definition
reverse.h:28
di::container::next_permutation
constexpr auto next_permutation
Definition
next_permutation.h:71
di::container::iterator_swap
constexpr auto iterator_swap
Definition
iterator_swap.h:49
di::container::end
constexpr auto end
Definition
end.h:47
di::container::begin
constexpr auto begin
Definition
begin.h:44
di::function::invoke
constexpr auto invoke
Definition
invoke.h:100
di::meta::BorrowedIterator
Conditional< concepts::BorrowedContainer< Con >, ContainerIterator< Con >, container::Dangling > BorrowedIterator
Definition
borrowed_iterator.h:11
di::util::ref
constexpr auto ref
Definition
reference_wrapper.h:98
di
Definition
zstring_parser.h:9
di::proj
constexpr auto proj
Definition
proj.h:59
di::container::InFoundResult
Definition
in_found_result.h:8
di::container::detail::NextPermutationFunction
Definition
next_permutation.h:12
libs
di
include
di
container
algorithm
next_permutation.h
Generated by
1.13.0