Blog Entry © Friday, November 21, 2025, by James Pate Williams, Jr., Win32 C/C++ Desktop GUI Solution of the 15-Tile Puzzle Using Iterative Deepening A* Informed Seach Algorithm

Blog Entry © Monday, November 17, 2025, by James Pate Williams, Jr. An Elitist Evolutionary Hill Climber to Solve the 8-Tile Puzzle

Blog Entry © Sunday, July 27, 2025, A Bit of Programming Nostalgia Prime Number Related Programs by James Williams, Jr.

/*
  Author:  Pate Williams c 1995

  The following program is a solution to problem 18.15
  in Pascalgorithms by Edwin D. Reilly and Francis D.
  Federighi page 627. The program uses Simpson's rule
  to calculate the number of primes less than or equal
  a given number.
*/

#include <math.h>
#include <stdio.h>

typedef double real;

static real f(real x)
{
	return(1.0 / log(x));
}

static real simpson(int n, real a, real b)
{
	int i;
	real evensum, h, oddsum, twoh, x;

	if (n % 2 == 1) n = n - 1;
	h = (b - a) / n;
	twoh = h + h;
	x = h + a;
	oddsum = 0.0;
	for (i = 1; i <= n / 2; i++)
	{
		oddsum += f(x);
		x = twoh + x;
	}
	x = twoh + a;
	evensum = 0.0;
	for (i = 1; i <= n / 2 - 1; i++)
	{
		evensum += f(x);
		x = twoh + x;
	}
	return(h / 3.0 * (f(a) + f(b) + 4.0 * oddsum + 2.0 * evensum));
}

int main(void)
{
	int i, n, Nmaximum = 0, Nminimum = 0, Nstep;

	printf("n = ");			scanf_s("%d", &n);
	printf("N minimum = "); scanf_s("%d", &Nminimum);
	printf("N maximum = "); scanf_s("%d", &Nmaximum);
	printf("N step = ");	scanf_s("%d", &Nstep);
	printf("\n");
	printf("----------------------------------------\n");
	printf("Min\t\tMax\t\tprimes\n");
	printf("----------------------------------------\n");
	for (i = Nminimum; i <= Nmaximum; i += Nstep)
	{
		printf("%8d\t%8d\t%8.0lf\n", Nminimum, i + Nstep,
			simpson(n, Nminimum, i + Nstep));
	}
	printf("----------------------------------------\n");
	return(0);
}
n = 1024
N minimum = 0
N maximum = 10000000
N step = 1000000

----------------------------------------
Min             Max             primes
----------------------------------------
       0         1000000           78551
       0         2000000          148923
       0         3000000          216788
       0         4000000          283122
       0         5000000          348361
       0         6000000          412754
       0         7000000          476461
       0         8000000          539590
       0         9000000          602224
       0        10000000          664424
       0        11000000          726239
----------------------------------------

D:\PrimeCounter\x64\Release\PrimeCounter.exe (process 51884) exited with code 0 (0x0).
Press any key to close this window . . .
/*
  Author:  Pate Williams c 1995

  The following is a translation of the Pascal program
  sieve found in Pascalgorithms by Edwin D. Reilly and
  Francis D. Federighi page 652. This program uses sets
  to represent the sieve (see C Programming Language An
  Applied Perspective by Lawrence Miller and Alec Qui-
  lici pages 160 - 162).
*/

#include <math.h>
#include <stdio.h>

#define _WORD_SIZE 32
#define _VECT_SIZE 524288
#define SET_MIN    0
#define SET_MAX    16777215

typedef unsigned long SET[_VECT_SIZE];
typedef long ELEMENT;
typedef unsigned long LONG;

SET set;

static int get_bit_pos(int* long_ptr, int* bit_ptr,
	ELEMENT element)
{
	*long_ptr = element / _WORD_SIZE;
	*bit_ptr = element % _WORD_SIZE;
	return(element >= SET_MIN && element <= SET_MAX);
}

static void set_bit(ELEMENT element, int inset)
{
	int bit, word;

	if (get_bit_pos(&word, &bit, element))
	{
		if (inset > 0)
			set[word] |= (01 << bit);
		else
			set[word] &= ~(01 << bit);
	}
}

static int get_bit(ELEMENT element)
{
	int bit, word;

	return(get_bit_pos(&word, &bit, element) ?
		(set[word] >> bit) & 01 : 0);
}

static void set_Add(ELEMENT element)
{
	set_bit(element, 1);
}

static void set_Del(ELEMENT element)
{
	set_bit(element, 0);
}

