Skip to content

Instantly share code, notes, and snippets.

@SaitoAtsushi
Created November 4, 2017 09:33
Show Gist options
  • Save SaitoAtsushi/4a53fac3aba03d0dad839eacb2291b9f to your computer and use it in GitHub Desktop.
Save SaitoAtsushi/4a53fac3aba03d0dad839eacb2291b9f to your computer and use it in GitHub Desktop.
#include <iostream>
#include <cstdint>
class digit_t {
friend std::istream& operator>>(std::istream&, digit_t&);
friend std::ostream& operator<<(std::ostream&, digit_t&);
private:
using value_type = uint_least64_t;
value_type data;
unsigned int check_digit;
unsigned int make_check_digit(value_type digit);
public:
digit_t(value_type data);
digit_t(void);
digit_t& operator=(value_type);
};
digit_t::digit_t(value_type data)
: data(data), check_digit(make_check_digit(data)) {}
digit_t::digit_t(void)
: data(0), check_digit(0) {}
digit_t& digit_t::operator=(value_type data) {
this->data = data;
this->check_digit = make_check_digit(data);
return *this;
}
template<class T>
auto is_even(T x) -> typename std::enable_if<std::is_integral<T>::value, bool>::type {
return x%2==0;
}
unsigned int digit_t::make_check_digit(value_type digit) {
unsigned int d=0;
for(int i=0; i<12; i++, digit/=10) {
int c = digit%10;
if(is_even(i)) c*=2;
d += c/10+c%10;
}
return d ? 10-d%10 : 0;
}
std::istream& operator>>(std::istream& is, digit_t& d) {
digit_t::value_type v=0;
for(int i=0; i<12; i++) {
int ch=is.peek();
if(isdigit(ch)) {
is.ignore();
v*=10;
v+=ch-'0';
} else {
is.setstate(is.failbit);
return is;
}
}
int ch=is.peek();
if(ch=='\n') {
is.ignore();
} else {
is.setstate(is.failbit);
return is;
}
d = v;
return is;
}
std::ostream& operator<<(std::ostream& os, digit_t& d) {
os.width(12);
os.fill('0');
os << d.data;
os << d.check_digit;
return os;
}
int main(void) {
digit_t d;
while(std::cin >> d) {
std::cout << d << std::endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment