Solution of the 8-Puzzle Using Java by James Pate Williams, Jr.

/*
	Author:	James Pate Williams, Jr.

	Solution of 8-puzzle using A* search
*/

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class Puzzle8Panel extends JPanel {
	char[] s;
	int deltaX, deltaY;
	int x0, x1, y0, y1;
	
	public Puzzle8Panel(int iWidth, int iHeight, char[] solution) {
		x0 = iWidth / 8;
		x1 = 7 * x0;
		y0 = iHeight / 8;
		y1 = 7 * y0;
		deltaX = (x1 - x0) / 3;
		deltaY = (y1 - y0) / 3;
		s = new char[9];
		s = solution;
	}
	
	public void sevenSegmentDisplay(Graphics g, char digit,
		int x, int y, int xUnit, int yUnit) {
		int xInc = xUnit / 10;
		int yInc = yUnit / 10;
		int xPoint1 = x + xInc;
		int yPoint1 = y + yInc;
		int xPoint2 = x + xUnit - xInc;
		int yPoint2 = yPoint1;
		int xPoint3 = xPoint1;
		int yPoint3 = y + yUnit / 2;
		int xPoint4 = xPoint2;
		int yPoint4 = yPoint3;
		int xPoint5 = xPoint3;
		int yPoint5 = y + yUnit - yInc;
		int xPoint6 = xPoint4;
		int yPoint6 = yPoint5;

		g.setColor(Color.white);
		switch (digit) {
			case '0':
				g.drawLine(xPoint1, yPoint1, xPoint2, yPoint2);
				g.drawLine(xPoint2, yPoint2, xPoint6, yPoint6);
				g.drawLine(xPoint6, yPoint6, xPoint5, yPoint5);
				g.drawLine(xPoint5, yPoint5, xPoint1, yPoint1);
				break;
			case '1':
				g.drawLine(xPoint1, yPoint1, xPoint5, yPoint5);
				break;
			case '2':
				g.drawLine(xPoint1, yPoint1, xPoint2, yPoint2);
				g.drawLine(xPoint2, yPoint2, xPoint4, yPoint4);
				g.drawLine(xPoint4, yPoint4, xPoint3, yPoint3);
				g.drawLine(xPoint3, yPoint3, xPoint5, yPoint5);
				g.drawLine(xPoint5, yPoint5, xPoint6, yPoint6);
				break;
			case '3':
				g.drawLine(xPoint1, yPoint1, xPoint2, yPoint2);
				g.drawLine(xPoint2, yPoint2, xPoint4, yPoint4);
				g.drawLine(xPoint4, yPoint4, xPoint3, yPoint3);
				g.drawLine(xPoint4, yPoint4, xPoint6, yPoint6);
				g.drawLine(xPoint6, yPoint6, xPoint5, yPoint5);
				break;
			case '4':
				g.drawLine(xPoint1, yPoint1, xPoint3, yPoint3);
				g.drawLine(xPoint3, yPoint3, xPoint4, yPoint4);
				g.drawLine(xPoint4, yPoint4, xPoint2, yPoint2);
				g.drawLine(xPoint4, yPoint4, xPoint6, yPoint6);
				break;
			case '5':
				g.drawLine(xPoint1, yPoint1, xPoint2, yPoint2);
				g.drawLine(xPoint1, yPoint1, xPoint3, yPoint3);
				g.drawLine(xPoint3, yPoint3, xPoint4, yPoint4);
				g.drawLine(xPoint4, yPoint4, xPoint6, yPoint6);
				g.drawLine(xPoint6, yPoint6, xPoint5, yPoint5);
				break;
			case '6':
				g.drawLine(xPoint1, yPoint1, xPoint3, yPoint3);
				g.drawLine(xPoint3, yPoint3, xPoint4, yPoint4);
				g.drawLine(xPoint4, yPoint4, xPoint6, yPoint6);
				g.drawLine(xPoint6, yPoint6, xPoint5, yPoint5);
				g.drawLine(xPoint5, yPoint5, xPoint3, yPoint3);
				break;
			case '7':
				g.drawLine(xPoint1, yPoint1, xPoint2, yPoint2);
				g.drawLine(xPoint2, yPoint2, xPoint6, yPoint6);
				break;
			case '8':
				g.drawLine(xPoint1, yPoint1, xPoint2, yPoint2);
				g.drawLine(xPoint2, yPoint2, xPoint6, yPoint6);
				g.drawLine(xPoint6, yPoint6, xPoint5, yPoint5);
				g.drawLine(xPoint5, yPoint5, xPoint1, yPoint1);
				g.drawLine(xPoint3, yPoint3, xPoint4, yPoint4);
				break;
			case '9':
				g.drawLine(xPoint1, yPoint1, xPoint2, yPoint2);
				g.drawLine(xPoint2, yPoint2, xPoint6, yPoint6);
				g.drawLine(xPoint1, yPoint1, xPoint3, yPoint3);
				g.drawLine(xPoint3, yPoint3, xPoint4, yPoint4);
				break;
		}
	}		
				  
	public void paintComponent(Graphics g) {
		int i, j, x, y;
  		int xUnit = deltaY / 9;
  		int yUnit = deltaY / 15;
		
		super.paintComponent(g);
		y = y0;
		for (i = 0; i < 3; i++) {
			x = x0;
			for (j = 0; j < 3; j++) {
				g.setColor(Color.white);
				g.drawRect(x, y, deltaX, deltaY);
				g.setColor(Color.black);
				g.fillRect(x, y, deltaX, deltaY);
				sevenSegmentDisplay(g, s[3 * i + j], x, y, deltaX, deltaY);
				x += deltaX;
			}
			y += deltaY;
		}		
	}

	public void setSolution(char[] solution) {
		s = new char[9];
		s = solution;
	}
}

class Puzzle8Frame extends JFrame implements Runnable {
	boolean next;
	int iHeight, iWidth;
	JButton jButton1 = new JButton();
	JPanel jPanel = new JPanel();
	BorderLayout borderLayout = new BorderLayout();
	Puzzle8Panel puzzle8Panel;
	
	// step 3 - percentage size the window
	void setDesktopSize(JFrame frame, int wPerc, int hPerc) {
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		iWidth = screen.width * wPerc / 100;
		iHeight = screen.height * hPerc / 100;
		frame.setSize(iWidth, iHeight);
	}
	
	// step 4 - center the window
	void centerOnScreen(JFrame frame) {
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension window = frame.getSize();
		int iCenterX = screen.width / 2;
		int iCenterY = screen.height / 2;
		frame.setLocation(iCenterX - window.width / 2, iCenterY - window.height / 2);
	}
	
	public Puzzle8Frame(char[] solution) {
		String title = "Puzzle8 by James Pate Williams, Jr. (c) 2001";
		next = false;
		jButton1.setToolTipText("Perform one iteration of algorithm");
		jButton1.setText("Next");
		jButton1.setVerticalAlignment(SwingConstants.BOTTOM);
		jButton1.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(ActionEvent e) {
				jButton1_actionPerformed(e);
			}
    		});
    		this.getContentPane().setLayout(borderLayout);
		setTitle(title);
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent event) {
				System.exit(0);
			}
		});
		setDesktopSize(this, 100, 100);
		centerOnScreen(this);
		Container contentPane = getContentPane();
		contentPane.add(jPanel, BorderLayout.SOUTH);
		jPanel.add(jButton1, BorderLayout.CENTER);
		puzzle8Panel = new Puzzle8Panel(iWidth, iHeight, solution);
		contentPane.add(puzzle8Panel, BorderLayout.CENTER);
		this.show();
		(new Thread(this)).run();
	}

	public boolean getNext() {
		return next;
	}

	public void setNext(boolean n) {
		next = n;
	}

	void jButton1_actionPerformed(ActionEvent e) {
		next = true;
	}
	
	public void run() {
		Thread.yield();
	}

	public void draw(char[] solution) {
		puzzle8Panel.setSolution(solution);
		puzzle8Panel.paintComponent(getGraphics());
	}
}

class Puzzle {
	int g, nodesExpanded;
	int[][] board;
	Date date;
	Random random;
	public static final int MaxMoves = 100;

	public Puzzle() {
		boolean found;
		int digit, i, j, k;
		int[] placed = new int[9];
		
		date = new Date();
		random = new Random(date.getTime());
		for (i = 0; i < 9; i++)
			placed[i] = 0;
		board = new int[3][3];
		g = nodesExpanded = 0;
		for (i = 0; i < 3; i++)
			for (j = 0; j < 3; j++)
				board[i][j] = 0;
		for (i = 0; i < 9; i++) {
			found = false;
			do {
				digit = random.nextInt(9);
				found = placed[digit] == 0;
				if (found)
					placed[digit] = 1;
			} while (!found);
			do {
				j = random.nextInt(3);
				k = random.nextInt(3);
				found = board[j][k] == 0;
				if (found)
					board[j][k] = digit;
			} while (!found);
		}
	}

	int getNodesExpanded() {
		return nodesExpanded;
	}

	int expand(int[][] square, int[][][] tempSquare) {
		int b = - 1, col = - 1, i, j, k, row = - 1;

		for (i = 0; i < 4; i++)
			for (j = 0; j < 3; j++)
				for (k = 0; k < 3; k++)
					tempSquare[i][j][k] = square[j][k];
		for (i = 0; i < 3; i++) {
			for (j = 0; j < 3; j++) {
				if (square[i][j] == 0) {
					row = i;
					col = j;
					break;
				}
			}
		}
		if (row == 0 && col == 0) {
			tempSquare[0][0][0] = tempSquare[0][0][1];
			tempSquare[0][0][1] = 0;
			tempSquare[1][0][0] = tempSquare[1][1][0];
			tempSquare[1][1][0] = 0;
			b = 2;
		}
		else if (row == 0 && col == 1) {
			tempSquare[0][0][1] = tempSquare[0][0][0];
			tempSquare[0][0][0] = 0;
			tempSquare[1][0][1] = tempSquare[1][1][1];
			tempSquare[1][1][1] = 0;
			tempSquare[2][0][1] = tempSquare[2][0][2];
			tempSquare[2][0][2] = 0;
			b = 3;
		}
		else if (row == 0 && col == 2) {
			tempSquare[0][0][2] = tempSquare[0][0][1];
			tempSquare[0][0][1] = 0;
			tempSquare[1][0][2] = tempSquare[1][1][2];
			tempSquare[1][1][2] = 0;
			b = 2;
		}
		else if (row == 1 && col == 0) {
			tempSquare[0][1][0] = tempSquare[0][0][0];
			tempSquare[0][0][0] = 0;
			tempSquare[1][1][0] = tempSquare[1][1][1];
			tempSquare[1][1][1] = 0;
			tempSquare[2][1][0] = tempSquare[2][2][0];
			tempSquare[2][2][0] = 0;
			b = 3;
		}
		else if (row == 1 && col == 1) {
			tempSquare[0][1][1] = tempSquare[0][1][0];
			tempSquare[0][1][0] = 0;
			tempSquare[1][1][1] = tempSquare[1][0][1];
			tempSquare[1][0][1] = 0;
			tempSquare[2][1][1] = tempSquare[2][1][2];
			tempSquare[2][1][2] = 0;
			tempSquare[3][1][1] = tempSquare[3][2][1];
			tempSquare[3][2][1] = 0;
			b = 4;
		}
		else if (row == 1 && col == 2) {
			tempSquare[0][1][2] = tempSquare[0][0][2];
			tempSquare[0][0][2] = 0;
			tempSquare[1][1][2] = tempSquare[1][1][1];
			tempSquare[1][1][1] = 0;
			tempSquare[2][1][2] = tempSquare[2][2][2];
			tempSquare[2][2][2] = 0;
			b = 3;
		}
		else if (row == 2 && col == 0) {
			tempSquare[0][2][0] = tempSquare[0][1][0];
			tempSquare[0][1][0] = 0;
			tempSquare[1][2][0] = tempSquare[1][2][1];
			tempSquare[1][2][1] = 0;
			b = 2;
		}
		else if (row == 2 && col == 1) {
			tempSquare[0][2][1] = tempSquare[0][2][0];
			tempSquare[0][2][0] = 0;
			tempSquare[1][2][1] = tempSquare[1][1][1];
			tempSquare[1][1][1] = 0;
			tempSquare[2][2][1] = tempSquare[2][2][2];
			tempSquare[2][2][2] = 0;
			b = 3;
		}
		else if (row == 2 && col == 2) {
			tempSquare[0][2][2] = tempSquare[0][2][1];
			tempSquare[0][2][1] = 0;
			tempSquare[1][2][2] = tempSquare[1][1][2];
			tempSquare[1][1][2] = 0;
			b = 2;
		}
		return b;
	}

	int heuristic(int[][] square) {
		return ManhattenDistance(square);
	}

	boolean move() {
		int b, count, i, j, k, min;
		int[] f = new int[4], index = new int[4];
		int[][][] tempSquare = new int[4][3][3];

		if (board[0][0] == 1 && board[0][1] == 2 && board[0][2] == 3 &&
			board[1][0] == 8 && board[1][1] == 0 && board[1][2] == 4 &&
			board[2][0] == 7 && board[2][1] == 6 && board[2][2] == 5)
			return true;
		b = expand(board, tempSquare);
		for (i = 0; i < b; i++) {
			f[i] = g + heuristic(tempSquare[i]);
			for (j = 0; j < 3; j++)
				for (k = 0; k < 3; k++)
					board[j][k] = tempSquare[i][j][k];
		}
		// find the node of minimum f
		min = f[0];
		for (i = 1; i < b; i++)
			if (f[i] < min)
				min = f[i];
		for (count = i = 0; i < b; i++)
			if (f[i] == min)
				index[count++] = i;
		i = index[random.nextInt(count)];
		// increment the cost of the path thus far
		g++;
		nodesExpanded += b;
		for (j = 0; j < 3; j++)
			for (k = 0; k < 3; k++)
				board[j][k] = tempSquare[i][j][k];
		return false;
	}

	int outOfPlace(int[][] square) {
		int i, j, oop = 0;
		int[][] goal = new int[3][3];
		
		goal[0][0] = 1;
		goal[0][1] = 2;
		goal[0][2] = 3;
		goal[1][0] = 8;
		goal[1][1] = 0;
		goal[1][2] = 4;
		goal[2][0] = 7;
		goal[2][1] = 6;
		goal[2][2] = 5;
		for (i = 0; i < 3; i++)
			for (j = 0; j < 3; j++)
				if (square[i][j] != goal[i][j])
					oop++;
		return oop;
	}