static int set_Mem(ELEMENT element)
{
	return get_bit(element);
}

static void primes(long n)
{
	long c, i, inc, k;
	double x;

	set_Add(2);
	for (i = 3; i <= n; i++)
		if ((i + 1) % 2 == 0)
			set_Add(i);
		else
			set_Del(i);
	c = 3;
	do
	{
		i = c * c;
		inc = c + c;
		while (i <= n)
		{
			set_Del(i);
			i = i + inc;
		}
		c += 2;
		while (set_Mem(c) == 0) c += 1;
	} while (c * c <= n);
	k = 0;
	for (i = 2; i <= n; i++)
		if (set_Mem(i) == 1) k++;
	x = n / log(n) - 5.0;
	x = x + exp(1.0 + 0.15 * log(n) * sqrt(log(n)));
	printf("%8ld\t%8ld\t%8.0lf\n", n, k, x);
}

int main(void)
{
	long n = 100L;

	printf("----------------------------------------\n");
	printf("n\t\tprimes\t\ttheory\n");
	printf("----------------------------------------\n");
	do
	{
		primes((int)n);
		n = 10L * n;
	} while (n < (long)SET_MAX);
	printf("----------------------------------------\n");
	return(0);
}
----------------------------------------
n               primes          theory
----------------------------------------
     100              25              29
    1000             168             181
   10000            1229            1261
  100000            9592            9634
 1000000           78498           78396
10000000          664579          665060
----------------------------------------

D:\Sieve\x64\Release\Sieve.exe (process 60092) exited with code 0 (0x0).
Press any key to close this window . . .

Rice-Golomb Encoder and Decoder Copyright (c) Thursday, April 3, 2025, to Sunday, April 6, 2025, by James Pate Williams, Jr. BA, BS, Master of Software Engineering, Doctor of Philosophy Computer Science

Online references:

https://en.wikipedia.org/wiki/Golomb_coding

// Rice-Golomb Encoder and Decoder
// Copyright (c) Thursday, April 3, 2025
// by James Pate Williams, Jr.
// BA, BS, Master of Software Engineering
// Doctor of Philosophy Computer Science
// Online references:
// https://en.wikipedia.org/wiki/Golomb_coding
// https://ntrs.nasa.gov/api/citations/19790014634/downloads/19790014634.pdf

#include <iostream>
#include <string>
#include <vector>
//#include <stdlib.h>

bool Encode(const char* NChars, size_t NCharsCount,
    long M, long long& N, std::vector<char>& qBits,
    std::vector<char>& rBits, unsigned int& qSize, unsigned int& rSize,
    long long& q, long long& r, unsigned int& NSize) {
    N = NChars[0] - (long long)'0';
    for (unsigned int i = 1; i < NCharsCount; i++) {
        N = 10 * N + (long long)NChars[i] - (long long)'0';
    }
    q = N / M;
    r = N % M;
    qSize = 0;
    while (qSize < q) {
        qBits.push_back('1');
        qSize++;
    }
    qBits.push_back('0');
    qSize++;
    rSize = 0;
    unsigned int b = (unsigned int)floor(log2(M));
    if (b > 62) {
        return false;
    }
    long long p = (long long)pow(2, b + 1);
    if (r < p - M) {
        long long rr = r;
        while (rr > 0) {
            long long digit = (rr & 1) == 1 ? 1 : 0;
            rBits.push_back((char)digit + '0');
            rSize++;
            rr >>= 1;
        }
        rBits.push_back('0');
        rSize++;
    }
    else {
        long long rr = r + p - M;
        while (rSize < b + 1) {
            long long digit = rr & 1 ? 1 : 0;
            rBits.push_back((char)digit + '0');
            rSize++;
            rr >>= 1;
        }
    }
    long long rValue = rBits[0];
    for (size_t i = 1; i < rSize; i++) {
        rValue = rValue * 2 + rBits[i];
    }
    long long NBitCount = 0;
    while (N > 0) {
        N >>= 1;
        NBitCount++;
    }
    std::cout << "q-bits size = " << qSize << std::endl;
    std::cout << "r-bits size = " << rSize << std::endl;
    std::cout << "N-bits size = " << qSize + rSize << std::endl;
    std::cout << "N-Chars * 8-Bits per Char = " << NCharsCount * 8 << std::endl;
    std::cout << "% Compression = " << 100.0 * (1.0 - (qSize + rSize) /
        (NCharsCount * 8.0)) << std::endl;
    return true;
}

