using System;
using System.IO;
namespace primecalc
{
///
/// A hack program to generate HTML pages which correspond to the printed pages in the famous book
/// Lehmer, D. N. List of Prime Numbers from 1 to 10,006,721. Washington, DC: Carnegie Institution, 1914.
/// There are 133 pages of tables, each one with 5000 primes in 100 rows of 50 columns.
///
public sealed class Program
{
private int pages;
private int total;
private int count;
private int[] primes;
private DateTime progressTime;
private int columnsPerPage;
private const int PrimesPerPage = 5000;
private const int RowsPerPage = 100;
private const string OutputFilePattern = @"..\..\output\page{0:000}.htm";
private StreamWriter writer;
public static void Main(string[] args)
{
new Program().Run(args);
}
public Program()
{
}
///
/// The primes 1, 2 and 3 are manually set in the prime array before a loop starts
/// to test every number of the form 6n-1 and 6n+1. NOTE: Lehmer list 1 as a prime,
/// which was a personal convention of his that was never widely accepted, so this
/// program lists 1 to make the HTML pages correspond to the printed ones.
///
/// The command line must specify an integer number of pages to
/// generate as the first parameter. Lehmer's book has 133 pages.
public void Run(string[] args)
{
pages = (args.Length > 1 ? int.Parse(args[0]) : 133);
total = pages * PrimesPerPage;
columnsPerPage = PrimesPerPage / RowsPerPage;
primes = new int[total];
SavePrime(1);
SavePrime(2);
SavePrime(3);
for (int i = 6; ; i += 6)
{
CheckNum(i - 1);
CheckNum(i + 1);
if (count == total)
break;
}
WriteLinks();
}
///
/// This childishly simple check for a prime number attempts to divide by
/// all of the previous primes up to the square root.
///
private void CheckNum(int n)
{
int stop = (int)Math.Sqrt(n);
for (int i = 2; i < stop; i++)
{
if ((n % primes[i]) == 0)
return;
}
SavePrime(n);
}
///
/// Save a prime in the array. When a multiple of the page count is hit we
/// generate a HTML page with a 5000 cell table that has the same format as
/// Lehmer's table page.
///
private void SavePrime(int n)
{
if (count < total)
{
primes[count] = n;
++count;
if ((count > 0) && ((count % PrimesPerPage) == 0))
{
int pageNo = count / PrimesPerPage;
DisplayProgress(pageNo, n);
WritePageAsHtmlFile(pageNo);
}
}
}
private void DisplayProgress(int pageNo, int n)
{
double interval = 0.0;
DateTime newtime = DateTime.Now;
if (progressTime != DateTime.MinValue)
{
interval = newtime.Subtract(progressTime).TotalSeconds;
}
progressTime = newtime;
int len = (int)(10 * interval);
string bars = new string('*', len);
Console.WriteLine(" {0,3} {1,8} {2,8} {3,8} {4:0.000} {5}", pageNo, count, total, n, interval, bars);
}
private void WritePageAsHtmlFile(int pageNo)
{
string fname = string.Format(OutputFilePattern, pageNo);
writer = new StreamWriter(fname);
int ix1 = count - PrimesPerPage;
writer.WriteLine("");
writer.WriteLine("
");
// **** THE COLUMN COUNT ROW ****
writer.Write("
");
writer.Write("
");
for (int col = 0; col < columnsPerPage; col++)
{
writer.Write("
{0}
", col+1);
}
writer.WriteLine("
");
// **** THE 10,000 (TOP) PREFIX ROW ****
writer.Write("
");
writer.Write("
");
for (int col = 0; col < columnsPerPage; col++)
{
int t = primes[ix1 + col * RowsPerPage] / 10000;
string s = (t == 0 ? " " : t.ToString());
writer.Write("
{0}
", s);
}
writer.WriteLine("
");
// **** A TABLE ROW ****
for (int row=0; row");
writer.Write("
{0}
", row + 1);
for (int col = 0; col < columnsPerPage; col++)
{
int p = primes[ix1 + col*RowsPerPage + row];
if ((p >= 10000) && (row == 0))
{
writer.Write("
{0:0000}
", p % 10000);
}
else
{
writer.Write("
{0}
", p % 10000);
}
}
writer.WriteLine(" ");
}
// **** THE 10,000 (BOTTOM) PREFIX ROW ****
writer.Write("
");
writer.Write("
");
for (int col = 0; col < columnsPerPage; col++)
{
int t = primes[ix1 + col * RowsPerPage + RowsPerPage-1] / 10000;
string s = (t == 0 ? " " : t.ToString());
writer.Write("
{0}
", s);
}
writer.WriteLine("
");
writer.WriteLine("
");
writer.WriteLine("
{0}
", pageNo);
writer.WriteLine(" ");
writer.WriteLine("");
writer.Close();
}
///
/// Just a string of links I needed to put in the parent web page.
///
private void WriteLinks()
{
writer = new StreamWriter(@"links.txt");
for (int i = 0; i < pages; i++)
{
if (i > 0)
writer.Write(" ");
writer.Write("{0}", i + 1);
if ((i > 0) && ((i % 5) == 0))
{
writer.WriteLine("");
}
}
writer.Close();
}
}
}