	int ManhattenDistance(int[][] square) {
		// city block or Manhatten distance heuristic
		int md = 0;

		if (square[0][0] == 1)
			md += 0;
		else if (square[0][0] == 2)
			md += 1;
		else if (square[0][0] == 3)
			md += 2;
		else if (square[0][0] == 4)
			md += 3;
		else if (square[0][0] == 5)
			md += 4;
		else if (square[0][0] == 6)
			md += 3;
		else if (square[0][0] == 7)
			md += 2;
		else if (square[0][0] == 8)
			md += 1;
		if (square[0][1] == 1)
			md += 1;
		else if (square[0][1] == 2)
			md += 0;
		else if (square[0][1] == 3)
			md += 1;
		else if (square[0][1] == 4)
			md += 2;
		else if (square[0][1] == 5)
			md += 3;
		else if (square[0][1] == 6)
			md += 2;
		else if (square[0][1] == 7)
			md += 3;
		else if (square[0][1] == 8)
			md += 2;
		if (square[0][2] == 1)
			md += 2;
		else if (square[0][2] == 2)
			md += 1;
		else if (square[0][2] == 3)
			md += 0;
		else if (square[0][2] == 4)
			md += 1;
		else if (square[0][2] == 5)
			md += 2;
		else if (square[0][2] == 6)
			md += 3;
		else if (square[0][2] == 7)
			md += 4;
		else if (square[0][2] == 8)
			md += 3;
		if (square[1][0] == 1)
			md += 1;
		else if (square[1][0] == 2)
			md += 2;
		else if (square[1][0] == 3)
			md += 3;
		else if (square[1][0] == 4)
			md += 2;
		else if (square[1][0] == 5)
			md += 3;
		else if (square[1][0] == 6)
			md += 2;
		else if (square[1][0] == 7)
			md += 1;
		else if (square[1][0] == 8)
			md += 0;
		if (square[1][1] == 1)
			md += 2;
		else if (square[1][1] == 2)
			md += 1;
		else if (square[1][1] == 3)
			md += 2;
		else if (square[1][1] == 4)
			md += 1;
		else if (square[1][1] == 5)
			md += 2;
		else if (square[1][1] == 6)
			md += 1;
		else if (square[1][1] == 7)
			md += 2;
		else if (square[1][1] == 8)
			md += 1;
		if (square[1][2] == 1)
			md += 3;
		else if (square[1][2] == 2)
			md += 2;
		else if (square[1][2] == 3)
			md += 1;
		else if (square[1][2] == 4)
			md += 0;
		else if (square[1][2] == 5)
			md += 1;
		else if (square[1][2] == 6)
			md += 2;
		else if (square[1][2] == 7)
			md += 3;
		else if (square[1][2] == 8)
			md += 2;
		if (square[2][0] == 1)
			md += 2;
		else if (square[2][0] == 2)
			md += 3;
		else if (square[2][0] == 3)
			md += 4;
		else if (square[2][0] == 4)
			md += 3;
		else if (square[2][0] == 5)
			md += 2;
		else if (square[2][0] == 6)
			md += 1;
		else if (square[2][0] == 7)
			md += 0;
		else if (square[2][0] == 8)
			md += 1;
		if (square[2][1] == 1)
			md += 3;
		else if (square[2][1] == 2)
			md += 2;
		else if (square[2][1] == 3)
			md += 3;
		else if (square[2][1] == 4)
			md += 2;
		else if (square[2][1] == 5)
			md += 1;
		else if (square[2][1] == 6)
			md += 0;
		else if (square[2][1] == 7)
			md += 1;
		else if (square[2][1] == 8)
			md += 2;
		if (square[2][2] == 1)
			md += 4;
		else if (square[2][2] == 2)
			md += 3;
		else if (square[2][2] == 3)
			md += 2;
		else if (square[2][2] == 4)
			md += 1;
		else if (square[2][2] == 5)
			md += 0;
		else if (square[2][2] == 6)
			md += 1;
		else if (square[2][2] == 7)
			md += 2;
		else if (square[2][2] == 8)
			md += 3;
		return md;
	}

	int solve(char[][] solution) {
		boolean found;
		int i, j, k, m = 0;

		do {
			for (i = k = 0; i < 3; i++)
				for (j = 0; j < 3; j++)
					solution[m][k++] = (char) (board[i][j] + '0');
			found = move();
			m++;
		} while (!found && m < MaxMoves);
		for (i = k = 0; i < 3; i++)
			for (j = 0; j < 3; j++)
				solution[m][k++] = (char) (board[i][j] + '0');
		return m;
	}
}

class Puzzle8 implements Runnable {
	char[][] solution = null;
	int moves;
	
	public Puzzle8 () {
		solution = new char[Puzzle.MaxMoves + 1][9];
		do {
			Puzzle puzzle = new Puzzle();
			moves = puzzle.solve(solution);
		} while (moves == Puzzle.MaxMoves);
	}

	public void run() {
		Puzzle8Frame puzzle8Frame = new Puzzle8Frame(solution[0]);
		
		System.out.println("moves = " + moves);
		for (int i = 0; i < moves; i++) {
			while (!puzzle8Frame.getNext())
				Thread.yield();
			puzzle8Frame.setNext(false);
			puzzle8Frame.draw(solution[i]);
		}
		puzzle8Frame.draw(solution[moves]);
	}

	static void main(String[] arg) {
		(new Puzzle8()).run();
	}
}				
	

Plant Growth L-System in Java by James Pate Williams, Jr.

/*
	Author: James Pate Williams, Jr.

	Stochastic L-System to draw a plant. See "Simulating Plant Growth" by
	Marco Grubert, Crossroads, the ACM Student Magazine Issue 8.2, Winter
	2001, pages 20-27.
*/

import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import java.util.*;
import javax.swing.*;

class Cursor {
	private double factor, rTheta;
	private int height, theta, width, x, x0, y, y0;

	public Cursor() {
	}

	public Cursor(int w, int h) {
		width = w;
		height = h;
		factor = Math.PI / 180.0;
		theta = 270;
		rTheta = factor * theta;
		x0 = width / 2;
		y0 = height;
		x = 0;
		y = 0;
	}

	public Cursor(int iw, int ih, int iTheta, int ix, int iy) {
		width = iw;
		height = ih;
		theta = iTheta;
		factor = Math.PI / 180.0;
		rTheta = factor * theta;
		x0 = width / 2;
		y0 = height;
		x = ix;
		y = iy;
	}

	public void F(Graphics g, int n) {
		double nX = n * Math.cos(rTheta) + x, nY = n * Math.sin(rTheta) + y;
		int X = x, Y = y;

		x = (int) nX;
		y = (int) nY;
		g.drawLine(X + x0, Y + y0, x + x0, y + y0);
	}

	public void f(Graphics g, int n) {
		double nX = n * Math.cos(rTheta) + x, nY = n * Math.sin(rTheta) + y;

		x = (int) nX;
		y = (int) nY;
		g.translate(x + x0, y + y0);
	}

	public void plus(int alpha) {
		theta = (theta - alpha) % 360;
		if (theta < 0)
			theta += 360;
		rTheta = factor * theta;
	}
	
	public void minus(int alpha) {
		theta = (theta + alpha) % 360;
		if (theta < 0)
			theta += 360;
		rTheta = factor * theta;
	}

	public void exclamation() {
		theta = (theta + 180) % 360;
		if (theta < 0)
			theta += 360;
		rTheta = factor * theta;
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	public int getTheta() {
		return theta;
	}

	public int getX() {
		return x;
	}

	public int getY() {
		return y;
	}

	public int getX0() {
		return x0;
	}

	public int getY0() {
		return y0;
	}
}

class PlantPanel extends JPanel {
	int depth;
	Cursor cursor = null;
	Random random = null;

	public PlantPanel(int iDepth, int iWidth, int iHeight, int seed) {
		depth = iDepth;
		cursor = new Cursor(iWidth, iHeight);
		random = new Random(seed);
	}
	
	public void lSystem1(Graphics g, int d, int depth, int n, int width, int height, 
			    int theta, int x, int y) {
		int alpha = 20;
		Cursor cursor = new Cursor(width, height, theta, x, y);
		Cursor stackCursor = null;

		if (d == depth)
			return;
		cursor.F(g, n);
		theta = cursor.getTheta();
		x = cursor.getX();
		y = cursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
		stackCursor = new Cursor(cursor.getWidth(), cursor.getHeight(),
			cursor.getTheta(), cursor.getX(), cursor.getY());
		stackCursor.plus(alpha);
		stackCursor.F(g, n);
		theta = stackCursor.getTheta();
		x = stackCursor.getX();
		y = stackCursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
		cursor.F(g, n);
		theta = cursor.getTheta();
		x = cursor.getX();
		y = cursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
		stackCursor = new Cursor(cursor.getWidth(), cursor.getHeight(),
			cursor.getTheta(), cursor.getX(), cursor.getY());
		stackCursor.minus(alpha);
		stackCursor.F(g, n);
		theta = stackCursor.getTheta();
		x = stackCursor.getX();
		y = stackCursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
		cursor.F(g, n);
		theta = cursor.getTheta();
		x = cursor.getX();
		y = cursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
	}

	public void lSystem2(Graphics g, int d, int depth, int n, int width, int height, 
			    int theta, int x, int y) {
		int alpha = 20;
		Cursor cursor = new Cursor(width, height, theta, x, y);
		Cursor stackCursor = null;

		if (d == depth)
			return;
		cursor.F(g, n);
		theta = cursor.getTheta();
		x = cursor.getX();
		y = cursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
		stackCursor = new Cursor(cursor.getWidth(), cursor.getHeight(),
			cursor.getTheta(), cursor.getX(), cursor.getY());
		stackCursor.plus(alpha);
		stackCursor.F(g, n);
		theta = stackCursor.getTheta();
		x = stackCursor.getX();
		y = stackCursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
		cursor.F(g, n);
		theta = cursor.getTheta();
		x = cursor.getX();
		y = cursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
	}

	public void lSystem3(Graphics g, int d, int depth, int n, int width, int height, 
			    int theta, int x, int y) {
		int alpha = 20;
		Cursor cursor = new Cursor(width, height, theta, x, y);
		Cursor stackCursor = null;

		if (d == depth)
			return;
		cursor.F(g, n);
		theta = cursor.getTheta();
		x = cursor.getX();
		y = cursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
		stackCursor = new Cursor(cursor.getWidth(), cursor.getHeight(),
			cursor.getTheta(), cursor.getX(), cursor.getY());
		stackCursor.minus(alpha);
		stackCursor.F(g, n);
		theta = stackCursor.getTheta();
		x = stackCursor.getX();
		y = stackCursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
	}

	public void lSystem0(Graphics g, int d, int depth, int n, int width, int height, 
			    int theta, int x, int y) {
		double r = random.nextDouble();

		if (d == depth)
			return;
		if (r <= 0.33) 
			lSystem1(g, d, depth, n, width, height, theta, x, y);
		else if (r <= 0.66)
			lSystem2(g, d, depth, n, width, height, theta, x, y);
		else
			lSystem3(g, d, depth, n, width, height, theta, x, y);
		theta = cursor.getTheta();
		x = cursor.getX();
		y = cursor.getY();
		lSystem0(g, d + 1, depth, n / 2, width, height, theta, x, y);
	}

	public void lSystem(Graphics g, int d, int depth, int n, int width, int height, 
			    int theta, int x, int y) {
		lSystem0(g, d, depth, n, width, height, theta, x, y);
	}

	public void paintComponent(Graphics g) {
		int n = 120;
		int width = cursor.getWidth(), height = cursor.getHeight();
		int theta = cursor.getTheta(), x0 = cursor.getX0(), y0 = cursor.getY0();
		
		lSystem(g, 0, depth, n, width, height, theta, 0, 0);
	}
}

class PlantFrame extends JFrame {
	int iHeight, iWidth;
	PlantPanel plantPanel;
	
	// step 3 - percentage size the window
	void setDesktopSize(JFrame frame, int wPerc, int hPerc) {
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		iWidth = screen.width * wPerc / 100;
		iHeight = screen.height * hPerc / 100;
		frame.setSize(iWidth, iHeight);
	}
	
	// step 4 - center the window
	void centerOnScreen(JFrame frame) {
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension window = frame.getSize();
		int iCenterX = screen.width / 2;
		int iCenterY = screen.height / 2;
		frame.setLocation(iCenterX - window.width / 2, iCenterY - window.height / 2);
	}
	
	public PlantFrame(int depth, int seed) {
		String title = "Plant by James Pate Williams, Jr. (c) 2001";

		setTitle(title);
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent event) {
				System.exit(0);
			}
		});
		setDesktopSize(this, 100, 100);
		centerOnScreen(this);
		Container contentPane = getContentPane();
		plantPanel = new PlantPanel(depth, iWidth, iHeight, seed);
		contentPane.add(plantPanel, BorderLayout.CENTER);
		this.show();
	}
}

class Plant {
	public static void main(String[] args) {
		if (args.length != 2) {
			System.out.println("usage: java Plant depth seed");
			System.out.println("where 5 <= depth <= 8 and seed >= 1");
			System.exit(0);
		}
		int depth = (new Integer(args[0])). intValue();
		if (depth < 5 || depth > 8) {
			System.out.println("depth not in range 5 <= depth <= 8!");
			System.exit(0);
		}
		int seed = (new Integer(args[1])).intValue();
		if (seed < 1) {
			System.out.println("seed must be >= 1");
			System.exit(0);
		}
		PlantFrame plantFrame = new PlantFrame(depth, seed);
	}
}

Wallace and Freuder’s Min-Conflicts Hill Climber Solution of the N-Queens Problem

/*
	Author:	James Pate Williams, Jr. (c) 2000

	Min-conflicts hill-climbing applied to N-Queens problem.
	Wallace and Freuder's algorithm with an unbiased
	preprocessor.
*/

#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;

const bool Debug = true;
const int MaxRepairs = 1000000;

int conflicts(int a, int i, int n, vector<int> &Q) {
	int b, c = 0, j;

	for (j = 0; j < n; j++) {
		b = Q[j];
		if (i != j && a != - 1 && b != - 1) {
			if (a == b) c++;
			if (i - j == a - b || i - j == b - a) c++;
		}
	}
	return c;
}

int constraintsViolated(vector<int> &Q) {
	int a, b, c = 0, i, j, n;
	
	n = Q.size();
	for (i = 0; i < n; i++) {
		a = Q[i];
		for (j = 0; j < n; j++) {
			b = Q[j];
			if (i != j && a != - 1 && b != - 1) {
				if (a == b) c++;
				if (i - j == a - b || i - j == b - a) c++;
			}
		}
	}
	return c;
}

int mchcAlgorithm(int n, vector<int> &compoundLabel) {
	bool commit, firstLoop = true;
	double p = 0.1, r;
	int c, i, index, j, minConflict, v;
	int repairs = 0;
	vector<int> conflict, domain, position;

	// preprocessing
	for (i = 0; i < n; i++) {
		conflict.erase(conflict.begin(), conflict.end());
		for (j = 0; j < n; j++)
			domain.push_back(j);
		for (commit = false, j = 0; !commit && j < n; j++) {
			v = domain[rand() % domain.size()];
			vector<int>::iterator vIterator = find(domain.begin(), domain.end(), v);
			domain.erase(vIterator);
			compoundLabel[i] = v;
			c = conflicts(v, i, i, compoundLabel);
			conflict.push_back(c);
			if (c == 0) commit = true;
		}
		if (!commit) {
			minConflict = conflict[0];
			for (j = 1; j < n; j++)
				if (conflict[j] < minConflict) minConflict = conflict[j];
			position.erase(position.begin(), position.end());
			for (j = 0; j < n; j++)
				if (minConflict == conflict[j]) position.push_back(j);
			compoundLabel[i] = position[rand() % position.size()];	
		}
	}
	for (;;) {
		conflict.erase(conflict.begin(), conflict.end());
		for (i = 0, j = 0; i < n; i++) {
			c = conflicts(compoundLabel[i], i, n, compoundLabel);
			conflict.push_back(c);
			j += c;
		}
		if (firstLoop) {
			cout << "conflicts after preprocessor: " << j << endl;
			firstLoop = false;
		}
		if (j == 0) break;
		position.erase(position.begin(), position.end());
		for (i = 0; i < n; i++)
			if (conflict[i] >= 1) position.push_back(i);
		index = position[rand() % position.size()];
		r = (double) rand() / RAND_MAX;
		if (r <= p)
			compoundLabel[index] = rand() % n;
		else {
			for (i = 0; i < n; i++) {
				compoundLabel[index] = i;
				conflict[i] = conflicts(i, index, n, compoundLabel);
				repairs++;
				if (repairs == MaxRepairs) return repairs;
			}
			minConflict = conflict[0];
			for (i = 1; i < n; i++)
				if (conflict[i] < minConflict) minConflict = conflict[i];
			position.erase(position.begin(), position.end());
			for (i = 0; i < n; i++)
				if (minConflict == conflict[i]) position.push_back(i);
			compoundLabel[index] = position[rand() % position.size()];
		}
	}
	return repairs;
}