void Decode(long long M, long long& N,
    std::vector<char> qBits, std::vector<char> rBits,
    unsigned int& qSize, unsigned int& rSize,
    long long& q, long long& r) {
    int count = 0;
    while (qBits[count] != '0') {
        count++;
    }
    q = count;
    int c = (int)rSize - 1;
    unsigned int b = (unsigned int)floor(log2(M));
    long long p = (long long)pow(2, b + 1);
    long long s = 0;
    r = rBits[c--] - (long long)'0';
    do {
        r = 2 * r + rBits[c] - (long long)'0';
        c--;
    } while (c >= 0);
    if (r < p - M) {
        s = r;
    }
    else {
        s = r + p - M;
        c = 1;
        r = rBits[0] - (long long)'0';
        while (c < (int)(b + 1)) {
            r = 2 * r + rBits[c] - (long long)'0';
            c++;
        }
        s = r;
    }
    r = s;
    N = q * M + r;
}

int main() {
    char line[128] = { };
    size_t NSize = 0, qSize = 0, rSize = 0;
    long long M = 10, N = 42, q = -1, r = -1;
    std::vector<char> qBits, rBits;
    std::cout << "M = ";
    std::cin.getline(line, 127);
    std::string str1(line);
    M = std::stoi(str1);
    std::cout << "N = ";
    std::cin.getline(line, 127);
    std::string str2(line);
    Encode(str2.c_str(), strlen(str2.c_str()), M, N,
        qBits, rBits, qSize, rSize, q, r, NSize);
    std::cout << "q = " << q << std::endl;
    std::cout << "r = " << r << std::endl;
    std::cout << "q-size = " << qSize << std::endl;
    std::cout << "r-size = " << rSize << std::endl;
    std::cout << "q ";
    for (unsigned int i = 0; i < qSize; i++) {
        std::cout << qBits[i] << ' ';
    }
    std::cout << std::endl;
    std::cout << "r ";
    for (int i = (int)rSize - 1; i >= 0; i--) {
        std::cout << rBits[i] << ' ';
    }
    std::cout << std::endl;
    Decode(M, N, qBits, rBits, qSize, rSize, q, r);
    std::cout << "q = " << q << std::endl;
    std::cout << "r = " << r << std::endl;
    std::cout << "q-size = " << qSize << std::endl;
    std::cout << "r-size = " << rSize << std::endl;
    std::cout << "q ";
    for (unsigned int i = 0; i < qSize; i++) {
        std::cout << qBits[i] << ' ';
    }
    std::cout << std::endl;
    std::cout << "r ";
    for (int i = rSize - 1; i >= 0; i--) {
        std::cout << rBits[i] << ' ';
    }
    std::cout << std::endl;
    std::cout << "N = " << N << std::endl;
    return 0;
}
M = 64
N = 1027
q-bits size = 17
r-bits size = 3
N-bits size = 20
N-Chars * 8-Bits per Char = 32
% Compression = 37.5
q = 16
r = 3
q-size = 17
r-size = 3
q 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
r 0 1 1
q = 16
r = 3
q-size = 17
r-size = 3
q 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
r 0 1 1
N = 1027

Live Person-to-Person Tutoring

Blog Entry (c) Friday, June 21, 2024, by James Pate Williams, Jr. Comparison of Two Prime Number Sieves

First the C++ results:

Limit = 1000000
Number of primes <= 1000000 78498
Milliseconds taken by Sieve of Atkin: 12
Number of primes <= 1000000 78498
Milliseconds taken by Sieve of Eratosthenes: 14
Limit = 10000000
Number of primes <= 10000000 664579
Milliseconds taken by Sieve of Atkin: 159
Number of primes <= 10000000 664579
Milliseconds taken by Sieve of Eratosthenes: 204
Limit = 100000000
Number of primes <= 100000000 5761455
Milliseconds taken by Sieve of Atkin: 1949
Number of primes <= 100000000 5761455
Milliseconds taken by Sieve of Eratosthenes: 2343
Limit = 0

Next, we have the Java results:

C:\WINDOWS\system32>java -jar k:\SieveOfAtkin\build\Debug\SieveOfAtkin.jar 1000000 0
number of primes less than equal 1000000 = 78498
total computation time in seconds = 0.008

C:\WINDOWS\system32>java -jar k:\SieveOfAtkin\build\Debug\SieveOfAtkin.jar 10000000 0
number of primes less than equal 10000000 = 664579
total computation time in seconds = 0.098

C:\WINDOWS\system32>java -jar k:\SieveOfEratosthenes\build\Debug\SieveOfEratosthenes.jar 1000000 0
number of primes less than equal 1000000 = 78498
total computation time in seconds = 0.011

