Kojirion

Home Projects Links About RSS

Digits

Problems like those at Project Euler often involve the digits of a number. The solution will usually require something cleverer than iterating over them, however doing so may be the avenue to understanding the problem. It is a shame then that there is no simple way to do so in C++; it is possible to convert the number to a string with std::to_string, but then it is necessary to convert the characters to integers for arithmetic operations, getting in the way of STL algorithms. Clearly(!), it is needed to write an iterator:

#include <boost/iterator/iterator_facade.hpp>

class DigitIterator :
    public boost::iterator_facade<
        DigitIterator, //CRTP
        const int, //type iterated over
        boost::forward_traversal_tag //kind of traversal
        int //'reference'
    >
{
public:
    DigitIterator(int n = 0):
        value(n)
    { }
 
private:
    friend class boost::iterator_core_access;
 
    void increment() {
        value /= 10;
    }
 
    int dereference() const {
        return value % 10;
    }
 
    bool equal(const DigitIterator &other) const {
        return value == other.value;
    }
    
    int value;
};

A range can then be made out of a pair of these:

#include <boost/range/iterator_range.hpp>

auto digits_of(int n)
{
    return boost::make_iterator_range(DigitIterator(n), DigitIterator());
}

In C++14 it is not necessary to specify the function’s return type. Done! It is now possible to iterate over the digits with a range-based for, or STL/Boost algorithms:

int main(){
    int n = 1537;
    
    for (const auto digit : digits_of(n))
        cout << digit << '\n';
    
    cout << "Sum: " << accumulate(digits_of(n), 0) << '\n';    
}
7
3
5
1
Sum: 16