void printSolution(vector<int> &solution) {
	char hyphen[256];
	int column, i, i4, n = solution.size(), row;

	if (n <= 10) {
		for (i = 0; i < n; i++) {
			i4 = i * 4;
			hyphen[i4 + 0] = '-';
			hyphen[i4 + 1] = '-';
			hyphen[i4 + 2] = '-';
			hyphen[i4 + 3] = '-';
		}
		i4 = i * 4;
		hyphen[i4 + 0] = '-';
		hyphen[i4 + 1] = '\n';
		hyphen[i4 + 2] = '\0';
		for (row = 0; row < n; row++) {
			column = solution[row];
			cout << hyphen;
			for (i = 0; i < column; i++)
				cout << "|   ";
			cout << "| Q ";
			for (i = column + 1; i < n; i++)
				cout << "|   ";
			cout << '|' << endl;
		}
		cout << hyphen;
	}
	else
		for (row = 0; row < n; row++)
			cout << row << ' ' << solution[row] << endl;
}

int main(int argc, char *argv[]) {
	if (argc != 2) {
		cout << "usage: " << argv[0] << " numberOfQueens" << endl;
		exit(1);
	}
	int n = atoi(argv[1]), repairs;
	double seconds;
	clock_t time0, time1;
	vector<int> solution(n, - 1);
	srand(time(NULL));
	time0 = clock();
	repairs = mchcAlgorithm(n, solution);
	time1 = clock();
	time1 -= time0;
	seconds = (double) time1 / CLOCKS_PER_SEC;
	if (Debug) printSolution(solution);
	cout << "Repairs: " << repairs << endl;
	cout << "seconds: " << seconds << endl;
	return 0;
}			
		

Brute Force Solution of the N-Queens Problem by James Pate Williams, Jr.

/*
*  NQueensBruteForce.cpp
*  NQueensBruteForce
*
*	Brute force determination of the total number of
*	solutions of the n-queens constraint satisfaction
*	problem (CSP). Order n! complexity algorithm.
*
*  Created by James Pate Williams, Jr. on 12/10/07.
*  Copyright 2007. All rights reserved.
*
*/

#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

int ConstraintViolations(std::vector<int> &Q, int &cvCount) {
	int a, b, cv = 0, i, j, n;

	n = Q.size();

	for (i = 0; i < n; i++) {

		a = Q[i];

		for (j = 0; j < n; j++) {
			b = Q[j];

			if (i != j && a != -1 && b != -1) {

				if (a == b)
					cv++;

				if (i - j == a - b || i - j == b - a)
					cv++;
			}
		}
	}

	cvCount++;
	return cv;
}

void PrintSolution(std::vector<int> &solution) {
	char hyphen[256];
	int column, i, i4, n = solution.size(), row;

	if (n <= 10) {
		for (i = 0; i < n; i++) {
			i4 = i * 4;
			hyphen[i4 + 0] = '-';
			hyphen[i4 + 1] = '-';
			hyphen[i4 + 2] = '-';
			hyphen[i4 + 3] = '-';
		}
		i4 = i * 4;
		hyphen[i4 + 0] = '-';
		hyphen[i4 + 1] = '\n';
		hyphen[i4 + 2] = '\0';
		for (row = 0; row < n; row++) {
			column = solution[row];
			std::cout << hyphen;
			for (i = 0; i < column; i++)
				std::cout << "|   ";
			std::cout << "| Q ";
			for (i = column + 1; i < n; i++)
				std::cout << "|   ";
			std::cout << '|' << std::endl;
		}
		std::cout << hyphen;
	}
	else
		for (row = 0; row < n; row++)
			std::cout << row << ' ' << solution[row] << std::endl;
}

int main(int argc, char * const argv[])
{
	if (argc != 3) {
		std::cout << "usage: " << argv[0] << " numberOfQueens print";
		std::cout << std::endl;
		exit(-1);
	}

	int numberOfQueens = atoi(argv[1]);

	if (numberOfQueens <= 0) {
		std::cout << "numberOfQueens must be positive" << std::endl;
		exit(-1);
	}

	int count = 0, i, cvCount = 0, print = atoi(argv[2]), space = 0;
	clock_t clock0;
	std::vector<int> queenVector;

	clock0 = clock();
	for (i = 0; i < numberOfQueens; i++)
		queenVector.push_back(i);

	do {

		int cv = ConstraintViolations(queenVector, cvCount);

		if (cv == 0) {
			count++;

			if (print == 1) {
				PrintSolution(queenVector);
				std::cout << std::endl;
			}
		}
		space++;
	} while (std::next_permutation(
		queenVector.begin(),
		queenVector.end(),
		std::less<int>()));

	double seconds = (double)(clock() - clock0) / CLOCKS_PER_SEC;

	std::cout << "search space size     = " << space << std::endl;
	std::cout << "number of con checks  = " << cvCount << std::endl;
	std::cout << "number of solutions   = " << count << std::endl;
	std::cout << "total time (seconds)  = " << seconds << std::endl;
	return 0;
}
N-Queens Problem for Four Queens 4! = 24 Search Space

Latest Sorting C++ Code

#pragma once
// Insertion sort, heap sort, and quick sort algorithms
// From "Algortihms" by Thomas H. Cormen, et. al.
// Selection sort, Singleton's sort, and Tree Sort 3, etc.
// From "Sorting and Sort Systems" by Harold Lorin
class Sorting {
public:
	// Translated from Lorin's PL/I procedure
	static void BasicExchange(long long tosort[], int number);
	// Translated from Lorin's PL/I procedure
	static void StandardExchange(long long tosort[], int number);
	static void InsertionSort(long long a[], int n);
	static void SelectionSort(long long a[], int n);
	// CACM Algorithm 175
	static void SimpleShifting(long long tosort[], int number);
	// CACM Algorithm 201 1963
	static void ShellSort(long long tosort[], int number);
	static void HeapSort(long long a[], int n);
	static void QuickSort(long long a[], int n);
	// CACM Algorithm 347 Ricahrd C. Singleton 1968
	// Translated from Lorin's PL/I procedure
	static void SingletonsSort(long long a[], int n);
	// CACM Algorithm 245 Robert W. Floyd 1964
	// Translated from Lorin's PL/I procedure
	static void TreeSort3(long long a[], int n);
	// see "Algortihms" by Thomas H. Cormen, et. al.
	// A is the array to be sorted, B is the sorted
	// array and k is maximum number in A
	static void CountingSort(
		long long A[],
		long long B[],
		long long C[],
		int n, long long k);
private:
	// five helper methods for Heap Sort
	static int Parent(int i);
	static int Left(int i);
	static int Right(int i);
	static void BuildHeap(long long a[], int n, int& heapSize);
	static void Heapify(long long a[], int i, int n, int& heapSize);
	/* helper functions for SETHEAP
	static void SWOPHEAP(long long A[], int n, long long& in, long long& out);
	static void INHEAP(long long A[], int& n, long long& in);
	static void OUTHEAP(long long A[], int& n, long long& out);
	static void SETHEAP(long long A[], int n);*/
	// helper methods for Quick Sort
	static int Partition(long long a[], int n, int lo, int hi);
	static void DoQuickSort(long long a[], int n, int p, int r);
	// helper function for Singleton's sort
	static void DoSingletonsSort(long long a[], int ii, int jj);
	// helper function for TreeSort3
	static void SiftUp(long long a[], int i, int n);
};
#include "Sorting.h"
#include <math.h>

void Sorting::BasicExchange(long long tosort[], int number)
{
    int adjust = 2 * (number / 2);
    int elimit, olimit;

    if (adjust < number)
    {
        elimit = adjust;
        olimit = adjust - 1;
    }
    else
    {
        elimit = number - 2;
        olimit = number - 1;
    }
odd:
    int passw = 1;
    int limit = olimit;
    int oddeve = 1;
pass:
    int excount = 0;

    for (int i = oddeve; i <= limit; i += 2)
    {
        if (tosort[i] > tosort[i + 1])
        {
            long long temp = tosort[i];

            tosort[i] = tosort[i + 1];
            tosort[i + 1] = temp;
            excount = 1;
        }
    }
    if (excount == 0)
        return;

    if (passw == 1)
    {
        passw = 0;
        oddeve = 0;
        limit = elimit;
        goto pass;
    }

    goto odd;
}

void Sorting::StandardExchange(long long tosort[], int number)
{
pass:
    int excount = 0;

    for (int i = 0; i < number - 1; i++)
    {
        if (tosort[i] > tosort[i + 1])
        {
            long long temp = tosort[i];

            tosort[i] = tosort[i + 1];
            tosort[i + 1] = temp;
            excount = 1;
        }
    }
    if (excount == 0)
        return;
    goto pass;
}

void Sorting::InsertionSort(long long a[], int n)
{
    for (int j = 1; j < n; j++)
    {
        long long key = a[j];
        int i = j - 1;

        while (i >= 0 && a[i] > key)
        {
            a[i + 1] = a[i];
            i--;
        }

        a[i + 1] = key;
    }
}

void Sorting::SelectionSort(long long a[], int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (a[i] > a[j])
            {
                long long t = a[i];

                a[i] = a[j];
                a[j] = t;
            }
        }
    }
}

void Sorting::SimpleShifting(long long tosort[], int number)
{
    for (int i = 0; i < number - 1; i++)
    {
        for (int j = i; j >= 0; j--)
        {
            if (tosort[j] > tosort[j + 1])
            {
                long long temp = tosort[j];

                tosort[j] = tosort[j + 1];
                tosort[j + 1] = temp;
            }
        }
    }
}

void Sorting::ShellSort(long long tosort[], int number)
{
    int lognumber = log2(number);
    int distance = (int)pow(2, lognumber) - 1;

    while (distance > 0)
    {
        int limit = number - distance;

        for (int j = 0; j < limit; j++)
        {
            for (int i = j; i >= 0; i--)
            {
                if (tosort[i + distance] < tosort[i])
                {
                    long long temp = tosort[i];

                    tosort[i] = tosort[i + distance];
                    tosort[i + distance] = temp;
                }
            }
        }

        distance /= 2;
    }
}

int Sorting::Parent(int i)
{
    return i / 2;
}

int Sorting::Left(int i)
{
    return 2 * i;
}

int Sorting::Right(int i) 
{
    return 2 * i + 1;
}

void Sorting::Heapify(long long a[], int i, int n, int& heapSize)
{
    int l = Left(i);
    int r = Right(i);
    int largest = -1;

    if (l < heapSize && a[l] > a[i])
        largest = l;
    else
        largest = i;

    if (r < heapSize && a[r] > a[largest])
        largest = r;

    if (largest != i)
    {
        long long t = a[i];

        a[i] = a[largest];
        a[largest] = t;

        Heapify(a, largest, n, heapSize);
    }
}

void Sorting::BuildHeap(long long a[], int n, int& heapSize)
{
    for (int i = n / 2; i >= 0; i--)
        Heapify(a, i, n, heapSize);
}

void Sorting::HeapSort(long long a[], int n)
{
    int heapSize = n;

    BuildHeap(a, n, heapSize);

    for (int i = n - 1; i >= 0; i--)
    {
        long long t = a[0];

        a[0] = a[i];
        a[i] = t;

        heapSize--;

        Heapify(a, 0, n, heapSize);
    }
}

void SWOPHEAP(long long A[], int n,
    long long& in, long long& out)
{
    if (in <= A[0])
        out = in;
    else
    {
        int i = 0;
        A[n] = in;
        out = A[0];
    scan:
        int j = i + i;
        if (j <= n - 1)
        {
            long long temp = A[j];
            long long temp1 = A[j + 1];
            if (temp1 < temp)
            {
                temp = temp1;
                j++;
            }
            if (temp < in)
            {
                A[i] = temp;
                i = j;
                goto scan;
            }
        }
        A[i] = in;
    }
}

void INHEAP(long long A[], int& n, long long& in)
{
    int i = n;
    n++;
scan:
    if (i > 0)
    {
        int j = i / 2;
        if (in < A[j])
        {
            A[i] = A[j];
            i = j;
            goto scan;
        }
    }
    A[i] = in;
}

void OUTHEAP(long long A[], int& n, long long& out)
{
    SWOPHEAP(A, n - 1, A[n - 1], out);
    n = n - 2;
}

void SETHEAP(long long A[], int n)
{
    int j = 0;
L:
    INHEAP(A, j, A[j + 1]);

    if (j < n - 2)
        goto L;
}

void HEAP(long long A[], int n)
{
    SETHEAP(A, n);

    for (int i = n - 1; i >= 1; i--)
        OUTHEAP(A, i, A[i]);
}

int Sorting::Partition(long long a[], int n, int lo, int hi)
{
    int pivotIndex = lo + (hi - lo) / 2;
    long long x = a[pivotIndex];
    long long t = x;

    a[pivotIndex] = a[hi];
    a[hi] = t;

    int storeIndex = lo;

    for (int i = lo; i < hi; i++)
    {
        if (a[i] < x)
        {
            t = a[i];
            a[i] = a[storeIndex];
            a[storeIndex++] = t;
        }
    }

    t = a[storeIndex];
    a[storeIndex] = a[hi];
    a[hi] = t;

    return storeIndex;
}

void Sorting::DoQuickSort(long long a[], int n, int p, int r)
{
    if (p < r)
    {
        int q = Partition(a, n, p, r);

        DoQuickSort(a, n, p, q - 1);
        DoQuickSort(a, n, q + 1, r);
    }
}

void Sorting::QuickSort(long long a[], int n)
{
    DoQuickSort(a, n, 0, n - 1);
}

void QuickerSort(long long tosort[], int number)
{
    const int limit = 20;
    int highlim = 0, lowlim, origin, partind, pivot;
    long long exch, temp = 0;
    int partablow[limit] = { 0 }, parttabhigh[limit] = { 0 };
    origin = partind = 0;
testsize:
    if (number - 1 - origin > 0)
    {
        pivot = (number - 1 + origin) / 2;
        temp = tosort[pivot];
        tosort[pivot] = tosort[origin];
        highlim = number - 1;

        for (lowlim = origin + 1; lowlim <= highlim; lowlim++)
        {
            if (tosort[lowlim] > temp)
            {
                for (highlim = highlim; highlim >= lowlim; highlim--)
                {
                    if (tosort[highlim] < temp)
                    {
                        exch = tosort[lowlim];
                        tosort[lowlim] = tosort[highlim];
                        tosort[highlim] = exch;
                        highlim = lowlim - 1;
                        goto limsmet;
                    }
                }
                highlim = lowlim - 1;
                goto limsmet;
            }
       }
    }
limsmet:
    tosort[origin] = tosort[highlim];
    tosort[highlim] = temp;
    if (2 * highlim > origin + number - 1)
    {
        partablow[partind] = origin;
        parttabhigh[partind] = highlim - 1;
        origin = highlim + 1;
    }
    else
    {
        partablow[partind] = highlim + 1;
        parttabhigh[partind] = number - 1;
        number = highlim - 1;
    }
    partind++;
    goto testsize;
    if (origin == number - 1)
        goto setpart;
    if (tosort[origin] > tosort[number - 1])
    {
        exch = tosort[origin];
        tosort[origin] = tosort[number - 1];
        tosort[number - 1] = exch;
    }
setpart:
    partind--;
    if (partind > -1)
    {
        origin = partablow[partind];
        number = parttabhigh[partind];
        goto testsize;
    }
}

