How to resolve the algorithm Unprimeable numbers step by step in the C++ programming language

Published on 7 June 2024 03:52 AM

How to resolve the algorithm Unprimeable numbers step by step in the C++ programming language

Table of Contents

Problem Statement

As used here, all unprimeable numbers   (positive integers)   are always expressed in base ten.

───── Definition from OEIS ─────: Unprimeable numbers are composite numbers that always remain composite when a single decimal digit of the number is changed.

───── Definition from Wiktionary   (referenced from Adam Spencer's book) ─────: (arithmetic)   that cannot be turned into a prime number by changing just one of its digits to any other digit.   (sic)

Unprimeable numbers are also spelled:   unprimable. All one─ and two─digit numbers can be turned into primes by changing a single decimal digit.

190   isn't unprimeable,   because by changing the zero digit into a three yields   193,   which is a prime.

The number   200   is unprimeable,   since none of the numbers   201, 202, 203, ··· 209   are prime, and all the other numbers obtained by changing a single digit to produce   100, 300, 400, ··· 900,   or   210, 220, 230, ··· 290   which are all even.

It is valid to change   189   into   089   by changing the   1   (one)   into a   0   (zero),   which then the leading zero can be removed,   and then treated as if the   "new"   number is   89.

Show all output here, on this page.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Unprimeable numbers step by step in the C++ programming language

The provided C++ code defines functions to identify and categorize "unprimeable" numbers based on specific criteria and uses a prime sieve to check for primality efficiently. Here's a breakdown of what the code does:

  1. Counting Digits (count_digits function):

    • Calculates the number of decimal digits in the given integer n.
  2. Changing a Digit (change_digit function):

    • Replaces a digit at a specified index in the given integer n with a new digit new_digit to create a modified number m.
  3. Unprimeability Check (unprimeable function):

    • Uses a pre-calculated prime sieve to check if the given integer n is prime.
    • Iterates through each digit of n and modifies it to check if there exists any modified number m that is prime.
    • If no such m is found, the function returns true, indicating that n is unprimeable. Otherwise, it returns false.
  4. Main Function:

    • Sets a limit of 10,000,000 integers and initializes a prime sieve for that limit.
    • Iterates through integers from 100 to the limit:
      • For each number n, it checks if n is unprimeable using the unprimeable function.
      • If n is unprimeable, it prints it and keeps track of the count and the lowest unprimeable number ending in each digit.
    • After processing, it prints the first 35 unprimeable numbers, the 600th unprimeable number, and the least unprimeable number ending in each digit from 0 to 9.
  5. Prime Sieve Implementation (prime_sieve class in prime_sieve.hpp):

    • The prime_sieve class provides a simple implementation of the Sieve of Eratosthenes to efficiently check for prime numbers.
    • It constructs a sieve up to a specified limit and uses a vector to mark prime numbers.
    • The is_prime function checks if a given integer is prime within the limit of the sieve.

Source code in the cpp programming language

#include <iostream>
#include <cstdint>
#include "prime_sieve.hpp"

typedef uint32_t integer;

// return number of decimal digits
int count_digits(integer n) {
    int digits = 0;
    for (; n > 0; ++digits)
        n /= 10;
    return digits;
}

// return the number with one digit replaced
integer change_digit(integer n, int index, int new_digit) {
    integer p = 1;
    integer changed = 0;
    for (; index > 0; p *= 10, n /= 10, --index)
        changed += p * (n % 10);
    changed += (10 * (n/10) + new_digit) * p;
    return changed;
}

// returns true if n unprimeable
bool unprimeable(const prime_sieve& sieve, integer n) {
    if (sieve.is_prime(n))
        return false;
    int d = count_digits(n);
    for (int i = 0; i < d; ++i) {
        for (int j = 0; j <= 9; ++j) {
            integer m = change_digit(n, i, j);
            if (m != n && sieve.is_prime(m))
                return false;
        }
    }
    return true;
}

int main() {
    const integer limit = 10000000;
    prime_sieve sieve(limit);

    // print numbers with commas
    std::cout.imbue(std::locale(""));

    std::cout << "First 35 unprimeable numbers:\n";
    integer n = 100;
    integer lowest[10] = { 0 };
    for (int count = 0, found = 0; n < limit && (found < 10 || count < 600); ++n) {
        if (unprimeable(sieve, n)) {
            if (count < 35) {
                if (count != 0)
                    std::cout << ", ";
                std::cout << n;
            }
            ++count;
            if (count == 600)
                std::cout << "\n600th unprimeable number: " << n << '\n';
            int last_digit = n % 10;
            if (lowest[last_digit] == 0) {
                lowest[last_digit] = n;
                ++found;
            }
        }
    }
    for (int i = 0; i < 10; ++i)
        std::cout << "Least unprimeable number ending in " << i << ": " << lowest[i] << '\n';
    return 0;
}


#ifndef PRIME_SIEVE_HPP
#define PRIME_SIEVE_HPP

#include <algorithm>
#include <vector>

/**
 * A simple implementation of the Sieve of Eratosthenes.
 * See https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes.
 */
class prime_sieve {
public:
    explicit prime_sieve(size_t);
    bool is_prime(size_t) const;
private:
    std::vector<bool> is_prime_;
};

/**
 * Constructs a sieve with the given limit.
 *
 * @param limit the maximum integer that can be tested for primality
 */
inline prime_sieve::prime_sieve(size_t limit) {
    limit = std::max(size_t(3), limit);
    is_prime_.resize(limit/2, true);
    for (size_t p = 3; p * p <= limit; p += 2) {
        if (is_prime_[p/2 - 1]) {
            size_t inc = 2 * p;
            for (size_t q = p * p; q <= limit; q += inc)
                is_prime_[q/2 - 1] = false;
        }
    }
}

/**
 * Returns true if the given integer is a prime number. The integer
 * must be less than or equal to the limit passed to the constructor.
 *
 * @param n an integer less than or equal to the limit passed to the
 * constructor
 * @return true if the integer is prime
 */
inline bool prime_sieve::is_prime(size_t n) const {
    if (n == 2)
        return true;
    if (n < 2 || n % 2 == 0)
        return false;
    return is_prime_.at(n/2 - 1);
}

#endif


  

You may also check:How to resolve the algorithm 2048 step by step in the Pony programming language
You may also check:How to resolve the algorithm Parallel calculations step by step in the Erlang programming language
You may also check:How to resolve the algorithm Euler's sum of powers conjecture step by step in the Go programming language
You may also check:How to resolve the algorithm Palindromic gapful numbers step by step in the zkl programming language
You may also check:How to resolve the algorithm Cheryl's birthday step by step in the Arturo programming language