Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
template<typename IntT, size_t BASE>
class palindrome_iterator
{
static const size_t MAX_WIDTH = sizeof(IntT) * CHAR_BIT;
struct IncrementData
{
IncrementData()
: m_counter(BASE - 1)
, m_counterLimit(BASE - 1)
, m_increment(IntT(1))
{}
size_t m_counter; // current counter value
size_t m_counterLimit; // number of iterations, usually B, but B - 1 for last increment
IntT m_increment; // increment value
};
public:
palindrome_iterator()
: m_value(1)
, m_countersSize(1)
, m_basicIncrement(1)
, m_width(1)
{
m_powers[0] = IntT(1);
for (size_t i = 1; i < MAX_WIDTH / 2 + 1; ++i)
m_powers[i] = m_powers[i - 1] * IntT(BASE);
}
inline void operator ++()
{
// always increment basic
m_value += m_basicIncrement;
size_t i = 0;
do {
if (--m_counters[i].m_counter)
return;
// fix value on digit overflow
m_counters[i].m_counter = m_counters[i].m_counterLimit;
m_value += m_counters[i].m_increment;
} while (++i < m_countersSize);
// reset increments when new digit is added
IncWidth();
}
inline const IntT & operator *() const
{
return m_value;
}
private:
void IncWidth()
{
++m_width;
if (m_width & 1) {
m_counters[m_countersSize - 1].m_counter = m_counters[m_countersSize - 1].m_counterLimit = BASE;
++m_countersSize;
}
if (m_width & 1) {
m_basicIncrement = m_powers[m_countersSize - 1]; // 100...
m_counters[0].m_increment = m_powers[m_countersSize - 2];
}
else {
m_basicIncrement = m_powers[m_countersSize - 1] + m_powers[m_countersSize]; // 110...
m_counters[0].m_increment = m_powers[m_countersSize - 2] - m_powers[m_countersSize];
}
for (size_t i = 1; i < m_countersSize - 1; ++i)
m_counters[i].m_increment = m_powers[m_countersSize - i - 2] - m_powers[m_countersSize - i];
m_counters[m_countersSize - 1].m_increment = m_powers[0] - m_powers[1];
}
IntT m_value; // current value
IntT m_basicIncrement; // basic increment (100... for odd width, 1100... for even width
size_t m_countersSize; // just greater half of width: (width + 1) / 2
IncrementData m_counters[MAX_WIDTH];
IntT m_powers[MAX_WIDTH / 2 + 1]; // 1, B, B^2, B^3, ... sequence
size_t m_width; // current width = number of digits
};
template<typename IntT, size_t B>
class palindrome_iterator
{
static const size_t MAX_W = sizeof(IntT) * 8;
struct IncrementData
{
size_t m_counter; // current counter value
size_t m_counterLimit; // number of iterations, usually B, but B - 1 for last increment
IntT m_increment; // increment value
};
public:
palindrome_iterator()
: m_value(1)
, m_countersSize(1)
, m_basicIncrement(1)
, m_width(1)
{
m_powers[0] = 1;
for (size_t i = 1; i < MAX_W; ++i)
m_powers[i] = m_powers[i - 1] * (IntT)B;
for (size_t i = 0; i < MAX_W; ++i) {
m_counters[i].m_counter = m_counters[i].m_counterLimit = B - 1;
}
m_counters[0].m_increment = 1;
}
inline void operator ++()
{
// always increment basic
m_value += m_basicIncrement;
size_t i = 0;
do {
if (--m_counters[i].m_counter)
return;
// fix value on digit overflow
m_counters[i].m_counter = m_counters[i].m_counterLimit;
m_value += m_counters[i].m_increment;
} while (++i < m_countersSize);
// reset increments when new digit is added
IncWidth();
}
inline const IntT & operator *() const
{
return m_value;
}
private:
void IncWidth()
{
++m_width;
if (m_width & 1) {
m_counters[m_countersSize - 1].m_counter = m_counters[m_countersSize - 1].m_counterLimit = B;
++m_countersSize;
}
if (m_width & 1) {
m_basicIncrement = m_powers[m_countersSize - 1]; // 100...
m_counters[0].m_increment = m_powers[m_countersSize - 2];
}
else {
m_basicIncrement = m_powers[m_countersSize - 1] + m_powers[m_countersSize];
m_counters[0].m_increment = m_powers[m_countersSize - 2] - m_powers[m_countersSize];
}
for (size_t i = 1; i < m_countersSize - 1; ++i) {
m_counters[i].m_increment = m_powers[m_countersSize - i - 2] - m_powers[m_countersSize - i]; // 110...
}
m_counters[m_countersSize - 1].m_increment = m_powers[0] - m_powers[1];
}
IntT m_value; // current value
IntT m_basicIncrement; // basic increment (100... for odd width, 1100... for even width
size_t m_countersSize; // just greater half of width (width + 1 / 2)
IncrementData m_counters[MAX_W];
IntT m_powers[MAX_W]; // 1, B, B^2, B^3, ... sequence
size_t m_width; // current width = number of digits
};
Вперед, на поиски палиндромов