2025-11-30 13:42:16 +01:00
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
#include <fstream>
|
2026-02-20 00:37:32 +01:00
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <vector>
|
2026-02-22 22:19:28 +01:00
|
|
|
|
#ifdef _OPENMP
|
|
|
|
|
|
#include <omp.h>
|
|
|
|
|
|
#endif
|
2025-11-30 13:42:16 +01:00
|
|
|
|
|
|
|
|
|
|
#ifndef CHECK_ISBN_CPP
|
|
|
|
|
|
#define CHECK_ISBN_CPP
|
|
|
|
|
|
|
|
|
|
|
|
const bool DEBUG = 0;
|
|
|
|
|
|
const int ISBN_LENGTH = 10;
|
|
|
|
|
|
const int CHECK_NUMBER = 11;
|
|
|
|
|
|
const unsigned long long int HIGHEST_ISBN = 9999999999;
|
|
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
void printVector(std::vector<int> v) {
|
|
|
|
|
|
for (unsigned int i = 0; i < v.size(); i++) {
|
|
|
|
|
|
std::cout << v[i] << "; ";
|
|
|
|
|
|
}
|
2025-11-30 13:42:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
void print(const std::string printMe) { std::cout << printMe << std::endl; }
|
|
|
|
|
|
|
|
|
|
|
|
void e() { print("PRINT"); }
|
|
|
|
|
|
|
|
|
|
|
|
bool checkInput(const std::string input) {
|
|
|
|
|
|
if (input.length() != ISBN_LENGTH) {
|
|
|
|
|
|
print("Your number is too short/too long");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i <= ISBN_LENGTH - 1; i++) {
|
|
|
|
|
|
if (input.at(i) < '0' || input.at(i) > '9') {
|
|
|
|
|
|
print("Your number consists of illegal characters");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
2025-11-30 13:42:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
std::vector<int> stringToIntVector(const std::string input) {
|
|
|
|
|
|
std::vector<int> vector;
|
|
|
|
|
|
for (int i = input.length() - 1; i >= 0; i--) {
|
|
|
|
|
|
vector.push_back(input.at(i) - '0');
|
|
|
|
|
|
}
|
|
|
|
|
|
return vector;
|
2025-11-30 13:42:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
std::vector<int> userISBN() {
|
|
|
|
|
|
std::string input;
|
|
|
|
|
|
do {
|
|
|
|
|
|
std::cout << "Enter the ISBN number (10 digits): ";
|
|
|
|
|
|
getline(std::cin, input);
|
|
|
|
|
|
} while (!checkInput(input));
|
|
|
|
|
|
return stringToIntVector(input);
|
2025-11-30 13:42:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
bool checkISBN(const std::vector<int> isbn) {
|
|
|
|
|
|
int sum = 0, t = 0;
|
|
|
|
|
|
for (int i = 0; i < ISBN_LENGTH; i++) {
|
|
|
|
|
|
t += isbn[i];
|
|
|
|
|
|
sum += t;
|
|
|
|
|
|
}
|
2025-11-30 13:42:16 +01:00
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
/*if(DEBUG)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!(sum % CHECK_NUMBER)) print("^^^ VALID NUMBER ^^^");
|
|
|
|
|
|
} */
|
2025-11-30 13:42:16 +01:00
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
return !(sum % CHECK_NUMBER);
|
2025-11-30 13:42:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-22 22:19:28 +01:00
|
|
|
|
// Optimisation 1 – no heap allocation: intToVector() removed; checkAll()
|
|
|
|
|
|
// uses only stack variables in the nested loops below.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Optimisation 2 – algorithmic reduction (10^10 → 10^9 iterations):
|
|
|
|
|
|
// ISBN-10 validity: 10*d0 + 9*d1 + ... + 2*d8 + 1*d9 ≡ 0 (mod 11)
|
|
|
|
|
|
// Given a 9-digit prefix d0..d8 the check digit is determined:
|
|
|
|
|
|
// d9 = (11 - S%11) % 11 where S = weighted sum of prefix
|
|
|
|
|
|
// The number is valid iff d9 ≤ 9 (i.e. d9 ≠ 10).
|
|
|
|
|
|
//
|
|
|
|
|
|
// Optimisation 3 – incremental partial sums + OpenMP:
|
|
|
|
|
|
// Each loop level accumulates its contribution once, not inside the
|
|
|
|
|
|
// innermost body. The outermost loop is parallelised with OpenMP.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Optimisation 4 – separated I/O:
|
|
|
|
|
|
// File writing is done in a second serial pass with a large buffer so
|
|
|
|
|
|
// it doesn't contend with (or race against) the parallel counting pass.
|
|
|
|
|
|
long long countISBNs() {
|
|
|
|
|
|
long long sum = 0;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _OPENMP
|
|
|
|
|
|
#pragma omp parallel for reduction(+ : sum) schedule(static)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
for (int d0 = 0; d0 <= 9; d0++) {
|
|
|
|
|
|
int s0 = 10 * d0;
|
|
|
|
|
|
for (int d1 = 0; d1 <= 9; d1++) {
|
|
|
|
|
|
int s1 = s0 + 9 * d1;
|
|
|
|
|
|
for (int d2 = 0; d2 <= 9; d2++) {
|
|
|
|
|
|
int s2 = s1 + 8 * d2;
|
|
|
|
|
|
for (int d3 = 0; d3 <= 9; d3++) {
|
|
|
|
|
|
int s3 = s2 + 7 * d3;
|
|
|
|
|
|
for (int d4 = 0; d4 <= 9; d4++) {
|
|
|
|
|
|
int s4 = s3 + 6 * d4;
|
|
|
|
|
|
for (int d5 = 0; d5 <= 9; d5++) {
|
|
|
|
|
|
int s5 = s4 + 5 * d5;
|
|
|
|
|
|
for (int d6 = 0; d6 <= 9; d6++) {
|
|
|
|
|
|
int s6 = s5 + 4 * d6;
|
|
|
|
|
|
for (int d7 = 0; d7 <= 9; d7++) {
|
|
|
|
|
|
int s7 = s6 + 3 * d7;
|
|
|
|
|
|
for (int d8 = 0; d8 <= 9; d8++) {
|
|
|
|
|
|
int d9 = (11 - (s7 + 2 * d8) % 11) % 11;
|
|
|
|
|
|
if (d9 <= 9)
|
|
|
|
|
|
++sum;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-20 00:37:32 +01:00
|
|
|
|
}
|
2026-02-22 22:19:28 +01:00
|
|
|
|
return sum;
|
2026-02-20 00:37:32 +01:00
|
|
|
|
}
|
2025-11-30 13:42:16 +01:00
|
|
|
|
|
2026-02-22 22:19:28 +01:00
|
|
|
|
void writeISBNsToFile() {
|
|
|
|
|
|
static const int BUF = 1 << 20; // 1 MB write buffer
|
2026-02-20 00:37:32 +01:00
|
|
|
|
std::ofstream file;
|
2026-02-22 22:19:28 +01:00
|
|
|
|
file.rdbuf()->pubsetbuf(nullptr, BUF);
|
2026-02-20 00:37:32 +01:00
|
|
|
|
file.open("ISBN.txt");
|
2026-02-22 22:19:28 +01:00
|
|
|
|
long long written = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (int d0 = 0; d0 <= 9; d0++) {
|
|
|
|
|
|
int s0 = 10 * d0;
|
|
|
|
|
|
for (int d1 = 0; d1 <= 9; d1++) {
|
|
|
|
|
|
int s1 = s0 + 9 * d1;
|
|
|
|
|
|
for (int d2 = 0; d2 <= 9; d2++) {
|
|
|
|
|
|
int s2 = s1 + 8 * d2;
|
|
|
|
|
|
for (int d3 = 0; d3 <= 9; d3++) {
|
|
|
|
|
|
int s3 = s2 + 7 * d3;
|
|
|
|
|
|
for (int d4 = 0; d4 <= 9; d4++) {
|
|
|
|
|
|
int s4 = s3 + 6 * d4;
|
|
|
|
|
|
for (int d5 = 0; d5 <= 9; d5++) {
|
|
|
|
|
|
int s5 = s4 + 5 * d5;
|
|
|
|
|
|
for (int d6 = 0; d6 <= 9; d6++) {
|
|
|
|
|
|
int s6 = s5 + 4 * d6;
|
|
|
|
|
|
for (int d7 = 0; d7 <= 9; d7++) {
|
|
|
|
|
|
int s7 = s6 + 3 * d7;
|
|
|
|
|
|
for (int d8 = 0; d8 <= 9; d8++) {
|
|
|
|
|
|
int s = s7 + 2 * d8;
|
|
|
|
|
|
int d9 = (11 - s % 11) % 11;
|
|
|
|
|
|
if (d9 <= 9) {
|
|
|
|
|
|
long long isbn = (long long)d0 * 1000000000LL +
|
|
|
|
|
|
d1 * 100000000 + d2 * 10000000 +
|
|
|
|
|
|
d3 * 1000000 + d4 * 100000 + d5 * 10000 +
|
|
|
|
|
|
d6 * 1000 + d7 * 100 + d8 * 10 + d9;
|
|
|
|
|
|
file << isbn << '\n';
|
|
|
|
|
|
++written;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-20 00:37:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-22 22:19:28 +01:00
|
|
|
|
file << "There are " << written << " valid ISBN numbers\n";
|
2026-02-20 00:37:32 +01:00
|
|
|
|
file.close();
|
2025-11-30 13:42:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-20 00:37:32 +01:00
|
|
|
|
int main() {
|
2026-02-22 22:19:28 +01:00
|
|
|
|
long long count = countISBNs();
|
|
|
|
|
|
std::cout << "There are " << count << " valid ISBN numbers\n";
|
|
|
|
|
|
writeISBNsToFile();
|
2026-02-20 00:37:32 +01:00
|
|
|
|
return 0;
|
2025-11-30 13:42:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|