void Sorting::DoSingletonsSort(long long a[], int ii, int jj)
{
    int m = 0;
    int i = ii;
    int j = jj;
    int iu[50] = { 0 };
    int il[50] = { 0 };
    int ij = 0, l = 1, k = 0;
    long long t = 0, tt = 0;
    Label1:
        if (i >= j)
            goto Label8;
        goto Label2;
    Label2:
        k = i;
        ij = (j + i) / 2;
        t = a[ij];
        if (a[i] <= t)
            goto Label3;
        a[ij] = a[i];
        a[i] = t;
        t = a[ij];
        goto Label3;
    Label3:
        l = j;
        if (a[j] >= t)
            goto Label5;
        a[ij] = a[j];
        a[j] = t;
        t = a[ij];
        if (a[i] <= t)
            goto Label5;
        a[ij] = a[i];
        a[i] = t;
        t = a[ij];
        goto Label5;
    Label4:
        a[l] = a[k];
        a[k] = tt;
        goto Label5;
    Label5:
        l--;
        if (a[l] > t)
            goto Label5;
        tt = a[l];
        goto Label6;
    Label6:
        k++;
        if (a[k] < t)
            goto Label6;
        if (k <= l)
            goto Label4;
        if (l - i <= j - k)
            goto Label7;
        il[m] = i;
        iu[m] = l;
        i = k;
        m++;
        goto Label9;
    Label7:
        il[m] = k;
        iu[m] = j;
        j = l;
        m++;
        goto Label9;
    Label8:
        m--;
        if (m == -1)
            return;
        i = il[m];
        j = iu[m];
        goto Label9;
    Label9:
        if (j - i > 10)
            goto Label2;
        if (i == ii)
            goto Label1;
        i--;
        goto Label10;
    Label10:
        i++;
        if (i == j)
            goto Label8;
        t = a[i + 1];
        if (a[i] <= t)
            goto Label10;
        k = i;
        goto Label11;
    Label11:
        a[k + 1] = a[k];
        k--;
        if (t < a[k])
            goto Label11;
        a[k + 1] = t;
        goto Label10;
}

void Sorting::SingletonsSort(long long a[], int n)
{
    DoSingletonsSort(a, 0, n - 1);
}

void Sorting::SiftUp(long long a[], int i, int n)
{
    long long copy = a[i];
    int j;

    while (true)
    {
        j = i + i;

        if (j <= n)
        {
            if (j < n)
            {
                if (a[j + 1] > a[j])
                    j++;
            }

            if (a[j] > copy)
            {
                a[i] = a[j];
                i = j;
                continue;
            }
        }

        break;
    }

    a[i] = copy;
}

void Sorting::TreeSort3(long long a[], int n)
{
    for (int i = n / 2; i >= 1; i--)
        SiftUp(a, i, n - 1);

    for (int i = n - 1; i >= 1; i--)
    {
        SiftUp(a, 0, i);

        long long t = a[0];

        a[0] = a[i];
        a[i] = t;
    }
}

void Sorting::CountingSort(
    long long A[],
    long long B[],
    long long C[],
    int n, long long k)
{
    for (long long i = 0; i <= k; i++)
        C[i] = 0;

    for (int j = 0; j < n; j++)
    {
        B[j] = 0;
        C[A[j]]++;
    }

    for (long long i = 1; i <= k; i++)
        C[i] += C[i - 1];

    for (int i = n - 1; i >= 0; i--)
    {
        long long j = A[i];

        C[j]--;
        B[C[j]] = A[i];
    }
}
#pragma once
#include <limits.h>
#include <vector>
using namespace std;

class SampleStatistics {
public:
	inline static long long Mean(vector<long long> x) {
		long long sum = 0;

		for (int i = 0; i < (int)x.size(); i++)
			sum += (long long)x[i];

		return sum / (int)x.size();
	};
	inline static long long Max(vector<long long> x)
	{
		long long max = LLONG_MIN;

		for (int i = 0; i < (int)x.size(); i++)
			if (x[i] > max)
				max = x[i];

		return max;
	};
	inline static long long Min(vector<long long> x)
	{
		long long min = LLONG_MAX;

		for (int i = 0; i < (int)x.size(); i++)
			if (x[i] < min)
				min = x[i];

		return min;
	};
	inline static long long Median(vector<long long> x)
	{
		unsigned int n0 = (unsigned int)x.size();
		unsigned int n1 = n0 / 2 - 1;
		unsigned int n2 = n0 / 2;
		long long median = 0, lt = x[n1], rt = x[n2];

		if ((n0 & 1) == 1)
			median = x[n0 / 2];
		else
			median = (lt + rt) / 2;

		return median;
	};
	inline static long long Variance(vector<long long> x)
	{
		long long mean = Mean(x), sumSq = 0;
		int n = (int)x.size();
		int n1 = n - 1;

		for (int i = 0; i < n; i++)
		{
			long long delta = x[i] - mean;

			sumSq += delta * delta;
		}

		return sumSq / n1;
	};
};
#include "SampleStatistics.h"
#include "Sorting.h"
#include <stdlib.h>
#include <algorithm>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std::chrono;
using namespace std;

// https://www.geeksforgeeks.org/measure-execution-time-function-cpp/

int GetSubOption(char title[])
{
	char line[128];
	cout << title << endl;
	cout << "1 Basic Exchange" << endl;
	cout << "2 Standard Exchange" << endl;
	cout << "3 Insertion Sort" << endl;
	cout << "4 Selection Sort" << endl;
	cout << "5 Simple Sifting (Shuttle Sort)" << endl;
	cout << "6 Shell Sort" << endl;
	cout << "7 Heap Sort" << endl;
	cout << "8 Quick Sort" << endl;
	cout << "9 Singleton's Sort" << endl;
	cout << "10 Tree Sort 3" << endl;
	cout << "11 Counting Sort" << endl;
	cout << "12 Exit Submenu" << endl;
	cout << "13 Exit Program" << endl;
	cout << "Suboption Number: ";
	cin.getline(line, 128);

	int so = 0;
	if (strlen(line) > 1)
	{
		so = 10 * (line[0] - '0');
		so += line[1] - '0';
	}

	else
		so = line[0] - '0';
	
	return so;
}

int DoSort(char option) {
	char line[128];
	char title[128] = { 0 };
	char name[11][64] = { { 0 } };
	int subOption;

	strcpy_s(name[0], 64, "Basic Exchange");
	strcpy_s(name[1], 64, "Standard Exchange");
	strcpy_s(name[2], 64, "Insertion Sort");
	strcat_s(name[3], 64, "Selection Sort");
	strcpy_s(name[4], 64, "Simple Shifting");
	strcpy_s(name[5], 64, "Shell Sort");
	strcat_s(name[6], 64, "Heap Sort");
	strcat_s(name[7], 64, "Quick Sort");
	strcat_s(name[8], 64, "Singleton's Sort");
	strcat_s(name[9], 64, "Tree Sort 3");
	strcpy_s(name[10], 64, "Counting Sort");

	vector<long long> runtime;
	
	if (option == '1')
	{
		strcpy_s(title, 128, "Single Sorting Tests Submenu");
	}
	else {
		strcpy_s(title, 128, "Statistical Sorting Tests Submenu");
	}

	subOption = GetSubOption(title);
	
	if (subOption < 1 || subOption > 13)
	{
		cout << "Illegal Suboption Exiting Application!" << endl;
		exit(-1);
	}

	if (subOption == 12)
		return subOption;
	
	if (subOption == 13)
		exit(1);

	int index = subOption - 1, maximum = 0, n = 0, seed = 1;

	cout << name[index] << endl;

	do {
		cout << "PRNG Seed             = ";
		cin.getline(line, 128);
		seed = atoi(line);
	} while (seed < 1);

	do {
		cout << "Number of Samples     = ";
		cin.getline(line, 128);
		n = atoi(line);
	} while (n < 2);

	do {
		cout << "Maximum Sample Value  = ";
		cin.getline(line, 128);
		maximum = atoi(line);
	} while (maximum < 10);

	srand(seed);

	int number = 0;
	
	if (option == '2')
	{
		do {
			cout << "Number of Experiments = ";
			cin.getline(line, 128);
			number = atoi(line);
		} while (number < 1);
	}

	else
	{
		number = 1;
	}
	
	long long k = 0;
	long long* B = new long long[n];
	long long* sample = new long long[n];
	long long* shadow = new long long[n];

	for (int i = 0; i < number; i++)
	{
		long long* C = NULL;

		for (int j = 0; j < n; j++)
		{
			sample[j] = rand() % maximum;

			if (option == '1') {
				shadow[j] = sample[j];
			}
		}

		if (subOption == 11)
		{
			for (int j = 0; j < n; j++)
				if (sample[j] > k)
					k = sample[j];

			C = new long long[(unsigned int)(k + 1)];
		}
		
		auto start = high_resolution_clock::now();

		switch (subOption) {
		case 1:
			Sorting::BasicExchange(sample, n);
			break;
		case 2:
			Sorting::StandardExchange(sample, n);
			break;
		case 3:
			Sorting::InsertionSort(sample, n);
			break;
		case 4:
			Sorting::SelectionSort(sample, n);
			break;
		case 5:
			Sorting::SimpleShifting(sample, n);
			break;
		case 6:
			Sorting::ShellSort(sample, n);
			break;
		case 7:
			Sorting::HeapSort(sample, n);
			break;
		case 8:
			Sorting::QuickSort(sample, n);
			break;
		case 9:
			Sorting::SingletonsSort(sample, n);
			break;
		case 10:
			Sorting::TreeSort3(sample, n);
			break;
		case 11:		
			Sorting::CountingSort(sample, B, C, n, k);
			break;
		default:
			cout << "Unknown Suboption" << endl;
			break;
		}

		auto stop = high_resolution_clock::now();
		auto duration = duration_cast<microseconds>(stop - start);
		long long rt = (long long)duration.count();

		runtime.push_back(rt);

		if (subOption == 11)
		{
			if (C != NULL)
				delete[] C;
		}
	}

	if (option == '1')
	{
		for (int i = 0; i < n; i++)
		{
			cout << setw(2) << shadow[i] << ' ';
			if (subOption != 11)
				cout << setw(2) << sample[i] << endl;
			else
				cout << setw(2) << B[i] << endl;
		}
	}
	
	else if (option == '2') {
		sort(runtime.begin(), runtime.end());

		cout << "Runtimes in Microseconds" << endl;

		if (runtime.size() <= 15)
		{
			for (int i = 0; i < (int)runtime.size(); i++)
				cout << setw(4) << runtime[i] << endl;
		}

		cout << "Minimum Runtime       = " 
			<< setw(4) << fixed << setprecision(0)
			<< SampleStatistics::Min(runtime) << endl;
		cout << "Maximum Runtime       = " 
			<< setw(4) << fixed << setprecision(0)
			<< SampleStatistics::Max(runtime) << endl;
		cout << "Mean Runtime          = " 
			<< setw(4) << fixed << setprecision(0)
			<< SampleStatistics::Mean(runtime) << endl;
		cout << "Median Runtime        = "
			<< setw(4) << fixed << setprecision(0) <<
			SampleStatistics::Median(runtime) << endl;
	}

	delete[] B;
	delete[] sample;
	delete[] shadow;
	
	return subOption;
}

int main() {
	while (true) {
		char line[128];

		cout << "Menu" << endl;
		cout << "1 Single Sorting Tests" << endl;
		cout << "2 Statistical Tests" << endl;
		cout << "3 Exit" << endl;;
		cout << "Option number: ";
		cin.getline(line, 128);

		if (line[0] == '3')
			break;

		if (line[0] == '1' || line[0] == '2') {
			while (true)
			{
				int doSort = DoSort(line[0]);

				if (doSort == 12)
					break;
				else if (doSort == 13)
					exit(1);
			}
		}
	}

	return 0;
}

New Sorting Results by James Pate Wiliams, Jr.

My sorting application now supports eleven sorting algorithms. Below are some results from ten of the methods.

Basic Exchange
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       = 134039
Maximum Runtime       = 143654
Mean Runtime          = 137164
Median Runtime        = 136788

Standard Exchange
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       = 318753
Maximum Runtime       = 389181
Mean Runtime          = 330273
Median Runtime        = 328034

Insertion Sort
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       = 48089
Maximum Runtime       = 54204
Mean Runtime          = 49308
Median Runtime        = 49116

Selection Sort
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       = 224979
Maximum Runtime       = 348275
Mean Runtime          = 233022
Median Runtime        = 229386

Simple Shifting
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       = 115351
Maximum Runtime       = 131739
Mean Runtime          = 117297
Median Runtime        = 116714

Heap Sort
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       = 2408
Maximum Runtime       = 2800
Mean Runtime          = 2477
Median Runtime        = 2454


Quick Sort
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       =  838
Maximum Runtime       = 1011
Mean Runtime          =  900
Median Runtime        =  893

Singleton's Sort
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       =  727
Maximum Runtime       =  849
Mean Runtime          =  761
Median Runtime        =  747

Counting Sort
PRNG Seed             = 1
Number of Samples     = 10000
Maximum Sample Value  = 10000
Number of Experiments = 100
Runtimes in Microseconds
Minimum Runtime       =   97
Maximum Runtime       =  122
Mean Runtime          =  103
Median Runtime        =  103

Hamiltonian Circuit (Cycle) by James Pate Williams, Jr.

namespace HamiltonianCircuit
{
    class Algorithm
    {
        // code from C/C++
        // http://www.geeksforgeeks.org/backtracking-set-7-hamiltonian-cycle/

        // A utility function to check if the vertex v can be added at
        // index 'pos' in the Hamiltonian Cycle constructed so far (stored
        // in 'path[]')

        private bool IsSafe(int v, bool[,] graph, int[] path, int pos)
        {
            /* Check if this vertex is an adjacent vertex of the previously
               added vertex. */
            if (!graph[path[pos - 1], v])
                return false;

            /* Check if the vertex has already been included.
              This step can be optimized by creating an array of size V */
            for (int i = 0; i < pos; i++)
                if (path[i] == v)
                    return false;

            return true;
        }

        /* A recursive utility function to solve hamiltonian cycle problem */
        private bool HamCycleUtil(bool[,] graph, int V, int[] path, int pos)
        {
            /* base case: If all vertices are included in Hamiltonian Cycle */
            if (pos == V)
            {
                // And if there is an edge from the last included vertex to the
                // first vertex
                if (graph[path[pos - 1], path[0]])
                    return true;
                else
                    return false;
            }

            // Try different vertices as a next candidate in Hamiltonian Cycle.
            // We don't try for 0 as we included 0 as starting point in in hamCycle()
            for (int v = 1; v < V; v++)
            {
                // Check if this vertex can be added to Hamiltonian Cycle

                if (IsSafe(v, graph, path, pos))
                {
                    path[pos] = v;

                    // recur to construct rest of the path

                    if (HamCycleUtil(graph, V, path, pos + 1))
                        return true;

                    // If adding vertex v doesn't lead to a solution,
                    // then remove it
                    path[pos] = -1;
                }
            }

            // If no vertex can be added to Hamiltonian Cycle constructed so far,
            // then return false
            return false;
        }

        // This function solves the Hamiltonian Cycle problem using Backtracking.
        // It mainly uses HamCycleUtil() to solve the problem. It returns false
        // if there is no Hamiltonian Cycle possible, otherwise return true and
        // prints the path. Please note that there may be more than one solutions,
        // this function prints one of the feasible solutions.
        public bool HamCycle(bool[,] graph, int V, out int[] path)
        {
            path = new int[V];

            for (int i = 0; i < V; i++)
                path[i] = -1;

           // Let us put vertex 0 as the first vertex in the path. If there is
           // a Hamiltonian Cycle, then the path can be started from any point
           // of the cycle as the graph is undirected

            path[0] = 0;

            if (HamCycleUtil(graph, V, path, 1) == false)
                return false;

            return true;
        }

    }
}
using System;
using System.Collections.Generic;

namespace HamiltonianCircuit
{
    class Edge : IComparable
    {
        public Vertex Lt { get; set; }
        public Vertex Rt { get; set; }
        public int Wt { get; set; }
        public Edge(Vertex lt, Vertex rt, int wt)
        {
            Lt = lt;
            Rt = rt;
            Wt = wt;
        }

        public int CompareTo(object obj)
        {
            Edge other = (Edge)obj;
            int c1 = Lt.CompareTo(other.Lt);
            int c2 = Rt.CompareTo(other.Rt);

            if (c1 != 0)
                return c1;

            if (c2 != 0)
                return c2;

            return Wt - other.Wt;
        }

        public bool InList(List<Edge> elist)
        {
            for (int i = 0; i < elist.Count; i++)
            {
                Edge e = elist[i];

                if (Lt == e.Lt && Rt == e.Rt)
                    return true;
            }

            return false;
        }
    }
}
using System;
using System.Collections.Generic;