C:\WINDOWS\system32>java -jar k:\SieveOfEratosthenes\build\Debug\SieveOfEratosthenes.jar 10000000 0
number of primes less than equal 10000000 = 664579
total computation time in seconds = 0.151

C:\WINDOWS\system32>java -jar k:\SieveOfAtkin\build\Debug\SieveOfAtkin.jar 100000000 0
number of primes less than equal 100000000 = 5761455
total computation time in seconds = 1.511

C:\WINDOWS\system32>java -jar k:\SieveOfEratosthenes\build\Debug\SieveOfEratosthenes.jar 100000000 0
number of primes less than equal 100000000 = 5761455
total computation time in seconds = 1.995

Notice that the Java application outperforms the C++ application.

// PrimeSieveComparison.cpp (c) Friday, June 21, 2024
// by James Pate Williams, Jr.
//
//  SieveOfAtkin.java
//  SieveOfAtkin
//
//  Created by James Pate Williams, Jr. on 9/29/07.
//  Copyright (c) 2007 James Pate Williams, Jr. All rights reserved.
//
//  SieveOfEratosthenes.java
//  SieveOfEratosthenes
//
//  Created by James Pate Williams, Jr. on 9/29/07.
//  Copyright (c) 2007 James Pate Williams, Jr. All rights reserved.
//

#include <math.h>
#include <iostream>
#include <chrono>
using namespace std::chrono;
using namespace std;

const int Maximum = 100000000;
bool sieve[Maximum + 1];

void SieveOfAtkin(int limit)
{
	auto start = high_resolution_clock::now();
	int e, k, n, p, x, xx3, xx4, y, yy;
	int primeCount = 2, sqrtLimit = (int)sqrt(limit);

	for (n = 5; n <= limit; n++)
		sieve[n] = false;

	for (x = 1; x <= sqrtLimit; x++) {
		xx3 = 3 * x * x;
		xx4 = 4 * x * x;
		for (y = 1; y <= sqrtLimit; y++) {
			yy = y * y;
			n = xx4 + yy;
			if (n <= limit && (n % 12 == 1 || n % 12 == 5))
				sieve[n] = !sieve[n];
			n = xx3 + yy;
			if (n <= limit && n % 12 == 7)
				sieve[n] = !sieve[n];
			n = xx3 - yy;
			if (x > y && n <= limit && n % 12 == 11)
				sieve[n] = !sieve[n];
		}
	}

	for (n = 5; n <= sqrtLimit; n++) {
		if (sieve[n]) {
			e = 1;
			p = n * n;
			while (true) {
				k = e * p;
				if (k > limit)
					break;
				sieve[k] = false;
				e++;
			}
		}
	}
	
	for (n = 5; n <= limit; n++)
		if (sieve[n])
			primeCount++;

	auto stop = high_resolution_clock::now();
	auto duration = duration_cast<milliseconds>(stop - start);

	std::cout << "Number of primes <= " << limit << ' ';
	std::cout << primeCount << endl;
	std::cout << "Milliseconds taken by Sieve of Atkin: "
		<< duration.count() << endl;
}

void SieveOfEratosthenes(int limit)
{
	auto start = high_resolution_clock::now();
	int i = 0, k = 0, n = 0, nn = 0;
	int primeCount = 0, sqrtLimit = (int)sqrt(limit);

	// initialize the prime number sieve

	for (n = 2; n <= limit; n++)
		sieve[n] = true;

	// eliminate the multiples of n

	for (n = 2; n <= sqrtLimit; n++)
		for (i = 2; i <= n - 1; i++)
			sieve[i * n] = false;

	// eliminate squares

	for (n = 2; n <= sqrtLimit; n++) {
		if (sieve[n]) {
			k = 0;
			nn = n * n;
			i = nn + k * n;
			while (i <= limit) {
				sieve[i] = false;
				i = nn + k * n;
				k++;
			}
		}
	}

	primeCount = 0;

	for (n = 2; n <= limit; n++)
		if (sieve[n])
			primeCount++;

	auto stop = high_resolution_clock::now();
	auto duration = duration_cast<milliseconds>(stop - start);

	std::cout << "Number of primes <= " << limit << ' ';
	std::cout << primeCount << endl;
	std::cout << "Milliseconds taken by Sieve of Eratosthenes: "
		<< duration.count() << endl;
}

int main()
{
	while (true)
	{
		int limit = 0;
		std::cout << "Limit = ";
		cin >> limit;

		if (limit == 0)
			break;

		SieveOfAtkin(limit);
		SieveOfEratosthenes(limit);
	}

	return 0;
}

