144 lines
2.5 KiB
C++
144 lines
2.5 KiB
C++
#include <iostream>
|
|
#include <fstream>
|
|
|
|
using namespace std;
|
|
|
|
ifstream input_stream;
|
|
ofstream output_stream;
|
|
|
|
bool checkAscending(string numStr) {
|
|
char highestDigit = numStr[0];
|
|
|
|
for (uint8_t i = 1; i < numStr.length(); i++) {
|
|
if (numStr[i] < highestDigit) {
|
|
return false;
|
|
}
|
|
highestDigit = numStr[i];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
uint64_t n_choose_m(uint8_t n, uint8_t m) {
|
|
if (m > n) {
|
|
return 0;
|
|
}
|
|
|
|
if (m * 2 > n) {
|
|
m = n - m;
|
|
}
|
|
|
|
if (m == 0) {
|
|
return 1;
|
|
}
|
|
|
|
uint64_t res = n;
|
|
|
|
for (int i = 2; i <= m; i++) {
|
|
res *= n - i + 1;
|
|
res /= i;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
uint64_t pos_combinations(uint8_t pos) {
|
|
/**
|
|
pos starts at 0 from right end of number
|
|
10^pos <> 10^pos-1
|
|
*/
|
|
if (pos == 0) {
|
|
return 0;
|
|
} else {
|
|
return n_choose_m(8 + pos, pos);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint64_t following_combinations(uint8_t first_num, uint8_t pos) {
|
|
/**
|
|
10^pos+1 <> first_num * 10^pos
|
|
available = 10 - (first_num - 1) + allowed_repeats (pos)
|
|
*/
|
|
return n_choose_m(10 - first_num + pos, pos + 1);
|
|
}
|
|
|
|
|
|
|
|
uint64_t preceeding_combinations(uint8_t first_num, uint8_t pos) {
|
|
/**
|
|
first_num * 10^pos <> 10^pos
|
|
*/
|
|
return pos_combinations(pos + 1) - following_combinations(first_num, pos);
|
|
}
|
|
|
|
|
|
|
|
uint64_t find_ascending(string start, string end) {
|
|
uint64_t result = 0;
|
|
const uint8_t end_len = end.length();
|
|
|
|
if (end_len == 1) {
|
|
result += stoi(end) - stoi(start) + 1;
|
|
} else if (start == "1") {
|
|
char highest_digit = '1';
|
|
bool sequence_integrity = true;
|
|
|
|
// Run this loop until a digit lower than the others is encountered
|
|
uint8_t i;
|
|
for (i = 0; i < end_len - 1; i++) {
|
|
uint8_t pos = end_len - i - 1;
|
|
result += pos_combinations(pos);
|
|
|
|
if (end[i] > highest_digit) {
|
|
result += preceeding_combinations(end[i] - '0', pos) - preceeding_combinations(highest_digit - '0', pos);
|
|
highest_digit = end[i];
|
|
} else if (end[i] < highest_digit) {
|
|
sequence_integrity = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
for (i; i < end_len - 1; i++) {
|
|
uint8_t pos = end_len - i - 1;
|
|
result += pos_combinations(pos);
|
|
}
|
|
|
|
if (sequence_integrity && end[end_len - 1] >= highest_digit) {
|
|
result += end[end_len - 1] - highest_digit + 1;
|
|
}
|
|
} else {
|
|
result += find_ascending("1", end) - find_ascending("1", start);
|
|
|
|
if (checkAscending(start)) {
|
|
result += 1;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
int main() {
|
|
input_stream.open("input.txt");
|
|
output_stream.open("output.txt");
|
|
|
|
string A;
|
|
string B;
|
|
|
|
input_stream >> A;
|
|
input_stream >> B;
|
|
|
|
cout << find_ascending(A, B) << endl;
|
|
|
|
input_stream.close();
|
|
output_stream.close();
|
|
return 0;
|
|
}
|