namespace HamiltonianCircuit
{
    class Vertex : IComparable
    {
        public int Id { get; set; }
        public List<Edge> Edges { get; set; }
        public Vertex(int id)
        {
            Id = id;
        }

        public Vertex(int id, List<Edge> edges)
        {
            Id = id;
            Edges = edges;
        }

        public int CompareTo(object obj)
        {
            Vertex other = (Vertex)obj;

            return Id - other.Id;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace HamiltonianCircuit
{
    public partial class MainForm : Form
    {
        private bool generate = true;
        private int n, x, y, x1, y1, x2, y2;
        private Algorithm algo = new Algorithm();
        private Color[] colors =
            {
            Color.Red,
            Color.Blue,
            Color.Green,
            Color.Orange,
            Color.Purple,
            Color.Brown,
            Color.Turquoise,
            Color.Violet,
            Color.Tan,
            Color.Plum,
            Color.Teal,
            Color.Yellow
            };
        private List<Edge> E, F;
        private List<Vertex> V;
        private Random random = new Random();
        private SolidBrush drawBrush;
        private Font drawFont;
        public MainForm()
        {
            InitializeComponent();
            panel1.Paint += new PaintEventHandler(panel1_Paint);
            drawBrush = new SolidBrush(Color.White);
        }

        void panel1_Paint(object sender, PaintEventArgs e)
        {
            if (generate)
                GenerateDraw(e.Graphics);

            else
                PathDraw(e.Graphics);
        }

        private void calculateXY(int id)
        {
            int Width = panel1.Width;
            int Height = panel1.Height;

            x = Width / 2 + (int)(Width * Math.Cos(2 * id * Math.PI / n) / 4.0);
            y = Height / 2 + (int)(Width * Math.Sin(2 * id * Math.PI / n) / 4.0);
        }

        private void PathDraw(Graphics g)
        {
            if (V != null)
            {
                GenerateDraw(g);

                int divisor = 1;
                int Width = panel1.Width;
                int Height = panel1.Height;
                Pen pen = new Pen(Color.Red);

                n = V.Count;

                for (int i = 0; i < F.Count; i++)
                {
                    Vertex u = F[i].Lt, v = F[i].Rt;

                    calculateXY(u.Id);
                    x1 = x + (Width / 2) / n / 2;
                    y1 = y + (Width / 2) / n / 2;
                    calculateXY(v.Id);
                    x2 = x + (Width / 2) / n / 2;
                    y2 = y + (Width / 2) / n / 2;
                    g.DrawLine(pen, x1, y1, x2, y2);
                }

                if (n >= 4 && n <= 5)
                    divisor = 16;
                else if (n >= 6 && n <= 8)
                    divisor = 24;
                else if (n >= 9 && n <= 10)
                    divisor = 32;

                drawFont = new Font("Arial", Width / divisor);

                for (int i = 0; i < n; i++)
                {
                    Vertex u = V[i];
                    SolidBrush brush = new SolidBrush(colors[u.Id]);

                    calculateXY(u.Id);
                    g.FillEllipse(brush, x, y, (Width / 2) / n, (Width / 2) / n);

                    if (n >= 4 && n <= 10)
                        g.DrawString(i.ToString(), drawFont, drawBrush, x + 4, y + 4);
                }
            }
        }

        private void GenerateDraw(Graphics g)
        {
            if (V != null)
            {
                int divisor = 1;
                int Width = panel1.Width;
                int Height = panel1.Height;
                Pen pen = new Pen(Color.Black);

                n = V.Count;

                for (int i = 0; i < n; i++)
                {
                    Vertex u = V[i];

                    calculateXY(u.Id);
                    x1 = x + (Width / 2) / n / 2;
                    y1 = y + (Width / 2) / n / 2;

                    if (u.Edges != null)
                    {
                        for (int j = 0; j < u.Edges.Count; j++)
                        {
                            Vertex v = u.Edges[j].Rt;

                            calculateXY(v.Id);
                            x2 = x + (Width / 2) / n / 2;
                            y2 = y + (Width / 2) / n / 2;
                            g.DrawLine(pen, x1, y1, x2, y2);
                        }
                    }
                }

                if (n >= 4 && n <= 5)
                    divisor = 16;
                else if (n >= 6 && n <= 8)
                    divisor = 24;
                else if (n >= 9 && n <= 10)
                    divisor = 32;

                drawFont = new Font("Arial", Width / divisor);

                for (int i = 0; i < n; i++)
                {
                    Vertex u = V[i];
                    SolidBrush brush = new SolidBrush(colors[u.Id]);

                    calculateXY(u.Id);
                    g.FillEllipse(brush, x, y, (Width / 2) / n, (Width / 2) / n);
                    
                    if (n >= 4 && n <= 10)
                        g.DrawString(i.ToString(), drawFont, drawBrush, x + 4, y + 4);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            generate = true;
            button2.Enabled = true;

            int numVers = (int)numericUpDown1.Value;

            E = new List<Edge>();
            V = new List<Vertex>();

            for (int i = 0; i < numVers; i++)
            {
                Vertex v = new Vertex(i);

                v.Edges = new List<Edge>();
                V.Add(v);
            }

            for (int i = 0; i < numVers; i++)
            {
                int numEdges = random.Next(numVers - 1);

                while (numEdges < 2)
                    numEdges = random.Next(numVers - 1);

                Vertex v = V[i];

                for (int j = 0; j < numEdges; j++)
                {
                    int id = random.Next(numVers);
                    int wt = random.Next(100);
                    Edge edge;

                    while (wt < 10)
                        wt = random.Next(100);

                    while (id == v.Id)
                        id = random.Next(numVers);

                    edge = new Edge(v, V[id], wt);

                    if (!edge.InList(E))
                        E.Add(edge);

                    edge = new Edge(V[id], v, wt);

                    if (!edge.InList(E))
                        E.Add(edge);
                }
            }

            for (int i = 0; i < E.Count; i++)
            {
                Vertex u = E[i].Lt, v = E[i].Rt;

                u.Edges.Add(new Edge(u, v, E[i].Wt));
                v.Edges.Add(new Edge(v, u, E[i].Wt));
            }

            for (int i = 0; i < V.Count; i++)
            {
                if (V[i].Edges.Count == 0)
                {
                    MessageBox.Show("Generate a new graph", "Warning Message",
                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
            }

            textBox1.Text = string.Empty;
            textBox1.Text = "Edges(u, v)\r\n";
            textBox1.Text += " u  v wt\r\n";

            for (int i = 0; i < E.Count; i++)
            {
                textBox1.Text += E[i].Lt.Id.ToString().PadLeft(2) + " ";
                textBox1.Text += E[i].Rt.Id.ToString().PadLeft(2) + " ";
                textBox1.Text += E[i].Wt.ToString().PadLeft(2) + "\r\n";
            }

            panel1.Invalidate();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            generate = false;

            Algorithm algo = new Algorithm();

            int n = V.Count;
            bool[,] graph = new bool[n, n];
            int[] ipath;

            for (int i = 0; i < E.Count; i++)
            {
                Edge edge = E[i];
                Vertex u = edge.Lt, v = edge.Rt;

                graph[u.Id, v.Id] = true;
            }

            if (!algo.HamCycle(graph, n, out ipath))
            {
                MessageBox.Show("No Hamilton circuit exists", "Warning Message",
                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            textBox1.Text += "\r\n";
            textBox1.Text += "Edges(u, v)\r\n";
            textBox1.Text += " u  v wt\r\n";

            Vertex[] path = new Vertex[n];
            int tcost = 0;

            F = new List<Edge>();

            for (int i = 0; i < n - 1; i++)
            {
                Vertex u = V[ipath[i]], v = V[ipath[i + 1]];
                Edge edge = new Edge(u, v, 0);

                for (int j = 0; j < E.Count; j++)
                {
                    if (edge.Lt == E[j].Lt && edge.Rt == E[j].Rt)
                    {
                        edge.Wt = E[j].Wt;
                        tcost += edge.Wt;
                        break;
                    }
                }

                F.Add(edge);
                textBox1.Text += u.Id.ToString().PadLeft(2) + " ";
                textBox1.Text += v.Id.ToString().PadLeft(2) + " ";
                textBox1.Text += edge.Wt.ToString().PadLeft(2) + "\r\n";
            }

            Vertex up = V[ipath[n - 1]], vp = V[0];

            Edge edgep = new Edge(up, vp, 0);

            for (int j = 0; j < E.Count; j++)
            {
                if (edgep.Lt == E[j].Lt && edgep.Rt == E[j].Rt)
                {
                    edgep.Wt = E[j].Wt;
                    tcost += edgep.Wt;
                    break;
                }
            }

            F.Add(edgep);
            textBox1.Text += up.Id.ToString().PadLeft(2) + " ";
            textBox1.Text += vp.Id.ToString().PadLeft(2) + " ";
            textBox1.Text += edgep.Wt.ToString().PadLeft(2) + "\r\n";

            textBox1.Text += "Cost = " + tcost + "\r\n";
            panel1.Invalidate();
        }
    }
}
Hamiltonian for a Four Node Graph
Hamiltonian for a Five Node Graph
Hamiltonian for a Six Node Graph

Knight’s Tour with Windows C++ Mutual Exclusion and Threading by James Pate Williams, Jr.

Menu
1 N-Queens Problem (Backtracking)
2 Knight's Tour Problem (Backtracking)
3 Warnsdorff Heuristic Solution
4 Print Knight Move Count Matrix
5 Exit
Option (1 - 5): 2
n = 6
seed = 1
starting row = 1
starting col = 3
ending row = 1
ending col = 3
length = 36
maximum runtime per instance in seconds = 60
Chessboard Rows and Columns = 6
Pseudo-random Number Generator Seed = 1
Row = 1
Col = 3
Sequence Length = 36
18 29 26  9 12 35
27  8 19  0 25 10
30 17 28 11 34 13
 7 20  1 32  3 24
16 31 22  5 14 33
21  6 15  2 23  4
Current Runtime in Seconds = 50.747000
Menu
1 N-Queens Problem (Backtracking)
2 Knight's Tour Problem (Backtracking)
3 Warnsdorff Heuristic Solution
4 Print Knight Move Count Matrix
5 Exit
Option (1 - 5):
Menu
1 N-Queens Problem (Backtracking)
2 Knight's Tour Problem (Backtracking)
3 Warnsdorff Heuristic Solution
4 Print Knight Move Count Matrix
5 Exit
Option (1 - 5): 3
n = 6
seed = 1
starting row = 1
starting col = 3
ending row = 1
ending col = 3
length = 36
maximum runtime per instance in seconds = 60
Chessboard Rows and Columns = 6
Pseudo-random Number Generator Seed = 1
Row = 1
Col = 3
Sequence Length = 36
18 29 26  9 12 35
27  8 19  0 25 10
30 17 28 11 34 13
 7 20  1 32  3 24
16 31 22  5 14 33
21  6 15  2 23  4
Current Runtime in Seconds = 46.983000
Menu
1 N-Queens Problem (Backtracking)
2 Knight's Tour Problem (Backtracking)
3 Warnsdorff Heuristic Solution
4 Print Knight Move Count Matrix
5 Exit
Option (1 - 5):

// KnightsTourCPP.cpp : Defines the entry point for the console application.
//
/*
Author:	James Pate Williams, Jr. (c) 2000 - 2022
Backtracking algorithm applied to the N-Queens CSP.
Algorithm from _Foundations of Constraint Satisfaction_
by E. P. K. Tsang Chapter 2 page 37.
Warnsdorff's solution by James Pate Williams, Jr.
*/

#include "stdafx.h"
#include <windows.h>
#include <limits.h>
#include <stdlib.h>
#include <synchapi.h>
#include <time.h>
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <chrono>
using namespace std::chrono;
using namespace std;

// https://www.geeksforgeeks.org/measure-execution-time-function-cpp/

const int lBufferLength = 8192;

class Pair {
public:
	int row, col;
	static int n;
	Pair() { row = col = -1; };
	Pair(int row, int col) {
		this->row = row;
		this->col = col;
	};
	inline friend bool operator ==(
		const Pair lt,
		const Pair rt) {
		return
			lt.row == rt.row &&
			lt.col == rt.col;
	};
	inline friend bool operator <(
		const Pair lt,
		const Pair rt) {
		int lval = lt.row * n + lt.col;
		int rval = rt.row * n + rt.col;
		return lval < rval;
	};
	inline friend bool operator >(
		const Pair lt,
		const Pair rt) {
		int lval = lt.row * n + lt.col;
		int rval = rt.row * n + rt.col;
		return lval > rval;
	};
	inline static int BinarySearch(
		vector<Pair> arr, int p, int r, Pair num) {
		if (r >= p) {
			int mid = p + (r - p) / 2;
			if (arr[mid] == num)
				return mid;
			if (arr[mid] > num)
				return BinarySearch(arr, p, mid - 1, num);
			if (arr[mid] < num)
				return BinarySearch(arr, mid + 1, r, num);
		}
		return -1;
	};
	inline static bool BinarySearchSTL(vector<Pair> solution, Pair test) {
		return binary_search(solution.begin(), solution.end(), test);
	};
	inline static bool LinearSearch(vector<Pair> solution, Pair test, int& index) {
		for (int i = 0; i < (int)solution.size(); i++) {
			if (test == solution[i]) {
				index = i;
				return true;
			}
		}
		index = -1;
		return false;
	};
	inline static bool FindSTL(vector<Pair> solution, Pair test, int& index)
	{
		vector<Pair>::iterator sit = find(solution.begin(), solution.end(), test);
		index = sit - solution.begin();
		return sit != solution.end();
	};
};

int Pair::n = 6;

class Board {
public:
	ofstream file;
	bool warnsdorff, writeToFile;
	char* buffer;
	double currentRuntime, cumulativeRuntime;
	int bufferLength;
	int cumulativeCount, length, n;
	int startingRow, startingCol;
	int endingRow, endingCol;
	int maxRuntimeSeconds;
	unsigned int seed;
	bool** marked;
	int** legalMoveCount;
	vector<int> unlabeled;
	vector<Pair> compoundLabel;
	vector<Pair> Dx;
	vector<Pair> solution;
	Board(
		bool warnsdorff, 
		bool writeToFile,
		char* buffer,
		int bufferLength,
		int n,
		int startingRow, 
		int startingCol,
		int endingRow,
		int endingCol,
		int length,
		int maxRuntimeSeconds,
		unsigned int seed) {
		this->warnsdorff = warnsdorff;
		this->writeToFile = writeToFile;
		this->buffer = buffer;
		this->bufferLength = bufferLength;
		this->n = n;
		this->startingRow = startingRow;
		this->startingCol = startingCol;
		this->endingRow = endingRow;
		this->endingCol = endingCol;
		this->length = length;
		this->maxRuntimeSeconds = maxRuntimeSeconds;
		this->seed = seed;
		Initialization();
		currentRuntime = 0;
		cumulativeCount = 0;
		cumulativeRuntime = 0;
	}
	~Board() {
		if (marked != NULL) {
			for (int i = 0; i < n; i++)
				delete[] marked[i];
			delete[] marked;
		}
		if (legalMoveCount != NULL) {
			for (int i = 0; i < n; i++)
				delete[] legalMoveCount[i];
			delete[] legalMoveCount;
		}
	}
	vector<Pair> GetLegalKnightMoves(
		int i, int j);
	void Initialization();
	int KTconstraintsViolated(Pair pair);
	bool KTBacktrackingSolution(
		int count, int prevx, int prevy,
		vector<int> unlabeled,
		vector<Pair>& compounLabel,
		vector<Pair> Dx,
		vector<Pair>& solution);
	void DoBTSolution(
		int row, int col,
		HANDLE hBTMutex);
	void Board::GetPossibleMoveCountMatrix();
	void PrintPossibleMoveCountMatrix();
	bool WarnsdorffSolution(
		int count, int prevx, int prevy,
		vector<int> unlabeled,
		vector<Pair>& compoundLabel,
		vector<Pair> Dx,
		vector<Pair>& solution);
	void DoWarnsdorffSolution(
		int row, int col,
		HANDLE hWDMutex);
	void PrintPairVector();
	bool WriteBoardDataToFile(
		bool writeSolution, int row, int col);
};

vector<Pair> Board::GetLegalKnightMoves(int i, int j)
{
	int count = 0;
	Pair pair;
	vector<Pair> legal;
	// quadrant 1
	if (i + 1 < n && j + 2 < n)
	{
		if (!marked[i + 1][j + 2])
		{
			pair.row = i + 1;
			pair.col = j + 2;
			legal.push_back(pair);
		}
	}
	if (i + 2 < n && j + 1 < n)
	{
		if (!marked[i + 2][j + 1])
		{
			pair.row = i + 2;
			pair.col = j + 1;
			legal.push_back(pair);
		}
	}
	// quadrant 2
	if (i - 1 >= 0 && j + 2 < n)
	{
		if (!marked[i - 1][j + 2])
		{
			pair.row = i - 1;
			pair.col = j + 2;
			legal.push_back(pair);
		}
	}
	if (i - 2 >= 0 && j + 1 < n)
	{
		if (!marked[i - 2][j + 1])
		{
			pair.row = i - 2;
			pair.col = j + 1;
			legal.push_back(pair);
		}
	}
	// quadrant 3
	if (i - 1 >= 0 && j - 2 >= 0)
	{
		if (!marked[i - 1][j - 2])
		{
			pair.row = i - 1;
			pair.col = j - 2;
			legal.push_back(pair);
		}
	}
	if (i - 2 >= 0 && j - 1 >= 0)
	{
		if (!marked[i - 2][j - 1])
		{
			pair.row = i - 2;
			pair.col = j - 1;
			legal.push_back(pair);
		}
	}
	// quadrant 4
	if (i + 1 < n && j - 2 >= 0)
	{
		if (!marked[i + 1][j - 2])
		{
			pair.row = i + 1;
			pair.col = j - 2;
			legal.push_back(pair);
		}
	}
	if (i + 2 < n && j - 1 >= 0)
	{
		if (!marked[i + 2][j - 1])
		{
			pair.row = i + 2;
			pair.col = j - 1;
			legal.push_back(pair);
		}
	}
	return legal;
}

void Board::Initialization() {
	if (marked == NULL) {
		marked = new bool* [n];
		for (int i = 0; i < n; i++) {
			marked[i] = new bool[n];
		}
	}
	if (legalMoveCount == NULL) {
		legalMoveCount = new int* [n];
		for (int i = 0; i < n; i++) {
			legalMoveCount[i] = new int[n];
		}
	}
	if (warnsdorff)
		GetPossibleMoveCountMatrix();
	srand(seed);
	unlabeled.clear();
	compoundLabel.clear();
	Dx.clear();
	solution.clear();
	for (int i = 0; i < n * n; i++)
		unlabeled.push_back(i);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			Pair move;
			move.row = i;
			move.col = j;
			marked[i][j] = false;
			Dx.push_back(move);
		}
	}
}

int Board::KTconstraintsViolated(Pair pair) {
	int cv = 0;
	int row = pair.row;
	int col = pair.col;
	int xi = row, yi = col;

	for (int i = 0; i < (int)compoundLabel.size(); i++)
	{
		int x = compoundLabel[i].row;
		int y = compoundLabel[i].col;
		int r1 = x + 1, r2 = x + 2, r3 = x - 1, r4 = x - 2;
		int c1 = y + 1, c2 = y + 2, c3 = y - 1, c4 = y - 2;
		if (r1 < n && xi == r1 && c1 < n && yi == c1 ||
			r1 < n && xi == r1 && c2 < n && yi == c2 ||
			r1 < n && xi == r1 && c3 >= 0 && yi == c3 ||
			r1 < n && xi == r1 && c4 >= 0 && yi == c4 ||
			r2 < n && xi == r2 && c1 < n && yi == c1 ||
			r2 < n && xi == r2 && c2 < n && yi == c2 ||
			r2 < n && xi == r2 && c3 >= 0 && yi == c3 ||
			r2 < n && xi == r2 && c4 >= 0 && yi == c4 ||
			r3 >= 0 && xi == r3 && c1 < n && yi == c1 ||
			r3 >= 0 && xi == r3 && c2 < n && yi == c2 ||
			r3 >= 0 && xi == r3 && c3 >= 0 && yi == c3 ||
			r3 >= 0 && xi == r3 && c4 >= 0 && yi == c4 ||
			r4 >= 0 && xi == r4 && c1 < n && yi == c1 ||
			r4 >= 0 && xi == r4 && c2 < n && yi == c2 ||
			r4 >= 0 && xi == r4 && c3 >= 0 && yi == c3 ||
			r4 >= 0 && xi == r4 && c4 >= 0 && yi == c4)
		{
			if (marked[xi][yi])
				cv++;
		}
	}
	return cv;
}

bool Board::KTBacktrackingSolution(
	int count, int prevx, int prevy,
	vector<int> unlabeled,
	vector<Pair>& compounLabel,
	vector<Pair> Dx,
	vector<Pair>& solution)
{
	bool done, found, result;
	int i, x, y;
	Pair v;
	vector<Pair> legal;

	if (count == 0)
	{
		v.row = prevx;
		v.col = prevy;
		marked[prevx][prevy] = true;
		if (!Dx.empty()) {
			vector<Pair>::iterator dit = find(
				Dx.begin(), Dx.end(), v);
			if (dit != Dx.end())
				Dx.erase(dit);
		}
		if (!unlabeled.empty()) {
			vector<int>::iterator uit = find(
				unlabeled.begin(), unlabeled.end(), 0);
			if (uit != unlabeled.end())
				unlabeled.erase(uit);
		}
		compoundLabel.push_back(v);
		count++;
	}
	legal = GetLegalKnightMoves(
		prevx, prevy);
	while (!legal.empty())
	{
		x = rand() % legal.size();
		for (i = 0; i < (int)unlabeled.size(); i++)
		{
			if (x == unlabeled[i])
			{
				y = i;
				break;
			}
		}
		vector<int>::iterator uit = find(
			unlabeled.begin(), unlabeled.end(), y);
		if (uit != unlabeled.end()) {
			unlabeled.erase(uit);
		}
		done = false;
		do {
			v = legal[x];
			if (!marked[v.row][v.col]) {
				marked[v.row][v.col] = true;
			}
			int cv = KTconstraintsViolated(v);
			if (cv > 0) {
				found = binary_search(compoundLabel.begin(), compoundLabel.end(), v);
				if (!found) {
					vector<Pair>::iterator cit = find(
						compoundLabel.begin(), compoundLabel.end(), v);
					if (cit == compoundLabel.end())
						compoundLabel.push_back(v);
					vector<Pair>::iterator lit = find(
						legal.begin(), legal.end(), v);
					if (lit != legal.end()) {
						legal.erase(lit);
					}
					vector<Pair>::iterator dit = find(
						Dx.begin(), Dx.end(), v);
					if (dit != Dx.end())
						Dx.erase(dit);
					marked[v.row][v.col] = true;
					prevx = v.row;
					prevy = v.col;
					done = true;
				}
				if (compoundLabel.size() == length)
				{
					for (i = 0; i < (int)compoundLabel.size(); i++)
						solution.push_back(compoundLabel[i]);
					return true;
				}
				result = KTBacktrackingSolution(
					count, prevx, prevy,
					unlabeled, compoundLabel, Dx, solution);
				if (result)
					return result;
			}
		} while (!Dx.empty() && !legal.empty() && !done);
	}
	Pair move;
	prevx = compoundLabel[compoundLabel.size() - 1].row;
	prevy = compoundLabel[compoundLabel.size() - 1].col;
	move.row = prevx;
	move.col = prevy;
	marked[prevx][prevy] = false;
	vector<Pair>::iterator cit = find(
		compoundLabel.begin(), compoundLabel.end(), move);
	if (cit != compoundLabel.end()) {
		compoundLabel.erase(cit);
	}
	return false;
}

void Board::DoBTSolution(
	int row, int col,
	HANDLE hBTMutex) {
	int count = 0;
	int prevx = row;
	int prevy = col;
	startingRow = row;
	startingCol = col;
	bool io = false, bt = false;
	auto start = high_resolution_clock::now();
	bt = KTBacktrackingSolution(
		count, prevx, prevy,
		unlabeled, compoundLabel,
		Dx, solution);
	auto stop = high_resolution_clock::now();
	auto duration = duration_cast<milliseconds>(stop - start);
	currentRuntime = (double)duration.count() / 1.0e3;
	if (bt)
		io = WriteBoardDataToFile(true, row, col);
	else
		io = WriteBoardDataToFile(false, row, col);
	cumulativeCount++;
	cumulativeRuntime += currentRuntime;
	ReleaseMutex(hBTMutex);
}

void Board::GetPossibleMoveCountMatrix() {
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			vector<Pair> possible = GetLegalKnightMoves(
				i, j);
			legalMoveCount[i][j] = possible.size();
		}
	}
}

void Board::PrintPossibleMoveCountMatrix()
{
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			std::cout << legalMoveCount[i][j] << " ";
		}
		std::cout << endl;
	}
}

void Board::PrintPairVector() {
	int** matrix = new int* [n];
	for (int i = 0; i < n; i++)
		matrix[i] = new int[n];
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
			matrix[i][j] = -1;
	}
	bool done = (int)solution.size() == n * n;
	if (done) {
		for (int i = 0, count = 0; i < (int)solution.size(); count++, i++)
		{
			Pair pair = solution[i];
			std::cout << "(" << setw(2) << pair.row << ", ";
			std::cout << setw(2) << pair.col << ")" << " ";
			if ((count + 1) % n == 0)
				std::cout << endl;
			matrix[pair.row][pair.col] = count;
		}
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
				std::cout << setw(2) << matrix[i][j] << " ";
			std::cout << endl;
		}
	}
	else {
		for (int i = 0, count = 0; i < (int)compoundLabel.size(); count++, i++)
		{
			Pair pair = compoundLabel[i];
			std::cout << "(" << setw(2) << pair.row << ", ";
			std::cout << setw(2) << pair.col << ")" << " ";
			if ((i + 1) % n == 0)
				std::cout << endl;
		}
		std::cout << endl;
	}
	if (matrix != NULL) {
		for (int i = 0; i < n; i++)
			delete[] matrix[i];
		delete[] matrix;
	}
}

bool Board::WarnsdorffSolution(
	int count, int prevx, int prevy,
	vector<int> unlabeled,
	vector<Pair>& compoundLabel,
	vector<Pair> Dx,
	vector<Pair>& solution) {
	bool done, found, result;
	int i;
	Pair v;
	vector<Pair> legalMove, nextMoveVector, nextMove;

	if (count == 0)
	{
		prevx = startingRow;
		prevy = startingCol;
		v.row = prevx;
		v.col = prevy;
		marked[v.row][v.col] = true;
		if (!Dx.empty()) {
			vector<Pair>::iterator dit = find(
				Dx.begin(), Dx.end(), v);
			if (dit != Dx.end())
				Dx.erase(dit);
		}
		if (!unlabeled.empty()) {
			vector<int>::iterator uit = find(
				unlabeled.begin(), unlabeled.end(), 0);
			if (uit != unlabeled.end())
				unlabeled.erase(uit);
		}
		compoundLabel.push_back(v);
		count++;
	}
	legalMove = GetLegalKnightMoves(
		prevx, prevy);
	while (!legalMove.empty())
	{
		int min = INT_MAX;
		nextMoveVector.clear();
		for (int k = 0; k < (int)legalMove.size(); k++) {
			if (legalMoveCount[legalMove[k].row][legalMove[k].col] < min) {
				min = legalMoveCount[legalMove[k].row][legalMove[k].col];
				nextMoveVector.push_back(legalMove[k]);
			}
		}
		vector<int> index;
		index.clear();
		for (int k = 0; k < (int)nextMoveVector.size(); k++) {
			int number = legalMoveCount[nextMoveVector[k].row][nextMoveVector[k].col];
			if (number == min) {
				index.push_back(k);
			}
		}
		int r = rand() % index.size();
		v = nextMoveVector[r];
		done = false;
		do {
			if (!marked[v.row][v.col]) {
				marked[v.row][v.col] = true;
				nextMove.push_back(v);
			}
			int sum = 0;
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					if (marked[i][j])
						sum++;
				}
			}
			int cv = KTconstraintsViolated(v);
			if (cv > 0) {
				found = binary_search(compoundLabel.begin(), compoundLabel.end(), v);
				if (!found) {
					vector<Pair>::iterator cit = find(
						compoundLabel.begin(), compoundLabel.end(), v);
					if (cit == compoundLabel.end())
						compoundLabel.push_back(v);
					vector<Pair>::iterator lit = find(
						legalMove.begin(), legalMove.end(), v);
					if (lit != legalMove.end()) {
						legalMove.erase(lit);
					}
					vector<Pair>::iterator dit = find(
						Dx.begin(), Dx.end(), v);
					if (dit != Dx.end())
						Dx.erase(dit);
					marked[v.row][v.col] = true;
					prevx = v.row;
					prevy = v.col;
					done = true;
				}
				if (compoundLabel.size() == length)
				{
					for (i = 0; i < (int)compoundLabel.size(); i++)
						solution.push_back(compoundLabel[i]);
					return true;
				}
				result = WarnsdorffSolution(
					count, prevx, prevy, unlabeled,
					compoundLabel, Dx, solution);
				if (result)
					return result;
			}
		} while (!Dx.empty() && !legalMove.empty() && !done);
	}
	Pair move;
	prevx = compoundLabel[compoundLabel.size() - 1].row;
	prevy = compoundLabel[compoundLabel.size() - 1].col;
	move.row = prevx;
	move.col = prevy;
	marked[prevx][prevy] = false;
	vector<Pair>::iterator cit = find(
		compoundLabel.begin(), compoundLabel.end(), move);
	if (cit != compoundLabel.end()) {
		compoundLabel.erase(cit);
	}
	return false;
}

