From 9bee197bd8c0224ae5b6efb2745af0baf940ed8d Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Wed, 6 Jul 2016 11:42:18 +0300 Subject: [PATCH 1/7] Added all files to the new repository --- doc/algorithm.qbk | 1 + doc/is_palindrome.qbk | 84 +++++++++++++++++ example/Jamfile.v2 | 2 + example/is_palindrome_example.cpp | 94 +++++++++++++++++++ include/boost/algorithm/is_palindrome.hpp | 107 ++++++++++++++++++++++ test/Jamfile.v2 | 2 + test/is_palindrome_test.cpp | 66 +++++++++++++ 7 files changed, 356 insertions(+) create mode 100644 doc/is_palindrome.qbk create mode 100644 example/is_palindrome_example.cpp create mode 100644 include/boost/algorithm/is_palindrome.hpp create mode 100644 test/is_palindrome_test.cpp diff --git a/doc/algorithm.qbk b/doc/algorithm.qbk index 66971d1..1568fb5 100644 --- a/doc/algorithm.qbk +++ b/doc/algorithm.qbk @@ -66,6 +66,7 @@ Thanks to all the people who have reviewed this library and made suggestions for [include clamp-hpp.qbk] [include gather.qbk] [include hex.qbk] +[include is_palindrome.qbk] [endsect] diff --git a/doc/is_palindrome.qbk b/doc/is_palindrome.qbk new file mode 100644 index 0000000..d1477a2 --- /dev/null +++ b/doc/is_palindrome.qbk @@ -0,0 +1,84 @@ +[/ File is_palindrome.qbk] + +[section:is_palindrome is_palindrome] + +[/license +Copyright (c) 2016 Alexander Zaitsev + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +] + +The header file 'is_palindrome.hpp' contains four variants of a single algorithm, is_palindrome. +The algorithm tests the sequence and returns true if the sequence is a palindrome; i.e, it is identical when traversed either backwards or frontwards. + +The routine `is_palindrome` takes a sequence and, optionally, a predicate. It will return true if the predicate returns true for tested elements by algorithm in the sequence. + +The routine come in 4 forms; the first one takes two iterators to define the range. The second form takes two iterators to define the range and a predicate. +The third form takes a single range parameter, and uses Boost.Range to traverse it. And the fourth form takes a single range parameter ( uses Boost.Range to traverse it) and a predicate. + + +[heading interface] + +The function `is_palindrome` returns true if the predicate returns true any tested by algorithm items in the sequence. +There are four versions: +1) takes two iterators. +2) takes two iterators and a predicate. +3) takes a range. +4) takes a range and a predicate. + +`` +template + bool is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end ); +template + bool is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end, Predicate p ); +template + bool is_palindrome ( const Range &r ); +template + bool is_palindrome ( const Range &r, Predicate p ); +`` + + +[heading Examples] + +Given the containers: +const std::list empty, +const std::vector singleElement{'z'}, +int oddNonPalindrome[] = {3,2,2}, +const int evenPalindrome[] = {1,2,2,1}, then +`` + +is_palindrome(empty)) --> true //empty range +is_palindrome(singleElement)) --> true +is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome))) --> false +is_palindrome(std::begin(evenPalindrome), std::end(evenPalindrome))) --> true +is_palindrome(empty.begin(), empty.end(), functorComparator())) --> true //empty range +is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome), funcComparator)) --> false +is_palindrome(evenPalindrome, std::equal_to())) --> true +`` + +[heading Iterator Requirements] + +`is_palindrome` work on Bidirectional and RandomAccess iterators. + +[heading Complexity] + +All of the variants of `is_palindrome` run in ['O(N)] (linear) time; that is, they compare against each element in the list once. If any of the comparisons not succeed, the algorithm will terminate immediately, without examining the remaining members of the sequence. + +[heading Exception Safety] + +All of the variants of `is_palindrome` take their parameters by value or const reference, and do not depend upon any global state. Therefore, all the routines in this file provide the strong exception guarantee. + +[heading Notes] + +* `is_palindrome` returns true for empty ranges and for single element ranges. + +* If you use version of 'is_palindrome' without custom predicate, 'is_palindrome' uses default 'operator==' for elements. If you want use custom predicate, you must redefine 'operator=='. + +[endsect] + +[/ File is_palindrome.qbk +Copyright 2016 Alexander Zaitsev +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). +] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 1d8e3b5..ce067cf 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -20,3 +20,5 @@ project /boost/algorithm/example exe clamp_example : clamp_example.cpp ; exe search_example : search_example.cpp ; +exe is_palindrome_example : is_palindrome_example.cpp; + diff --git a/example/is_palindrome_example.cpp b/example/is_palindrome_example.cpp new file mode 100644 index 0000000..e995a9e --- /dev/null +++ b/example/is_palindrome_example.cpp @@ -0,0 +1,94 @@ +/* + Copyright (c) Alexander Zaitsev , 2016 + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include +#include +#include + +#include + + +namespace ba = boost::algorithm; + +template +bool funcComparator(const T& v1, const T& v2) +{ + return v1 == v2; +} + +struct functorComparator +{ + template + bool operator()(const T& v1, const T& v2) const + { + return v1 == v2; + } +}; + + +int main ( int /*argc*/, char * /*argv*/ [] ) +{ + //You can this algorithm with iterators(minimum Bidirectional) + std::vector vec{1,2,1}; + if(ba::is_palindrome(vec.begin(), vec.end())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //Of course, you can use const iterators + if(ba::is_palindrome(vec.cbegin(), vec.cend())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //Example with bidirectional iterators + std::list list{1,2,1}; + if(ba::is_palindrome(list.begin(), list.end())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //You can use custom comparators like functions, functors, lambdas + auto lambdaComparator = [](int v1, int v2){ return v1 == v2; }; + auto objFunc = std::function(lambdaComparator); + + if(ba::is_palindrome(vec.begin(), vec.end(), lambdaComparator)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + if(ba::is_palindrome(vec.begin(), vec.end(), funcComparator)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + if(ba::is_palindrome(vec.begin(), vec.end(), functorComparator())) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + if(ba::is_palindrome(vec.begin(), vec.end(), objFunc)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + + //You can use ranges + if(ba::is_palindrome(vec)) + std::cout << "This container is palindrome" << std::endl; + else + std::cout << "This container is not palindrome" << std::endl; + + return 0; +} diff --git a/include/boost/algorithm/is_palindrome.hpp b/include/boost/algorithm/is_palindrome.hpp new file mode 100644 index 0000000..38029bb --- /dev/null +++ b/include/boost/algorithm/is_palindrome.hpp @@ -0,0 +1,107 @@ +/* + Copyright (c) Alexander Zaitsev , 2016 + + Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) + + See http://www.boost.org/ for latest version. +*/ + +/// \file is_palindrome.hpp +/// \brief Checks the input sequence on palindrome. +/// \author Alexander Zaitsev + +#ifndef BOOST_ALGORITHM_is_palindrome_HPP +#define BOOST_ALGORITHM_is_palindrome_HPP + +#include + +#include +#include + +namespace boost { namespace algorithm { + +/// \fn is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end, Predicate p ) +/// \return true if the entire sequence is palindrome +/// +/// \param begin The start of the input sequence +/// \param end One past the end of the input sequence +/// \param p A predicate used to compare the values. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end, Predicate p) +{ + if(begin == end) + { + return true; + } + + --end; + while(begin != end) + { + if(!p(*begin, *end)) + { + return false; + } + ++begin; + if(begin == end) + { + break; + } + --end; + } + return true; +} + +/// \fn is_palindrome ( BidirectionalIterator begin, BidirectionalIterator end ) +/// \return true if the entire sequence is palindrome +/// +/// \param begin The start of the input sequence +/// \param end One past the end of the input sequence +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(BidirectionalIterator begin, BidirectionalIterator end) +{ + return is_palindrome(begin, end, + std::equal_to::value_type> ()); +} + +/// \fn is_palindrome ( const R& range ) +/// \return true if the entire sequence is palindrome +/// +/// \param range The range to be tested. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(const R& range) +{ + return is_palindrome(boost::begin(range), boost::end(range)); +} + +/// \fn is_palindrome ( const R& range, Predicate p ) +/// \return true if the entire sequence is palindrome +/// +/// \param range The range to be tested. +/// \param p A predicate used to compare the values. +/// +/// \note This function will return true for empty sequences and for palindromes. +/// For other sequences function will return false. +/// Complexity: O(N). +template +bool is_palindrome(const R& range, Predicate p) +{ + return is_palindrome(boost::begin(range), boost::end(range), p); +} + +}} + +#endif // BOOST_ALGORITHM_is_palindrome_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index dd18ef8..fb00843 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -68,6 +68,8 @@ alias unit_test_framework [ run sort_subrange_test.cpp unit_test_framework : : : : sort_subrange_test ] [ run partition_subrange_test.cpp unit_test_framework : : : : partition_subrange_test ] +# Is_palindrome tests + [ run is_palindrome_test.cpp unit_test_framework : : : : is_palindrome_test ] ; } diff --git a/test/is_palindrome_test.cpp b/test/is_palindrome_test.cpp new file mode 100644 index 0000000..673e95b --- /dev/null +++ b/test/is_palindrome_test.cpp @@ -0,0 +1,66 @@ +/* + Copyright (c) Alexander Zaitsev , 2016 + + Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) + + See http://www.boost.org/ for latest version. +*/ + +#include +#include +#include +#include + +#include +#include + +namespace ba = boost::algorithm; + + +template +bool funcComparator(const T& v1, const T& v2) +{ + return v1 == v2; +} + +struct functorComparator +{ + template + bool operator()(const T& v1, const T& v2) const + { + return v1 == v2; + } +}; + + +static void test_is_palindrome() +{ + const std::list empty; + const std::vector singleElement{'z'}; + int oddNonPalindrome[] = {3,2,2}; + const int evenPalindrome[] = {1,2,2,1}; + + // Test a default operator== + BOOST_CHECK ( ba::is_palindrome(empty)); + BOOST_CHECK ( ba::is_palindrome(singleElement)); + BOOST_CHECK (!ba::is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome))); + BOOST_CHECK ( ba::is_palindrome(std::begin(evenPalindrome), std::end(evenPalindrome))); + + //Test the custom comparators + BOOST_CHECK ( ba::is_palindrome(empty.begin(), empty.end(), functorComparator())); + BOOST_CHECK (!ba::is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome), funcComparator)); + BOOST_CHECK ( ba::is_palindrome(evenPalindrome, std::equal_to())); + + //Only C++14 or newer + //auto lambdaComparator = [](const auto& v1, const auto& v2){ return v1 == v2; }; + //BOOST_CHECK ( ba::is_palindrome(singleElement, lambdaComparator)); +} + +int test_main( int, char * [] ) +{ + test_is_palindrome(); + + return 0; +} From 1ec1cd304553567a9653c9662e325e9a029e86e4 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Wed, 6 Jul 2016 11:57:05 +0300 Subject: [PATCH 2/7] Fixed is_palindrome_test --- test/is_palindrome_test.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/is_palindrome_test.cpp b/test/is_palindrome_test.cpp index 673e95b..ed7b1c4 100644 --- a/test/is_palindrome_test.cpp +++ b/test/is_palindrome_test.cpp @@ -8,13 +8,17 @@ See http://www.boost.org/ for latest version. */ +#include +#include + +#define BOOST_TEST_MAIN +#include + #include #include #include #include -#include -#include namespace ba = boost::algorithm; @@ -35,7 +39,7 @@ struct functorComparator }; -static void test_is_palindrome() +void test_is_palindrome() { const std::list empty; const std::vector singleElement{'z'}; @@ -58,9 +62,7 @@ static void test_is_palindrome() //BOOST_CHECK ( ba::is_palindrome(singleElement, lambdaComparator)); } -int test_main( int, char * [] ) +BOOST_AUTO_TEST_CASE( test_main ) { - test_is_palindrome(); - - return 0; + test_is_palindrome (); } From 366274ff0a196ddbab67d5e2b831dac8434a0988 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 6 Jul 2016 22:56:02 +0300 Subject: [PATCH 3/7] Added new tests to is_palindrome_test Added evenNonPalindrome and oddPalindrome tests. --- test/is_palindrome_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/is_palindrome_test.cpp b/test/is_palindrome_test.cpp index ed7b1c4..b9279c9 100644 --- a/test/is_palindrome_test.cpp +++ b/test/is_palindrome_test.cpp @@ -44,22 +44,22 @@ void test_is_palindrome() const std::list empty; const std::vector singleElement{'z'}; int oddNonPalindrome[] = {3,2,2}; + const int oddPalindrome[] = {1,2,3,2,1}; const int evenPalindrome[] = {1,2,2,1}; + int evenNonPalindrome[] = {1,4,8,8}; // Test a default operator== BOOST_CHECK ( ba::is_palindrome(empty)); BOOST_CHECK ( ba::is_palindrome(singleElement)); BOOST_CHECK (!ba::is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome))); + BOOST_CHECK ( ba::is_palindrome(std::begin(oddPalindrome), std::end(oddPalindrome))); BOOST_CHECK ( ba::is_palindrome(std::begin(evenPalindrome), std::end(evenPalindrome))); + BOOST_CHECK (!ba::is_palindrome(std::begin(evenNonPalindrome), std::end(evenNonPalindrome))); //Test the custom comparators BOOST_CHECK ( ba::is_palindrome(empty.begin(), empty.end(), functorComparator())); BOOST_CHECK (!ba::is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome), funcComparator)); BOOST_CHECK ( ba::is_palindrome(evenPalindrome, std::equal_to())); - - //Only C++14 or newer - //auto lambdaComparator = [](const auto& v1, const auto& v2){ return v1 == v2; }; - //BOOST_CHECK ( ba::is_palindrome(singleElement, lambdaComparator)); } BOOST_AUTO_TEST_CASE( test_main ) From fb964d72d7933b4d7cbb9021625a3907edc81b3d Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 6 Jul 2016 23:00:55 +0300 Subject: [PATCH 4/7] Updated documentation for is_palindrome Added two lines with examples. --- doc/is_palindrome.qbk | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/is_palindrome.qbk b/doc/is_palindrome.qbk index d1477a2..928de6f 100644 --- a/doc/is_palindrome.qbk +++ b/doc/is_palindrome.qbk @@ -45,7 +45,9 @@ Given the containers: const std::list empty, const std::vector singleElement{'z'}, int oddNonPalindrome[] = {3,2,2}, -const int evenPalindrome[] = {1,2,2,1}, then +const int oddPalindrome[] = {1,2,3,2,1}, +const int evenPalindrome[] = {1,2,2,1}, +int evenNonPalindrome[] = {1,4,8,8}, then `` is_palindrome(empty)) --> true //empty range @@ -54,7 +56,9 @@ is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome))) --> fal is_palindrome(std::begin(evenPalindrome), std::end(evenPalindrome))) --> true is_palindrome(empty.begin(), empty.end(), functorComparator())) --> true //empty range is_palindrome(std::begin(oddNonPalindrome), std::end(oddNonPalindrome), funcComparator)) --> false -is_palindrome(evenPalindrome, std::equal_to())) --> true +is_palindrome(std::begin(oddPalindrome), std::end(oddPalindrome)) --> true +is_palindrome(evenPalindrome, std::equal_to())) --> true +is_palindrome(std::begin(evenNonPalindrome), std::end(evenNonPalindrome)) --> false `` [heading Iterator Requirements] From 52f91139afe8c24be08d221c1bc4555a86cbecef Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Sun, 10 Jul 2016 22:52:55 +0300 Subject: [PATCH 5/7] Fix comments --- include/boost/algorithm/is_palindrome.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/algorithm/is_palindrome.hpp b/include/boost/algorithm/is_palindrome.hpp index 38029bb..61acbae 100644 --- a/include/boost/algorithm/is_palindrome.hpp +++ b/include/boost/algorithm/is_palindrome.hpp @@ -12,8 +12,8 @@ /// \brief Checks the input sequence on palindrome. /// \author Alexander Zaitsev -#ifndef BOOST_ALGORITHM_is_palindrome_HPP -#define BOOST_ALGORITHM_is_palindrome_HPP +#ifndef BOOST_ALGORITHM_IS_PALINDROME_HPP +#define BOOST_ALGORITHM_IS_PALINDROME_HPP #include @@ -104,4 +104,4 @@ bool is_palindrome(const R& range, Predicate p) }} -#endif // BOOST_ALGORITHM_is_palindrome_HPP +#endif // BOOST_ALGORITHM_IS_PALINDROME_HPP From 093900a8f3d2608ff28ba009f16e9c3c689640e8 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 11 Jul 2016 18:25:04 +0300 Subject: [PATCH 6/7] [micro] Replaced constructor of singleElement Replaced bracket initializes constructor to simply constructor with two arguments in std::vector --- test/is_palindrome_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/is_palindrome_test.cpp b/test/is_palindrome_test.cpp index b9279c9..2c0f67a 100644 --- a/test/is_palindrome_test.cpp +++ b/test/is_palindrome_test.cpp @@ -42,7 +42,7 @@ struct functorComparator void test_is_palindrome() { const std::list empty; - const std::vector singleElement{'z'}; + const std::vector singleElement(1, 'z'); int oddNonPalindrome[] = {3,2,2}; const int oddPalindrome[] = {1,2,3,2,1}; const int evenPalindrome[] = {1,2,2,1}; From 1a34a6935b7694178631d0b06d7bfeedf6f89d61 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 11 Jul 2016 18:26:18 +0300 Subject: [PATCH 7/7] [micro] Added "#include " --- include/boost/algorithm/is_palindrome.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/algorithm/is_palindrome.hpp b/include/boost/algorithm/is_palindrome.hpp index 61acbae..e15e77a 100644 --- a/include/boost/algorithm/is_palindrome.hpp +++ b/include/boost/algorithm/is_palindrome.hpp @@ -16,6 +16,7 @@ #define BOOST_ALGORITHM_IS_PALINDROME_HPP #include +#include #include #include