diff --git a/libs/algorithm/test/modifying.cpp b/libs/algorithm/test/modifying.cpp index 65b1f978..0716a198 100644 --- a/libs/algorithm/test/modifying.cpp +++ b/libs/algorithm/test/modifying.cpp @@ -50,6 +50,8 @@ #include "./make_heap.cpp" #include "./make_partial_heap.cpp" #include "./sort_heap.cpp" +#include "./next_permutation.cpp" +#include "./prev_permutation.cpp" #include "./swap_element.cpp" #include "./swap_element_copy.cpp" #include "./bogo_sort.cpp" @@ -105,6 +107,8 @@ namespace testspr { testspr::algorithm_make_heap_test(); testspr::algorithm_make_partial_heap_test(); testspr::algorithm_sort_heap_test(); + testspr::algorithm_next_permutation_test(); + testspr::algorithm_prev_permutation_test(); testspr::algorithm_swap_element_test(); testspr::algorithm_swap_element_copy_test(); testspr::algorithm_bogo_sort_test(); diff --git a/libs/algorithm/test/next_permutation.cpp b/libs/algorithm/test/next_permutation.cpp new file mode 100644 index 00000000..d9429a47 --- /dev/null +++ b/libs/algorithm/test/next_permutation.cpp @@ -0,0 +1,137 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_NEXT_PERMUTATION_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_NEXT_PERMUTATION_CPP + +#include +#include +#include +#include +#include + +namespace testspr { + static void algorithm_next_permutation_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5}}; + + // 順列 + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::next_permutation( + arr1 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{1, 2, 3, 5, 4}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::next_permutation( + arr1 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{1, 2, 3, 5, 4}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + // 順列 + // 範囲の切り出し + // !!! +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::next_permutation( +// sprout::sub(arr1, 2, 4) +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{2, 4, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{1, 2, 4, 3, 5}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::next_permutation( +// sprout::sub(arr1, 2, 4) +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{2, 4, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{1, 2, 4, 3, 5}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } + } + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{1, 2, 3, 4, 5}}; + + // 順列 + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::next_permutation( + arr1, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{1, 2, 3, 5, 4}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::next_permutation( + arr1, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{1, 2, 3, 5, 4}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + // 順列 + // 範囲の切り出し + // !!! +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::next_permutation( +// sprout::sub(arr1, 2, 4), +// testspr::less() +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{2, 4, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{1, 2, 4, 3, 5}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::next_permutation( +// sprout::sub(arr1, 2, 4), +// testspr::less() +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{2, 4, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{1, 2, 4, 3, 5}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_next_permutation_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_NEXT_PERMUTATION_CPP diff --git a/libs/algorithm/test/prev_permutation.cpp b/libs/algorithm/test/prev_permutation.cpp new file mode 100644 index 00000000..f6df03d6 --- /dev/null +++ b/libs/algorithm/test/prev_permutation.cpp @@ -0,0 +1,137 @@ +#ifndef SPROUT_LIBS_ALGORITHM_TEST_PREV_PERMUTATION_CPP +#define SPROUT_LIBS_ALGORITHM_TEST_PREV_PERMUTATION_CPP + +#include +#include +#include +#include +#include + +namespace testspr { + static void algorithm_prev_permutation_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{5, 4, 3, 2, 1}}; + + // 順列 + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::prev_permutation( + arr1 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{5, 4, 3, 1, 2}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::prev_permutation( + arr1 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{5, 4, 3, 1, 2}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + // 順列 + // 範囲の切り出し + // !!! +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::prev_permutation( +// sprout::sub(arr1, 2, 4) +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{4, 2, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{5, 4, 2, 3, 1}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::prev_permutation( +// sprout::sub(arr1, 2, 4) +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{4, 2, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{5, 4, 2, 3, 1}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } + } + { + SPROUT_STATIC_CONSTEXPR auto arr1 = array{{5, 4, 3, 2, 1}}; + + // 順列 + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::prev_permutation( + arr1, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{5, 4, 3, 1, 2}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + { + SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::prev_permutation( + arr1, + testspr::less() + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + permutation.first, + array{{5, 4, 3, 1, 2}} + )); + TESTSPR_BOTH_ASSERT(permutation.second); + } + // 順列 + // 範囲の切り出し + // !!! +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::prev_permutation( +// sprout::sub(arr1, 2, 4), +// testspr::less() +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{4, 2, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{5, 4, 2, 3, 1}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } +// { +// SPROUT_STATIC_CONSTEXPR auto permutation = sprout::fit::prev_permutation( +// sprout::sub(arr1, 2, 4), +// testspr::less() +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// permutation.first, +// array{{4, 2, 3}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(permutation.first), +// array{{5, 4, 2, 3, 1}} +// )); +// TESTSPR_BOTH_ASSERT(permutation.second); +// } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::algorithm_prev_permutation_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_ALGORITHM_TEST_PREV_PERMUTATION_CPP diff --git a/sprout/algorithm/fit.hpp b/sprout/algorithm/fit.hpp index e3721477..1e1d4750 100644 --- a/sprout/algorithm/fit.hpp +++ b/sprout/algorithm/fit.hpp @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/sprout/algorithm/fit/next_permutation.hpp b/sprout/algorithm/fit/next_permutation.hpp new file mode 100644 index 00000000..dc0bce38 --- /dev/null +++ b/sprout/algorithm/fit/next_permutation.hpp @@ -0,0 +1,82 @@ +#ifndef SPROUT_ALGORITHM_FIT_NEXT_PERMUTATION_HPP +#define SPROUT_ALGORITHM_FIT_NEXT_PERMUTATION_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace fit { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + next_permutation_impl_1( + Container const& cont, + Permutation const& perm, + typename sprout::container_traits::difference_type offset + ) + { + return sprout::pair::type, bool>( + sprout::sub_copy( + sprout::get_internal(perm.first), + offset, + offset + sprout::size(cont) + ), + perm.second + ); + } + + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + next_permutation_impl( + Container const& cont, + Compare comp, + typename sprout::container_traits::difference_type offset + ) + { + return next_permutation_impl_1(cont, sprout::fixed::next_permutation(cont, comp), offset); + } + } // namespace detail + // + // next_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + next_permutation( + Container const& cont, + Compare comp + ) + { + return sprout::fit::detail::next_permutation_impl(cont, comp, sprout::internal_begin_offset(cont)); + } + + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + next_permutation_impl( + Container const& cont, + typename sprout::container_traits::difference_type offset + ) + { + return next_permutation_impl_1(cont, sprout::fixed::next_permutation(cont), offset); + } + } // namespace detail + // + // next_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + next_permutation( + Container const& cont + ) + { + return sprout::fit::detail::next_permutation_impl(cont, sprout::internal_begin_offset(cont)); + } + } // namespace fit +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FIT_NEXT_PERMUTATION_HPP diff --git a/sprout/algorithm/fit/prev_permutation.hpp b/sprout/algorithm/fit/prev_permutation.hpp new file mode 100644 index 00000000..c73ba6dd --- /dev/null +++ b/sprout/algorithm/fit/prev_permutation.hpp @@ -0,0 +1,82 @@ +#ifndef SPROUT_ALGORITHM_FIT_PREV_PERMUTATION_HPP +#define SPROUT_ALGORITHM_FIT_PREV_PERMUTATION_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace fit { + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + prev_permutation_impl_1( + Container const& cont, + Permutation const& perm, + typename sprout::container_traits::difference_type offset + ) + { + return sprout::pair::type, bool>( + sprout::sub_copy( + sprout::get_internal(perm.first), + offset, + offset + sprout::size(cont) + ), + perm.second + ); + } + + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + prev_permutation_impl( + Container const& cont, + Compare comp, + typename sprout::container_traits::difference_type offset + ) + { + return prev_permutation_impl_1(cont, sprout::fixed::prev_permutation(cont, comp), offset); + } + } // namespace detail + // + // prev_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + prev_permutation( + Container const& cont, + Compare comp + ) + { + return sprout::fit::detail::prev_permutation_impl(cont, comp, sprout::internal_begin_offset(cont)); + } + + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + prev_permutation_impl( + Container const& cont, + typename sprout::container_traits::difference_type offset + ) + { + return prev_permutation_impl_1(cont, sprout::fixed::prev_permutation(cont), offset); + } + } // namespace detail + // + // prev_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + prev_permutation( + Container const& cont + ) + { + return sprout::fit::detail::prev_permutation_impl(cont, sprout::internal_begin_offset(cont)); + } + } // namespace fit +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FIT_PREV_PERMUTATION_HPP diff --git a/sprout/algorithm/fixed.hpp b/sprout/algorithm/fixed.hpp index 75554868..874ed13b 100644 --- a/sprout/algorithm/fixed.hpp +++ b/sprout/algorithm/fixed.hpp @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/sprout/algorithm/fixed/next_permutation.hpp b/sprout/algorithm/fixed/next_permutation.hpp new file mode 100644 index 00000000..212ed078 --- /dev/null +++ b/sprout/algorithm/fixed/next_permutation.hpp @@ -0,0 +1,103 @@ +#ifndef SPROUT_ALGORITHM_FIXED_NEXT_PERMUTATION_HPP +#define SPROUT_ALGORITHM_FIXED_NEXT_PERMUTATION_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT + +namespace sprout { + namespace fixed { + namespace detail { + template + inline SPROUT_CONSTEXPR Result + next_permutation_impl_4(Container const& cont, Difference d) { + return Result( + sprout::get_internal(sprout::fixed::reverse(sprout::sub_array(cont, d, sprout::size(cont)))), + true + ); + } + template + inline SPROUT_CONSTEXPR Result + next_permutation_impl_3(Container const& cont, Compare comp, Iterator first, Iterator last, Iterator i, Iterator ii, Iterator j) { + return !comp(*i, *sprout::prev(j)) ? sprout::fixed::detail::next_permutation_impl_3( + cont, comp, first, last, + i, ii, sprout::prev(j) + ) + : sprout::fixed::detail::next_permutation_impl_4( + sprout::fixed::swap_element(cont, i, sprout::prev(j)), + NS_SSCRISK_CEL_OR_SPROUT::distance(first, ii) + ) + ; + } + template + inline SPROUT_CONSTEXPR Result + next_permutation_impl_2(Container const& cont, Compare comp, Iterator first, Iterator last, Iterator i, Iterator ii) { + return comp(*i, *ii) ? sprout::fixed::detail::next_permutation_impl_3( + cont, comp, first, last, + i, ii, last + ) + : i == first ? Result(sprout::fixed::reverse_copy(first, last, cont), false) + : sprout::fixed::detail::next_permutation_impl_2( + cont, comp, first, last, + sprout::prev(i), i + ) + ; + } + template + inline SPROUT_CONSTEXPR Result + next_permutation_impl_1(Container const& cont, Compare comp, Iterator first, Iterator last, Iterator i) { + return i == last ? Result(sprout::deep_copy(cont), false) + : sprout::fixed::detail::next_permutation_impl_2( + cont, comp, first, last, + sprout::prev(last, 2), sprout::prev(last) + ) + ; + } + template + inline SPROUT_CONSTEXPR Result + next_permutation_impl(Container const& cont, Compare comp, Iterator first, Iterator last) { + return first == last ? Result(sprout::deep_copy(cont), false) + : sprout::fixed::detail::next_permutation_impl_1( + cont, comp, first, last, + sprout::next(first) + ); + } + } // namespace detail + // + // next_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + next_permutation(Container const& cont, Compare comp) { + typedef sprout::pair::type, bool> type; + return sprout::fixed::detail::next_permutation_impl( + cont, comp, + sprout::begin(cont), sprout::end(cont) + ); + } + // + // next_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + next_permutation(Container const& cont) { + typedef sprout::pair::type, bool> type; + return sprout::fixed::detail::next_permutation_impl( + cont, NS_SSCRISK_CEL_OR_SPROUT::less::value_type>(), + sprout::begin(cont), sprout::end(cont) + ); + } + } // namespace fixed + + using sprout::fixed::next_permutation; +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FIXED_NEXT_PERMUTATION_HPP diff --git a/sprout/algorithm/fixed/prev_permutation.hpp b/sprout/algorithm/fixed/prev_permutation.hpp new file mode 100644 index 00000000..a12ab8f8 --- /dev/null +++ b/sprout/algorithm/fixed/prev_permutation.hpp @@ -0,0 +1,103 @@ +#ifndef SPROUT_ALGORITHM_FIXED_PREV_PERMUTATION_HPP +#define SPROUT_ALGORITHM_FIXED_PREV_PERMUTATION_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT + +namespace sprout { + namespace fixed { + namespace detail { + template + inline SPROUT_CONSTEXPR Result + prev_permutation_impl_4(Container const& cont, Difference d) { + return Result( + sprout::get_internal(sprout::fixed::reverse(sprout::sub_array(cont, d, sprout::size(cont)))), + true + ); + } + template + inline SPROUT_CONSTEXPR Result + prev_permutation_impl_3(Container const& cont, Compare comp, Iterator first, Iterator last, Iterator i, Iterator ii, Iterator j) { + return !comp(*sprout::prev(j), *i) ? sprout::fixed::detail::prev_permutation_impl_3( + cont, comp, first, last, + i, ii, sprout::prev(j) + ) + : sprout::fixed::detail::prev_permutation_impl_4( + sprout::fixed::swap_element(cont, i, sprout::prev(j)), + NS_SSCRISK_CEL_OR_SPROUT::distance(first, ii) + ) + ; + } + template + inline SPROUT_CONSTEXPR Result + prev_permutation_impl_2(Container const& cont, Compare comp, Iterator first, Iterator last, Iterator i, Iterator ii) { + return comp(*ii, *i) ? sprout::fixed::detail::prev_permutation_impl_3( + cont, comp, first, last, + i, ii, last + ) + : i == first ? Result(sprout::fixed::reverse_copy(first, last, cont), false) + : sprout::fixed::detail::prev_permutation_impl_2( + cont, comp, first, last, + sprout::prev(i), i + ) + ; + } + template + inline SPROUT_CONSTEXPR Result + prev_permutation_impl_1(Container const& cont, Compare comp, Iterator first, Iterator last, Iterator i) { + return i == last ? Result(sprout::deep_copy(cont), false) + : sprout::fixed::detail::prev_permutation_impl_2( + cont, comp, first, last, + sprout::prev(last, 2), sprout::prev(last) + ) + ; + } + template + inline SPROUT_CONSTEXPR Result + prev_permutation_impl(Container const& cont, Compare comp, Iterator first, Iterator last) { + return first == last ? Result(sprout::deep_copy(cont), false) + : sprout::fixed::detail::prev_permutation_impl_1( + cont, comp, first, last, + sprout::next(first) + ); + } + } // namespace detail + // + // prev_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + prev_permutation(Container const& cont, Compare comp) { + typedef sprout::pair::type, bool> type; + return sprout::fixed::detail::prev_permutation_impl( + cont, comp, + sprout::begin(cont), sprout::end(cont) + ); + } + // + // prev_permutation + // + template + inline SPROUT_CONSTEXPR sprout::pair::type, bool> + prev_permutation(Container const& cont) { + typedef sprout::pair::type, bool> type; + return sprout::fixed::detail::prev_permutation_impl( + cont, NS_SSCRISK_CEL_OR_SPROUT::less::value_type>(), + sprout::begin(cont), sprout::end(cont) + ); + } + } // namespace fixed + + using sprout::fixed::prev_permutation; +} // namespace sprout + +#endif // #ifndef SPROUT_ALGORITHM_FIXED_PREV_PERMUTATION_HPP diff --git a/sprout/algorithm/next_permutation.hpp b/sprout/algorithm/next_permutation.hpp new file mode 100644 index 00000000..1de02067 --- /dev/null +++ b/sprout/algorithm/next_permutation.hpp @@ -0,0 +1,8 @@ +#ifndef SPROUT_ALGORITHM_NEXT_PERMUTATION_HPP +#define SPROUT_ALGORITHM_NEXT_PERMUTATION_HPP + +#include +#include +#include + +#endif // #ifndef SPROUT_ALGORITHM_NEXT_PERMUTATION_HPP diff --git a/sprout/algorithm/prev_permutation.hpp b/sprout/algorithm/prev_permutation.hpp new file mode 100644 index 00000000..2396e1a2 --- /dev/null +++ b/sprout/algorithm/prev_permutation.hpp @@ -0,0 +1,8 @@ +#ifndef SPROUT_ALGORITHM_PREV_PERMUTATION_HPP +#define SPROUT_ALGORITHM_PREV_PERMUTATION_HPP + +#include +#include +#include + +#endif // #ifndef SPROUT_ALGORITHM_PREV_PERMUTATION_HPP diff --git a/sprout/sub_array/sub.hpp b/sprout/sub_array/sub.hpp index a9441dfc..02f5338c 100644 --- a/sprout/sub_array/sub.hpp +++ b/sprout/sub_array/sub.hpp @@ -10,7 +10,6 @@ #include namespace sprout { - // // sub //