void Board::DoWarnsdorffSolution(
	int row, int col,
	HANDLE hWDMutex) {
	int count = 0;
	int prevx = row;
	int prevy = col;
	startingRow = row;
	startingCol = col;
	bool io = false, ws = false;
	auto start = high_resolution_clock::now();
	Initialization();
	ws = WarnsdorffSolution(
		count, prevx, prevy,
		unlabeled, compoundLabel,
		Dx, solution);
	auto stop = high_resolution_clock::now();
	auto duration = duration_cast<milliseconds>(stop - start);
	currentRuntime = (double)duration.count() / 1.0e3;
	if (ws)
		io = WriteBoardDataToFile(true, row, col);
	else
		io = WriteBoardDataToFile(false, row, col);
	cumulativeCount++;
	cumulativeRuntime += currentRuntime;
	ReleaseMutex(hWDMutex);
}

bool Board::WriteBoardDataToFile(
	bool writeSolution, int row, int col) {
	char newLine[2] = { '\n', '\0' };
	errno_t err;
	if (strlen(buffer) == 0)
		strcpy_s(buffer, bufferLength, "Chessboard Rows and Columns = ");
	else
		strcat_s(buffer, bufferLength, "Chessboard Rows and Columns = ");
	char nBuf[64] = { '\0' };
	err = _itoa_s(n, nBuf, 10);
	strcat_s(buffer, bufferLength, nBuf);
	strcat_s(buffer, bufferLength, newLine);
	strcat_s(buffer, bufferLength, "Pseudo-random Number Generator Seed = ");
	err = _itoa_s((int)seed, nBuf, 10);
	strcat_s(buffer, bufferLength, nBuf);
	strcat_s(buffer, bufferLength, newLine);
	strcat_s(buffer, bufferLength, "Row = ");
	err = _itoa_s(row, nBuf, 10);
	strcat_s(buffer, bufferLength, nBuf);
	strcat_s(buffer, bufferLength, newLine);
	strcat_s(buffer, bufferLength, "Col = ");
	err = _itoa_s(col, nBuf, 10);
	strcat_s(buffer, bufferLength, nBuf);
	strcat_s(buffer, bufferLength, newLine);
	strcat_s(buffer, bufferLength, "Sequence Length = ");
	err = _itoa_s(length, nBuf, 10);
	strcat_s(buffer, bufferLength, nBuf);
	strcat_s(buffer, bufferLength, newLine);
	if (writeSolution && solution.size() == n * n)
	{
		int** matrix = new int* [n];
		for (int i = 0; i < n; i++)
			matrix[i] = new int[n];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
				matrix[i][j] = -1;
		}
		for (int i = 0, count = 0; i < (int)solution.size(); count++, i++)
		{
			Pair pair = solution[i];
			int r = pair.row;
			int c = pair.col;
			matrix[pair.row][pair.col] = count;
		}
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++) {
				string space = " ";
				if (matrix[i][j] < 10)
					err = strcat_s(buffer, bufferLength, space.c_str());
				err = _itoa_s(matrix[i][j], nBuf, 10);
				err = strcat_s(buffer, bufferLength, nBuf);
				err = strcat_s(buffer, bufferLength, space.c_str());
			}
			strcat_s(buffer, bufferLength, newLine);
		}
		strcat_s(buffer, bufferLength, "Current Runtime in Seconds = ");
		string cr = to_string(currentRuntime);
		strcat_s(buffer, bufferLength, cr.c_str());
		strcat_s(buffer, bufferLength, newLine);
		if (matrix != NULL) {
			for (int i = 0; i < n; i++)
				delete[] matrix[i];
			delete[] matrix;
		}
	}
	return true;
}

