示例 C++ 解决方案:
#include <algorithm>
#include <iterator>
#include <iostream>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/lexical_cast.hpp>
namespace {
bool is_palindrome(unsigned int i) {
const std::string& s = boost::lexical_cast<std::string>(i);
return std::equal(s.begin(), s.end(), s.rbegin());
}
const unsigned int stop = 1000000;
}
int main() {
std::remove_copy_if(boost::counting_iterator<unsigned int>(1),
boost::counting_iterator<unsigned int>(stop),
std::ostream_iterator<unsigned int>(std::cout, "\n"),
std::not1(std::ptr_fun(is_palindrome)));
}
(我用std::remove_copy_if来弥补C++0x中std::copy_if的不足)
为了完整起见,我实现了一个生成回文的版本,而不是针对谓词测试候选者:
#include <boost/lexical_cast.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cassert>
namespace {
template <int ver>
unsigned int make_palindrome(unsigned int i) {
std::string s = boost::lexical_cast<std::string>(i);
assert(s.size());
s.reserve(s.size()*2);
std::reverse_copy(s.begin(), s.end()-ver, std::back_inserter(s));
return boost::lexical_cast<unsigned int>(s);
}
}
int main() {
typedef boost::counting_iterator<unsigned int> counter;
std::merge(boost::make_transform_iterator(counter(1), make_palindrome<1>),
boost::make_transform_iterator(counter(999), make_palindrome<1>),
boost::make_transform_iterator(counter(1), make_palindrome<0>),
boost::make_transform_iterator(counter(999), make_palindrome<0>),
std::ostream_iterator<unsigned int>(std::cout, "\n"));
}
(我认为我可以使用 boost.range 而不是 std::merge)
我想讨论的重点是“这是一种更好的*方式来编写它吗?”。我喜欢以这种风格编写诸如回文之类的问题的一点是,您会得到“如果它编译它可能是正确的”启发式。即使存在错误,它仍然会在运行时得到合理处理(例如来自lexical_cast 的异常)。
这是一种与 C 编程明显不同的思维方式(但在某些方面与 Haskell 奇怪地相似)。它带来了许多额外安全方面的好处,但编译器错误消息可能很糟糕,并且很难改变您对问题的看法。
归根结底,重要的是“工作量越少,错误越少?”。如果没有一些指标提供帮助,我无法回答这个问题。
*对于更好的一些定义。