Classical Shor’s Algorithm Versus J. M. Pollard’s Factoring with Cubic Integers

We tried to factor the following numbers with each algorithm: 11^3+2, 2^33+2, 5^15+2, 2^66+2, 2^72+2, 2^81+2, 2^101+2, 2^129+2, and 2^183+2. Shor’s algorithm fully factored all of the numbers. Factoring with cubic integers fully factored all numbers except 2^66+2, 2^71+2, 2^129+2, and 2^183+2.

cs1cubiccs1shor

cs2cubiccs2shor

cs3cubiccs3shor

cs4cubiccs4shor

cs5cubiccs5shor

cs6cubiccs6shor

cs7cubiccs7shor

cs8cubiccs8shor

cs9cubiccs9shor

Typical full output from factoring with cubic integers:

A-Solutions = 973
B-Solutions = 234
Known Eqs = 614
Solutions = 1821
Rows = 1821
Columns = 1701
Kernel rank = 423
Sieved = 326434
Successes0 = 200863
Successes1 = 47073
Successes2 = 2708
Successes3 = 973
Successes4 = 1735

2417851639229258349412354 - 25 DDs

2 p
65537 p
414721 p
44479210368001 p

Sets = 189
#Factor Base 1 = 501
#Factor Base 2 = 868

FactB1 time = 00:00:00.000
FactB2 time = 00:00:05.296
Sieve time  = 00:00:17.261
Kernel time = 00:00:06.799
Factor time = 00:00:02.327
Total time  = 00:00:31.742

A-solutions have no large prime. B-solutions have a large prime between B0 and B1 exclusively which is this case is between 3272 and 50000 exclusively. The known equations are between the rational primes and the cubic primes and their associates of the form p = 6k + 1 that have -2 as a cubic residue. There are 81 rational primes of the form and 243 cubic primes but we keep many other associates of the cubic primes so more a and b pairs are successfully algebraically factored. In out case the algebraic factor base has 868 members. The rational prime factor base also includes the negative unit -1. The kernel rank is the number of independent columns in the matrix. The number of dependent sets is equal to columns – rank which is this case 1701 – 423 = 1278. The number of (a, b) pairs sieved is 326434. Successes0 is the pairs that have gcd(a, b) = 1. Successes1 is the number of (a, b) pairs such that a+b*r is B0-smooth or can be factored by the first 500 primes and the negative unit. r is equal to 2^27. Successes2 is the number of (a, b) pairs whose N[a, b] = a^2-2*b^3 can be factored using the norms of the algebraic primes. Successes3 is the number of A-solutions that are algebraically and rationally smooth. Successes4 is the number of B-solutions without combining to make the count modulo 2 = 0. Successes3 + Successes4 should equal Successes2 provided all proper algebraic primes and their associates are utilized.

Note factoring with cubic integers is very fickle with respect to parameter choice.

Classical Shor’s Algorithm

Shor’s algorithm is a fast method of factoring integers using a quantum computer:

https://en.wikipedia.org/wiki/Shor%27s_algorithm

I have implemented the algorithm classically and performed a few experiments on integers greater than equal 12. I used Floyd’s cycle finding algorithm as implemented with a randomized Pollard’s Rho Factoring method using two second degree polynomials:

https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm

I factored the seventh Fermat number in less than nine minutes. J. M. Pollard factored this number in 20.1 hours in 1988 using the special number field sieve [see “Lecture Notes in Mathematics 1554 The Development of the Number Field Sieve” edited by A. K. Lenstra and H. W. Lenstra, Jr. The paper by Pollard is entitled “Factoring with Cubic Integers”]. Both Pollard and I used personal computers.

Suppose Moore’s original law is applied to Pollard’s factoring of the seventh Fermat number and also assume computing time is cut in half every two years then we can compute the following table:

A less optimistic table states that the computation time is halved every four years:

I successfully factored 38 of 39 numbers of the form 12, 123, 1234, 12345, … , 1234567890123456789012345678901234567890. The results of my factoring C# Windows form application are displayed below:

I was eventually able to factor the 38-decimal digit number that failed in the above calculation as illustrated below:

The number of bits per number varied from 4-bits to 130-bits. This is still no where near the ability to factor a 3,000-bit Rivest-Shamir-Adleman composite integer so most financial systems remain secure. The link below will take you to the Microsoft C# project directory on my OneDrive account.

https://1drv.ms/f/s!AjoNe9CiN2M9gfMbQ8H_g3GMQEC6iA

The C# source code is at the preceding link in a printable and readable PDF.