typedef struct Data
{
	int row, col;
	Board* board;
	DWORD dwWaitMS;
} DATA, * PDATA;

DWORD WINAPI BTThreadCode(LPVOID lpParam)
{
	Data* pData = (Data*)lpParam;
	HANDLE hBTMutex = CreateMutex(NULL, FALSE, NULL);

	if (hBTMutex != NULL)
	{
		pData->board->DoBTSolution(
			pData->row,
			pData->col,
			hBTMutex);
		DWORD err = WaitForSingleObject(hBTMutex, pData->dwWaitMS);
		CloseHandle(hBTMutex);
	}
	return 0;
}

DWORD WINAPI WDThreadCode(LPVOID lpParam)
{
	Data* pData = (Data*)lpParam;
	HANDLE hWDMutex = CreateMutex(NULL, FALSE, NULL);

	if (hWDMutex != NULL)
	{
		pData->board->DoBTSolution(
			pData->row,
			pData->col,
			hWDMutex);
		DWORD err = WaitForSingleObject(
			hWDMutex, pData->dwWaitMS);
		CloseHandle(hWDMutex);
	}
	return 0;
}

int NQconstraintsViolated(vector<int>& Q) {
	int a, b, c = 0, i, j, n;

	n = Q.size();
	for (i = 0; i < n; i++) {
		a = Q[i];
		for (j = 0; j < n; j++) {
			b = Q[j];
			if (i != j && a != -1 && b != -1) {
				if (a == b) c++;
				if (i - j == a - b || i - j == b - a) c++;
			}
		}
	}
	return c;
}

bool NQBacktrack(
	vector<int> unlabeled,
	vector<int> compoundLabel,
	vector<int>& solution) {
	bool result;
	int i, j, v, x;
	vector<int> Dx(compoundLabel.size());

	if (unlabeled.empty()) {
		for (i = 0; i < (int)compoundLabel.size(); i++)
			solution[i] = compoundLabel[i];
		return true;
	}
	for (i = 0; i < (int)compoundLabel.size(); i++)
		Dx[i] = i;
	// pick a random variable from unlabeled array
	i = rand() % unlabeled.size();
	x = unlabeled[i];
	do {
		// pick a random value from domain of x
		j = rand() % Dx.size();
		v = Dx[j];
		vector<int>::iterator vIterator = find(Dx.begin(), Dx.end(), v);
		Dx.erase(vIterator);
		compoundLabel[x] = v;
		if (NQconstraintsViolated(compoundLabel) == 0) {
			vIterator = find(unlabeled.begin(), unlabeled.end(), x);
			unlabeled.erase(vIterator);
			result = NQBacktrack(unlabeled, compoundLabel, solution);
			if (result) return result;
			unlabeled.push_back(x);
		}
		else
			compoundLabel[x] = -1;
	} while (!Dx.empty());
	return false;
}

void PrintNQSolution(vector<int>& solution) {
	char hyphen[256] = { 0 };
	int column, i, i4, n = solution.size(), row;

	if (n <= 10) {
		for (i = 0; i < n; i++) {
			i4 = i * 4;
			hyphen[i4 + 0] = '-';
			hyphen[i4 + 1] = '-';
			hyphen[i4 + 2] = '-';
			hyphen[i4 + 3] = '-';
		}
		i4 = i * 4;
		hyphen[i4 + 0] = '-';
		hyphen[i4 + 1] = '\n';
		hyphen[i4 + 2] = '\0';
		for (row = 0; row < n; row++) {
			column = solution[row];
			std::cout << hyphen;
			for (i = 0; i < column; i++)
				std::cout << "|   ";
			std::cout << "| Q ";
			for (i = column + 1; i < n; i++)
				std::cout << "|   ";
			std::cout << '|' << endl;
		}
		std::cout << hyphen;
	}
	else
		for (row = 0; row < n; row++)
			std::cout << row << ' ' << solution[row] << endl;
	std::cout << endl;
}

int main(int argc, char* argv[]) {
	std::cout.setf(ios::fixed, ios::floatfield);
	std::cout.setf(ios::showpoint);
	while (true) {
		bool valid;
		int i, length, n, option;
		int srow = 0, scol = 0;
		int erow = 0, ecol = 0;
		int maxRuntimeSeconds = 0;
		unsigned int seed;
		std::cout << "Menu" << endl;
		std::cout << "1 N-Queens Problem (Backtracking)" << endl;
		std::cout << "2 Knight's Tour Problem (Backtracking)" << endl;
		std::cout << "3 Warnsdorff Heuristic Solution" << endl;
		std::cout << "4 Print Knight Move Count Matrix" << endl;
		std::cout << "5 Exit" << endl;
		std::cout << "Option (1 - 5): ";
		cin >> option;
		if (option >= 5)
			return 0;
		valid = false;
		while (!valid) {
			valid = true;
			std::cout << "n = ";
			cin >> n;
			while (n < 5 || n > 8) {
				std::cout << "n must be >= 5 and <= 8" << endl;
				std::cout << "n = ";
				cin >> n;
			}
			if (option != 4) {
				std::cout << "seed = ";
				cin >> seed;
				while (seed < 1) {
					std::cout << "seed must be >= 1" << endl;
					std::cout << "seed = ";
					cin >> seed;
				}
			}
			if (option == 2 || option == 3) {
				std::cout << "starting row = ";
				cin >> srow;
				while (srow < 0 || srow > 7) {
					std::cout << "starting row must be >= 0 and <= 9" << endl;
					std::cout << "starting row = ";
					cin >> srow;
				}
				std::cout << "starting col = ";
				cin >> scol;
				while (scol < 0 || scol > 7) {
					std::cout << "starting col must be >= 0 and <= 9" << endl;
					std::cout << "starting col = ";
					cin >> scol;
				}
				std::cout << "ending row = ";
				cin >> erow;
				while (erow < 0 || erow > 7) {
					std::cout << "starting row must be >= 0 and <= 7" << endl;
					std::cout << "starting row = ";
					cin >> erow;
				}
				std::cout << "ending col = ";
				cin >> ecol;
				while (ecol < 0 || ecol > 7) {
					std::cout << "ending col must be >= 0 and <= 7" << endl;
					std::cout << "ending col = ";
					cin >> ecol;
				}
			}
			if (option == 2 || option == 3) {
				std::cout << "length = ";
				cin >> length;
				while (length < 25 || length > 64)
				{
					std::cout << "length must be >= 25 and <= 64" << endl;
					std::cout << "length = ";
					cin >> length;
				}
				if (n == 5 && length < 25) {
					std::cout << "Invalid length value for given n" << endl;
					std::cout << "length  must be <= 25" << endl;
					valid = false;
				}
				else if (n == 6) {
					if (length > 36) {
						std::cout << "Invalid length value for given n" << endl;
						std::cout << "length must be <= 36" << endl;
						valid = false;
					}
				}
				else if (n == 7) {
					if (length > 49) {
						std::cout << "Invalid length value for given n" << endl;
						std::cout << "length must be <= 49" << endl;
						valid = false;
					}
				}
				else if (n == 8) {
					if (length > 64) {
						std::cout << "Invalid length value for given n" << endl;
						std::cout << "length must be <= 64" << endl;
						valid = false;
					}
				}
				std::cout << "maximum runtime per instance in seconds = ";
				cin >> maxRuntimeSeconds;
				while (maxRuntimeSeconds <= 0) {
					std::cout << "maximum runtime > 0" << endl;
					std::cout << "maximum runtime per instance in seconds = ";
					cin >> maxRuntimeSeconds;
				}
			}
		}
		if (option == 1) {
			auto start = high_resolution_clock::now();
			vector<int> compoundLabel(n, -1), solution(n, -1), unlabeled(n);
			for (i = 0; i < n; i++)
				unlabeled[i] = i;
			if (NQBacktrack(unlabeled, compoundLabel, solution))
				PrintNQSolution(solution);
			else
				std::cout << "Problem has no solution" << endl;
			auto stop = high_resolution_clock::now();
			auto duration = duration_cast<microseconds>(stop - start);
			std::cout << "Runtime: " << setprecision(6)
				<< (double)duration.count() / 1.0e6 << " seconds" << endl;
		}
		else if (option == 2) {
			string filename = "Chronological Backtracking Results.txt";
			ofstream file;
			file.open(filename.c_str(), ios::ate);
			Pair::n = n;
			for (int i = srow; i <= erow; i++) {
				for (int j = scol; j <= ecol; j++) {
					char lBuffer[lBufferLength] = { 0 };
					Board* board = new Board(
						true,
						true,
						lBuffer,
						lBufferLength,
						n,
						srow,
						scol,
						erow,
						ecol,
						length,
						maxRuntimeSeconds,
						seed);
					Data* pBTData = new Data();
					DWORD dwThreadId;
					pBTData->row = i;
					pBTData->col = j;
					pBTData->board = board;
					pBTData->dwWaitMS = maxRuntimeSeconds * 1000;
					HANDLE hBTThread = CreateThread(
						NULL,			    // default security attributes
						0,					// use default stack size  
						BTThreadCode,		// thread function name
						pBTData,			// argument to thread function 
						0,			        // use default creation flags 
						&dwThreadId);		// returns the thread identifier
					if (hBTThread != NULL)
					{
						WaitForSingleObject(
							hBTThread, maxRuntimeSeconds * 1000);
						CloseHandle(hBTThread);
					}
					file << lBuffer;
					std::cout << lBuffer;
				}
			}
		}
		else if (option == 3) {
			string filename = "Warnsdorff Heuristic Results.txt";
			ofstream file;
			file.open(filename.c_str(), ios::ate);
			Pair::n = n;
			for (int i = srow; i <= erow; i++) {
				for (int j = scol; j <= ecol; j++) {
					char lBuffer[lBufferLength] = { 0 };
					Board* board = new Board(
						true,
						true,
						lBuffer,
						lBufferLength,
						n,
						srow,
						scol,
						erow,
						ecol,
						length,
						maxRuntimeSeconds,
						seed);
					Data* pWDData = new Data();
					DWORD dwThreadId;
					pWDData->row = i;
					pWDData->col = j;
					pWDData->board = board;
					pWDData->dwWaitMS = maxRuntimeSeconds * 1000;
					HANDLE hWDThread = CreateThread(
						NULL,			    // default security attributes
						0,					// use default stack size  
						WDThreadCode,		// thread function name
						pWDData,			// argument to thread function 
						0,			        // use default creation flags 
						&dwThreadId);		// returns the thread identifier
					if (hWDThread != NULL)
					{
						WaitForSingleObject(
							hWDThread, maxRuntimeSeconds * 1000);
						CloseHandle(hWDThread);
					}
					file << lBuffer;
					std::cout << lBuffer;
				}
			}
		}
		else if (option == 4) {
			Board board(
				true,
				true,
				NULL,
				0,
				n,
				0,
				0,
				0,
				0,
				0,
				0,
				1);
			board.GetPossibleMoveCountMatrix();
			board.PrintPossibleMoveCountMatrix();
		}
	}
	return 0;
}

Sorting C++ Source Code by James Pate Williams, Jr.

#include "SampleStatistics.h"
#include "Sorting.h"
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <chrono>
using namespace std::chrono;
using namespace std;

// https://www.geeksforgeeks.org/measure-execution-time-function-cpp/

char GetSubOption(char title[])
{
	char line[128];
	cout << title << endl;
	cout << "1 Insertion Sort" << endl;
	cout << "2 Selection Sort" << endl;
	cout << "3 Heap Sort" << endl;
	cout << "4 Quick Sort" << endl;
	cout << "5 Singleton's Sort" << endl;
	cout << "6 Tree Sort 3" << endl;
	cout << "7 Exit Submenu" << endl;
	cout << "8 Exit Program" << endl;
	cout << "Suboption Number: ";
	cin.getline(line, 128);
	return line[0];
}

char DoSort(char option) {
	char subOption, line[128];
	char title[128] = { 0 };
	char name[6][64] = { { 0 } };
	strcpy_s(name[0], 64, "Insertion Sort");
	strcat_s(name[1], 64, "Selection Sort");
	strcat_s(name[2], 64, "Heap Sort");
	strcat_s(name[3], 64, "Quick Sort");
	strcat_s(name[4], 64, "Singleton's Sort");
	strcat_s(name[5], 64, "Tree Sort 3");
	vector<double> runtime;
	if (option == '1')
	{
		strcpy_s(title, 128, "Single Sorting Tests Submenu");
	}
	else {
		strcpy_s(title, 128, "Statistical Sorting Tests Submenu");
	}
	subOption = GetSubOption(title);
	if (subOption < '1' || subOption > '8') {
		cout << "Illegal Suboption Exiting Application!" << endl;
		exit(-1);
	}
	if (subOption == '7' || subOption == '8') {
		return subOption;
	}
	int index = (int)(subOption - '1');
	cout << name[index] << endl;
	cout << "PRNG Seed             = ";
	cin.getline(line, 128);
	int seed = atoi(line);
	cout << "Number of Samples     = ";
	cin.getline(line, 128);
	int n = atoi(line);
	cout << "Maximum Sample Value  = ";
	cin.getline(line, 128);
	int maximum = atoi(line);
	srand(seed);
	int number;
	if (option == '2') {
		cout << "Number of Experiments = ";
		cin.getline(line, 128);
		number = atoi(line);
	}
	else {
		number = 1;
	}
	double* sample = new double[n];
	double* shadow = new double[n];
	for (int i = 0; i < number; i++) {
		for (int j = 0; j < n; j++) {
			sample[j] = rand() % maximum;
			if (option == '1') {
				shadow[j] = sample[j];
			}
		}
		auto start = high_resolution_clock::now();
		switch (subOption) {
		case '1':
			Sorting::InsertionSort(sample, n);
			break;
		case '2':
			Sorting::SelectionSort(sample, n);
			break;
		case '3':
			Sorting::HeapSort(sample, n);
			break;
		case '4':
			Sorting::QuickSort(sample, n);
			break;
		case '5':
			Sorting::SingletonsSort(sample, n);
			break;
		case '6':
			Sorting::TreeSort3(sample, n);
			break;
		default:
			cout << "Unknown Suboption" << endl;
			break;
		}
		auto stop = high_resolution_clock::now();
		auto duration = duration_cast<microseconds>(stop - start);
		double rt = (double)duration.count();
		runtime.push_back(rt);
	}
	if (option == '1') {
		for (int i = 0; i < n; i++) {
			cout << setw(2) << shadow[i] << ' ';
			cout << setw(2) << sample[i] << endl;
		}
	}
	else if (option == '2') {
		cout << "Runtimes in Microseconds" << endl;
		cout << "Minimum Runtime       = " 
			<< setw(4) << fixed << setprecision(0)
			<< SampleStatistics::Min(runtime) << endl;
		cout << "Maximum Runtime       = " 
			<< setw(4) << fixed << setprecision(0)
			<< SampleStatistics::Max(runtime) << endl;
		cout << "Mean Runtime          = " 
			<< setw(4) << fixed << setprecision(0)
			<< SampleStatistics::Mean(runtime) << endl;
		cout << "Median Runtime        = "
			<< setw(4) << fixed << setprecision(0) <<
			SampleStatistics::Median(runtime) << endl;
	}
	delete[] sample;
	delete[] shadow;
	return subOption;
}

