testsAndMisc-archive/CPP/miscelanious/howManyValidISBNNumbersAreThere/11.cpp

183 lines
5.1 KiB
C++
Raw Normal View History

#include <algorithm>
#include <fstream>
2026-02-20 00:37:32 +01:00
#include <iostream>
#include <string>
#include <vector>
#ifdef _OPENMP
#include <omp.h>
#endif
#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] << "; ";
}
}
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;
}
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;
}
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);
}
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;
}
2026-02-20 00:37:32 +01:00
/*if(DEBUG)
{
if(!(sum % CHECK_NUMBER)) print("^^^ VALID NUMBER ^^^");
} */
2026-02-20 00:37:32 +01:00
return !(sum % CHECK_NUMBER);
}
// 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
}
return sum;
2026-02-20 00:37:32 +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;
file.rdbuf()->pubsetbuf(nullptr, BUF);
2026-02-20 00:37:32 +01:00
file.open("ISBN.txt");
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
}
}
file << "There are " << written << " valid ISBN numbers\n";
2026-02-20 00:37:32 +01:00
file.close();
}
2026-02-20 00:37:32 +01:00
int main() {
long long count = countISBNs();
std::cout << "There are " << count << " valid ISBN numbers\n";
writeISBNsToFile();
2026-02-20 00:37:32 +01:00
return 0;
}
#endif