int main() {
	while (true) {
		char line[128];
		cout << "Menu" << endl;
		cout << "1 Single Sortimg Tests" << endl;
		cout << "2 Statistical Tests" << endl;
		cout << "3 Exit" << endl;;
		cout << "Option number: ";
		cin.getline(line, 128);
		if (line[0] == '3')
			break;
		if (line[0] == '1' || line[0] == '2') {
			while (true)
			{
				char doSort = DoSort(line[0]);
				if (doSort == '7')
					break;
				else if (doSort == '8')
					exit(1);
			}
		}
	}
	return 0;
}
#pragma once
#include <limits.h>
#include <vector>
using namespace std;

class SampleStatistics {
public:
	inline static double Mean(vector<double> x) {
		double sum = 0;

		for (int i = 0; i < (int)x.size(); i++)
			sum += (double)x[i];

		return sum / (int)x.size();
	};
	inline static double Max(vector<double> x)
	{
		double max = DBL_MIN;

		for (int i = 0; i < (int)x.size(); i++)
			if (x[i] > max)
				max = x[i];

		return max;
	};
	inline static double Min(vector<double> x)
	{
		double min = DBL_MAX;

		for (int i = 0; i < (int)x.size(); i++)
			if (x[i] < min)
				min = x[i];

		return min;
	};
	inline static double Median(vector<double> x)
	{
		int n = x.size(), n2 = n / 2 - 1;

		if (n % 2 == 1)
			return x[(n + 1) / 2 - 1];

		return 0.5 * (x[n2] + x[n2 + 1]);
	};
	inline static double Variance(vector<double> x)
	{
		double mean = Mean(x), sumSq = 0;
		int n = x.size();
		int n1 = n - 1;

		for (int i = 0; i < n; i++)
		{
			double delta = x[i] - mean;

			sumSq += delta * delta;
		}

		return sumSq / n1;
	};
};
#pragma once
// Insertion sort, heap sort, and quick sort algorithms
// From "Algortihms" by Thomas H. Cormen, et. al.
// Selection sort, Singleton's sort, and Tree Sort 3
// From "Sorting and Sort Systems" by Harold Lorin
class Sorting {
public:
	static void InsertionSort(double a[], int n);
	static void SelectionSort(double a[], int n);
	static void HeapSort(double a[], int n);
	static void QuickSort(double a[], int n);
	static void SingletonsSort(double a[], int n);
	static void TreeSort3(double a[], int n);
private:
	// five helper methods for Heap Sort
	static int Parent(int i);
	static int Left(int i);
	static int Right(int i);
	static void BuildHeap(double a[], int n, int& heapSize);
	static void Heapify(double a[], int i, int n, int& heapSize);
	// helper methods for Quick Sort
	static int Partition(double a[], int n, int lo, int hi);
	static void DoQuickSort(double a[], int n, int p, int r);
	// helper function for Singleton's sort
	static void DoSingletonsSort(double a[], int ii, int jj);
	// helper function for TreeSort3
	static void SiftUp(double a[], int i, int n);
};
#include "Sorting.h"

void Sorting::InsertionSort(double a[], int n) {
    for (int j = 1; j < n; j++)
    {
        double key = a[j];
        int i = j - 1;

        while (i >= 0 && a[i] > key)
        {
            a[i + 1] = a[i];
            i--;
        }

        a[i + 1] = key;
    }
}

void Sorting::SelectionSort(double a[], int n) {
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (a[i] > a[j])
            {
                double t = a[i];

                a[i] = a[j];
                a[j] = t;
            }
        }
    }
}

int Sorting::Parent(int i) {
    return i / 2;
}

int Sorting::Left(int i) {
    return 2 * i;
}

int Sorting::Right(int i) {
    return 2 * i + 1;
}

void Sorting::Heapify(double a[], int i, int n, int& heapSize) {
    int l = Left(i);
    int r = Right(i);
    int largest = -1;

    if (l < heapSize && a[l] > a[i])
        largest = l;
    else
        largest = i;

    if (r < heapSize && a[r] > a[largest])
        largest = r;

    if (largest != i)
    {
        double t = a[i];

        a[i] = a[largest];
        a[largest] = t;

        Heapify(a, largest, n, heapSize);
    }
}

void Sorting::BuildHeap(double a[], int n, int& heapSize) {
    for (int i = n / 2; i >= 0; i--)
        Heapify(a, i, n, heapSize);
}

void Sorting::HeapSort(double a[], int n) {
    int heapSize = n;

    BuildHeap(a, n, heapSize);

    for (int i = n - 1; i >= 0; i--)
    {
        double t = a[0];

        a[0] = a[i];
        a[i] = t;

        heapSize--;

        Heapify(a, 0, n, heapSize);
    }
}

int Sorting::Partition(double a[], int n, int lo, int hi) {
    int pivotIndex = lo + (hi - lo) / 2;
    double x = a[pivotIndex];
    double t = x;

    a[pivotIndex] = a[hi];
    a[hi] = t;

    int storeIndex = lo;

    for (int i = lo; i < hi; i++)
    {
        if (a[i] < x)
        {
            t = a[i];
            a[i] = a[storeIndex];
            a[storeIndex++] = t;
        }
    }

    t = a[storeIndex];
    a[storeIndex] = a[hi];
    a[hi] = t;

    return storeIndex;
}

void Sorting::DoQuickSort(double a[], int n, int p, int r) {
    if (p < r)
    {
        int q = Partition(a, n, p, r);

        DoQuickSort(a, n, p, q - 1);
        DoQuickSort(a, n, q + 1, r);
    }
}

void Sorting::QuickSort(double a[], int n) {
    DoQuickSort(a, n, 0, n - 1);
}

void Sorting::DoSingletonsSort(double a[], int ii, int jj) {
    int m = 0;
    int i = ii;
    int j = jj;
    int iu[50] = { 0 };
    int il[50] = { 0 };
    int ij = 0, l = 1, k = 0;
    double t = 0.0, tt = 0.0;
    Label1:
        if (i >= j)
            goto Label8;
        goto Label2;
    Label2:
        k = i;
        ij = (j + i) / 2;
        t = a[ij];
        if (a[i] <= t)
            goto Label3;
        a[ij] = a[i];
        a[i] = t;
        t = a[ij];
        goto Label3;
    Label3:
        l = j;
        if (a[j] >= t)
            goto Label5;
        a[ij] = a[j];
        a[j] = t;
        t = a[ij];
        if (a[i] <= t)
            goto Label5;
        a[ij] = a[i];
        a[i] = t;
        t = a[ij];
        goto Label5;
    Label4:
        a[l] = a[k];
        a[k] = tt;
        goto Label5;
    Label5:
        l--;
        if (a[l] > t)
            goto Label5;
        tt = a[l];
        goto Label6;
    Label6:
        k++;
        if (a[k] < t)
            goto Label6;
        if (k <= l)
            goto Label4;
        if (l - i <= j - k)
            goto Label7;
        il[m] = i;
        iu[m] = l;
        i = k;
        m++;
        goto Label9;
    Label7:
        il[m] = k;
        iu[m] = j;
        j = l;
        m++;
        goto Label9;
    Label8:
        m--;
        if (m == -1)
            return;
        i = il[m];
        j = iu[m];
        goto Label9;
    Label9:
        if (j - i > 10)
            goto Label2;
        if (i == ii)
            goto Label1;
        i--;
        goto Label10;
    Label10:
        i++;
        if (i == j)
            goto Label8;
        t = a[i + 1];
        if (a[i] <= t)
            goto Label10;
        k = i;
        goto Label11;
    Label11:
        a[k + 1] = a[k];
        k--;
        if (t < a[k])
            goto Label11;
        a[k + 1] = t;
        goto Label10;
}

void Sorting::SingletonsSort(double a[], int n) {
    DoSingletonsSort(a, 0, n - 1);
}

void Sorting::SiftUp(double a[], int i, int n) {
    double copy = a[i];
    int j;

    while (true)
    {
        j = i + i;

        if (j <= n)
        {
            if (j < n)
            {
                if (a[j + 1] > a[j])
                    j++;
            }

            if (a[j] > copy)
            {
                a[i] = a[j];
                i = j;
                continue;
            }
        }

        break;
    }

    a[i] = copy;
}

void Sorting::TreeSort3(double a[], int n)
{
    for (int i = n / 2; i >= 1; i--)
        SiftUp(a, i, n - 1);

    for (int i = n - 1; i >= 1; i--)
    {
        SiftUp(a, 0, i);

        double t = a[0];

        a[0] = a[i];
        a[i] = t;
    }
}

Python Root Finder for Linear, Quadratic, Cubic, and Quartic Equations by James Pate Williams, Jr.

z1 = complex(0, 0)
z2 = complex(0, 0)
z3 = complex(0, 0)
z4 = complex(0, 0)

def complex_quadratic_formula(a, b, c):
    
    import cmath

    z1 = complex((-b + cmath.sqrt(b * b - 4 * a * c)) / (2 * a))
    z2 = complex((-b - cmath.sqrt(b * b - 4 * a * c)) / (2 * a))
    
    print("z1 = ", z1)
    print("z2 = ", z2)

def real_quadratic_formula(a, b, c):
    if b * b - 4 * a * c >= 0:
        
        import math
    
        z1 = float((-b + math.sqrt(b * b - 4 * a * c)) / (2 * a))
        z2 = float((-b - math.sqrt(b * b - 4 * a * c)) / (2 * a))

    else:
        
        import cmath

        z1 = complex((-b + cmath.sqrt(b * b - 4 * a * c)) / (2 * a))
        z2 = complex((-b - cmath.sqrt(b * b - 4 * a * c)) / (2 * a))
    
    print("z1 = ", z1)
    print("z2 = ", z2)

def cubic_equation(A, B, C, D):
    # https://en.wikipedia.org/wiki/Cubic_function
    # http://www.wolframalpha.com/widgets/view.jsp?id=3f4366aeb9c157cf9a30c90693eafc55

    import cmath
    import math

    A2 = float(A * A)
    B2 = float(B * B)
    B3 = float(B * B * B)
    C2 = float(C * C)
    C3 = float(C * C * C)
    D2 = float(D * D)
    Delta = float(18 * A * B * C * D - 4.0 * B3 * D
                + B2 * C2 - 4.0 * A * C3 - 27.0 * A2 * D2)
    Delta0 = float(B2 - 3.0 * A * C)
    Delta1 = float(2.0 * B3 - 9.0 * A * B * C + 27.0 * A2 * D)
    r = cmath.sqrt(-27.0 * A2 * Delta)
    c = complex(0.5 * (Delta1 + r)) ** (1.0 / 3.0)
    d = complex(0.5 * (Delta1 - r)) ** (1.0 / 3.0)

    if c.real == 0 and c.imag == 0:
        c = d

    i = complex(0.0, 1.0)
    chi = complex(-0.5, 0) + i * 0.5 * math.sqrt(3)

    import array

    ar = array.array('f', [0,0,0])
    ai = array.array('f', [0,0,0])

    for k in range(0, 3, 1):
        chik = chi ** k
        z = -(B + chik * c + Delta0 / (chik * c)) / (3.0 * A)
        ar[k] = z.real
        ai[k] = z.imag;

    z1 = ar[0] + ai[0] * complex(0, 1);
    z2 = ar[1] + ai[1] * complex(0, 1);
    z3 = ar[2] + ai[2] * complex(0, 1);
   
    print("z1 = ", z1)
    print("z2 = ", z2)
    print("z3 = ", z3)

def quartic_equation(A, B, C, D, E):
    # https://en.wikipedia.org/wiki/Quartic_function
    # https://keisan.casio.com/exec/system/1181809416

    import cmath

    A2 = float(A * A)
    A3 = float(A * A2)
    A4 = float(A2 * A2)
    B2 = float(B * B)
    B3 = float(B * B2)
    B4 = float(B2 * B2)
    C2 = float(C * C)
    C3 = float(C * C2)
    C4 = float(C2 * C2)
    D2 = float(D * D)
    D3 = float(D * D2)
    D4 = float(D2 * D2)
    E2 = float(E * E)
    E3 = float(E * E2)
    E4 = float(E2 * E2)
    Delta = float(256 * A3 * E3 - 192 * A2 * B * D * E2
                  - 128 * A2 * C2 * E2 + 144 * A2 * C * D2 * E
                  - 27 * A2 * D4 + 144 * A * B2 * C * E2
                  - 6 * A * B2 * D2 * E - 80 * A * B * C2 * D * E
                  + 18 * A * B * C * D3 + 16 * A * C4 * E
                  - 4 * A * C3 * D2 - 27 * B4 * E2 + 18 * B3 * C * D * E
                  - 4 * B3 * D3 - 4 * B2 * C3 * E + B2 * C2 * D2)
    Delta0 = float(C2 - 3 * B * D + 12 * A * E)
    Delta1 = float(2 * C3 - 9 * B * C * D
                   + 27 * B2 * E + 27 * A * D2 - 72 * A * C * E)
    p = float((8 * A * C - 3 * B2) / (8 * A2))
    q = float((B3 - 4 * A * B * C + 8 * A2 * D) / (8 * A3))
    R = cmath.sqrt(Delta1 * Delta1 - 4 * Delta0 * Delta0 * Delta0)
    P = cmath.sqrt(-27 * Delta)
    Q = complex(0.5 * (Delta1 + P)) ** complex(1.0 / 3.0)
    S = 0.5 * cmath.sqrt(((-2.0 * p) / 3.0)
                         + (Q + Delta0 / Q) / (3 * A))
    a = complex(-B / (4 * A), 0)
    s = 0.5 * cmath.sqrt(-4 * S * S - 2 * p + q / S)
    z1 = a - S + s
    z2 = a - S - s
    s = 0.5 * cmath.sqrt(-4 * S * S - 2 * p - q / S)
    z3 = a + S + s
    z4 = a + S - s

    print("z1 = ", z1)
    print("z2 = ", z2)
    print("z3 = ", z3)
    print("z4 = ", z4)

option = int(1)

print("Menu")
print("1 Solve a linear equation")
print("2 Solve a quadratic eqution")
print("3 Solve a cubic equation")
print("4 Solve a quartic equation")
print("5 Quit")

option = int(input("Option 1 to 5: "))

while option != 5:
    if option >= 1:
        a = float(input("a = "))
        b = float(input("b = "))
    if option >= 2:
        c = float(input("c = "))
    if option >= 3:
        d = float(input("d = "))
    if option == 4:
        e = float(input("e = "))

    if option == 1:
        z1 = -b / a
        print("z1 = ", z1)

    elif option == 2:
        real_quadratic_formula(a, b, c)

    elif option == 3:
        cubic_equation(a, b, c, d)

    elif option == 4:
        quartic_equation(a, b, c, d, e)

    option = int(input("Option 1 to 5: "))
Root Finder Output for Degrees 1, 2, and 3

Root Finder Output for Degrees 3 and 4