Compiler/syntax analyzer

The C and Python versions can be considered reference implementations.

;Related Tasks

* Lexical Analyzer task
* Code Generator task
* Virtual Machine Interpreter task
* AST Interpreter task

__TOC__

Solution:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

class Parser {
	private List<Token> source;
	private Token token;
	private int position;

	static class Node {
		public NodeType nt;
		public Node left, right;
		public String value;

		Node() {
			this.nt = null;
			this.left = null;
			this.right = null;
			this.value = null;
		}
		Node(NodeType node_type, Node left, Node right, String value) {
			this.nt = node_type;
			this.left = left;
			this.right = right;
			this.value = value;
		}
		public static Node make_node(NodeType nodetype, Node left, Node right) {
			return new Node(nodetype, left, right, "");
		}
		public static Node make_node(NodeType nodetype, Node left) {
			return new Node(nodetype, left, null, "");
		}
		public static Node make_leaf(NodeType nodetype, String value) {
			return new Node(nodetype, null, null, value);
		}
	}

	static class Token {
		public TokenType tokentype;
		public String value;
		public int line;
		public int pos;

		Token(TokenType token, String value, int line, int pos) {
			this.tokentype = token; this.value = value; this.line = line; this.pos = pos;
		}
		@Override
		public String toString() {
			return String.format("%5d  %5d %-15s %s", this.line, this.pos, this.tokentype, this.value);
		}
	}

	static enum TokenType {
		End_of_input(false, false, false, -1, NodeType.nd_None),
		Op_multiply(false, true, false, 13, NodeType.nd_Mul),
		Op_divide(false, true, false, 13, NodeType.nd_Div),
		Op_mod(false, true, false, 13, NodeType.nd_Mod),
		Op_add(false, true, false, 12, NodeType.nd_Add),
		Op_subtract(false, true, false, 12, NodeType.nd_Sub),
		Op_negate(false, false, true, 14, NodeType.nd_Negate),
		Op_not(false, false, true, 14, NodeType.nd_Not),
		Op_less(false, true, false, 10, NodeType.nd_Lss),
		Op_lessequal(false, true, false, 10, NodeType.nd_Leq),
		Op_greater(false, true, false, 10, NodeType.nd_Gtr),
		Op_greaterequal(false, true, false, 10, NodeType.nd_Geq),
		Op_equal(false, true, true, 9, NodeType.nd_Eql),
		Op_notequal(false, true, false, 9, NodeType.nd_Neq),
		Op_assign(false, false, false, -1, NodeType.nd_Assign),
		Op_and(false, true, false, 5, NodeType.nd_And),
		Op_or(false, true, false, 4, NodeType.nd_Or),
		Keyword_if(false, false, false, -1, NodeType.nd_If),
		Keyword_else(false, false, false, -1, NodeType.nd_None),
		Keyword_while(false, false, false, -1, NodeType.nd_While),
		Keyword_print(false, false, false, -1, NodeType.nd_None),
		Keyword_putc(false, false, false, -1, NodeType.nd_None),
		LeftParen(false, false, false, -1, NodeType.nd_None),
		RightParen(false, false, false, -1, NodeType.nd_None),
		LeftBrace(false, false, false, -1, NodeType.nd_None),
		RightBrace(false, false, false, -1, NodeType.nd_None),
		Semicolon(false, false, false, -1, NodeType.nd_None),
		Comma(false, false, false, -1, NodeType.nd_None),
		Identifier(false, false, false, -1, NodeType.nd_Ident),
		Integer(false, false, false, -1, NodeType.nd_Integer),
		String(false, false, false, -1, NodeType.nd_String);

		private final int precedence;
		private final boolean right_assoc;
		private final boolean is_binary;
		private final boolean is_unary;
		private final NodeType node_type;

		TokenType(boolean right_assoc, boolean is_binary, boolean is_unary, int precedence, NodeType node) {
			this.right_assoc = right_assoc;
			this.is_binary = is_binary;
			this.is_unary = is_unary;
			this.precedence = precedence;
			this.node_type = node;
		}
		boolean isRightAssoc() { return this.right_assoc; }
		boolean isBinary() { return this.is_binary; }
		boolean isUnary() { return this.is_unary; }
		int getPrecedence() { return this.precedence; }
		NodeType getNodeType() { return this.node_type; }
	}
	static enum NodeType {
		nd_None(""), nd_Ident("Identifier"), nd_String("String"), nd_Integer("Integer"), nd_Sequence("Sequence"), nd_If("If"),
		nd_Prtc("Prtc"), nd_Prts("Prts"), nd_Prti("Prti"), nd_While("While"),
		nd_Assign("Assign"), nd_Negate("Negate"), nd_Not("Not"), nd_Mul("Multiply"), nd_Div("Divide"), nd_Mod("Mod"), nd_Add("Add"),
		nd_Sub("Subtract"), nd_Lss("Less"), nd_Leq("LessEqual"),
		nd_Gtr("Greater"), nd_Geq("GreaterEqual"), nd_Eql("Equal"), nd_Neq("NotEqual"), nd_And("And"), nd_Or("Or");

		private final String name;

		NodeType(String name) {
			this.name = name;
		}

		@Override
		public String toString() { return this.name; }
	}
	static void error(int line, int pos, String msg) {
		if (line > 0 && pos > 0) {
			System.out.printf("%s in line %d, pos %d\n", msg, line, pos);
		} else {
			System.out.println(msg);
		}
		System.exit(1);
	}
	Parser(List<Token> source) {
		this.source = source;
		this.token = null;
		this.position = 0;
	}
	Token getNextToken() {
		this.token = this.source.get(this.position++);
		return this.token;
	}
	Node expr(int p) {
		Node result = null, node;
		TokenType op;
		int q;

		if (this.token.tokentype == TokenType.LeftParen) {
			result = paren_expr();
		} else if (this.token.tokentype == TokenType.Op_add || this.token.tokentype == TokenType.Op_subtract) {
			op = (this.token.tokentype == TokenType.Op_subtract) ? TokenType.Op_negate : TokenType.Op_add;
			getNextToken();
			node = expr(TokenType.Op_negate.getPrecedence());
			result = (op == TokenType.Op_negate) ? Node.make_node(NodeType.nd_Negate, node) : node;
		} else if (this.token.tokentype == TokenType.Op_not) {
			getNextToken();
			result = Node.make_node(NodeType.nd_Not, expr(TokenType.Op_not.getPrecedence()));
		} else if (this.token.tokentype == TokenType.Identifier) {
			result = Node.make_leaf(NodeType.nd_Ident, this.token.value);
			getNextToken();
		} else if (this.token.tokentype == TokenType.Integer) {
			result = Node.make_leaf(NodeType.nd_Integer, this.token.value);
			getNextToken();
		} else {
			error(this.token.line, this.token.pos, "Expecting a primary, found: " + this.token.tokentype);
		}

		while (this.token.tokentype.isBinary() && this.token.tokentype.getPrecedence() >= p) {
			op = this.token.tokentype;
			getNextToken();
			q = op.getPrecedence();
			if (!op.isRightAssoc()) {
				q++;
			}
			node = expr(q);
			result = Node.make_node(op.getNodeType(), result, node);
		}
		return result;
	}
	Node paren_expr() {
		expect("paren_expr", TokenType.LeftParen);
		Node node = expr(0);
		expect("paren_expr", TokenType.RightParen);
		return node;
	}
	void expect(String msg, TokenType s) {
		if (this.token.tokentype == s) {
			getNextToken();
			return;
		}
		error(this.token.line, this.token.pos, msg + ": Expecting '" + s + "', found: '" + this.token.tokentype + "'");
	}
	Node stmt() {
		Node s, s2, t = null, e, v;
		if (this.token.tokentype == TokenType.Keyword_if) {
			getNextToken();
			e = paren_expr();
			s = stmt();
			s2 = null;
			if (this.token.tokentype == TokenType.Keyword_else) {
				getNextToken();
				s2 = stmt();
			}
			t = Node.make_node(NodeType.nd_If, e, Node.make_node(NodeType.nd_If, s, s2));
		} else if (this.token.tokentype == TokenType.Keyword_putc) {
			getNextToken();
			e = paren_expr();
			t = Node.make_node(NodeType.nd_Prtc, e);
			expect("Putc", TokenType.Semicolon);
		} else if (this.token.tokentype == TokenType.Keyword_print) {
			getNextToken();
			expect("Print", TokenType.LeftParen);
			while (true) {
				if (this.token.tokentype == TokenType.String) {
					e = Node.make_node(NodeType.nd_Prts, Node.make_leaf(NodeType.nd_String, this.token.value));
					getNextToken();
				} else {
					e = Node.make_node(NodeType.nd_Prti, expr(0), null);
				}
				t = Node.make_node(NodeType.nd_Sequence, t, e);
				if (this.token.tokentype != TokenType.Comma) {
					break;
				}
				getNextToken();
			}
			expect("Print", TokenType.RightParen);
			expect("Print", TokenType.Semicolon);
		} else if (this.token.tokentype == TokenType.Semicolon) {
			getNextToken();
		} else if (this.token.tokentype == TokenType.Identifier) {
			v = Node.make_leaf(NodeType.nd_Ident, this.token.value);
			getNextToken();
			expect("assign", TokenType.Op_assign);
			e = expr(0);
			t = Node.make_node(NodeType.nd_Assign, v, e);
			expect("assign", TokenType.Semicolon);
		} else if (this.token.tokentype == TokenType.Keyword_while) {
			getNextToken();
			e = paren_expr();
			s = stmt();
			t = Node.make_node(NodeType.nd_While, e, s);
		} else if (this.token.tokentype == TokenType.LeftBrace) {
			getNextToken();
			while (this.token.tokentype != TokenType.RightBrace && this.token.tokentype != TokenType.End_of_input) {
				t = Node.make_node(NodeType.nd_Sequence, t, stmt());
			}
			expect("LBrace", TokenType.RightBrace);
		} else if (this.token.tokentype == TokenType.End_of_input) {
		} else {
			error(this.token.line, this.token.pos, "Expecting start of statement, found: " + this.token.tokentype);
		}
		return t;
	}
	Node parse() {
		Node t = null;
		getNextToken();
		while (this.token.tokentype != TokenType.End_of_input) {
			t = Node.make_node(NodeType.nd_Sequence, t, stmt());
		}
		return t;
	}
	void printAST(Node t) {
		int i = 0;
		if (t == null) {
			System.out.println(";");
		} else {
			System.out.printf("%-14s", t.nt);
			if (t.nt == NodeType.nd_Ident || t.nt == NodeType.nd_Integer || t.nt == NodeType.nd_String) {
				System.out.println(" " + t.value);
			} else {
				System.out.println();
				printAST(t.left);
				printAST(t.right);
			}
		}
	}
	public static void main(String[] args) {
		if (args.length > 0) {
			try {
				String value, token;
				int line, pos;
				Token t;
				boolean found;
				List<Token> list = new ArrayList<>();
				Map<String, TokenType> str_to_tokens = new HashMap<>();

				str_to_tokens.put("End_of_input", TokenType.End_of_input);
				str_to_tokens.put("Op_multiply", TokenType.Op_multiply);
				str_to_tokens.put("Op_divide", TokenType.Op_divide);
				str_to_tokens.put("Op_mod", TokenType.Op_mod);
				str_to_tokens.put("Op_add", TokenType.Op_add);
				str_to_tokens.put("Op_subtract", TokenType.Op_subtract);
				str_to_tokens.put("Op_negate", TokenType.Op_negate);
				str_to_tokens.put("Op_not", TokenType.Op_not);
				str_to_tokens.put("Op_less", TokenType.Op_less);
				str_to_tokens.put("Op_lessequal", TokenType.Op_lessequal);
				str_to_tokens.put("Op_greater", TokenType.Op_greater);
				str_to_tokens.put("Op_greaterequal", TokenType.Op_greaterequal);
				str_to_tokens.put("Op_equal", TokenType.Op_equal);
				str_to_tokens.put("Op_notequal", TokenType.Op_notequal);
				str_to_tokens.put("Op_assign", TokenType.Op_assign);
				str_to_tokens.put("Op_and", TokenType.Op_and);
				str_to_tokens.put("Op_or", TokenType.Op_or);
				str_to_tokens.put("Keyword_if", TokenType.Keyword_if);
				str_to_tokens.put("Keyword_else", TokenType.Keyword_else);
				str_to_tokens.put("Keyword_while", TokenType.Keyword_while);
				str_to_tokens.put("Keyword_print", TokenType.Keyword_print);
				str_to_tokens.put("Keyword_putc", TokenType.Keyword_putc);
				str_to_tokens.put("LeftParen", TokenType.LeftParen);
				str_to_tokens.put("RightParen", TokenType.RightParen);
				str_to_tokens.put("LeftBrace", TokenType.LeftBrace);
				str_to_tokens.put("RightBrace", TokenType.RightBrace);
				str_to_tokens.put("Semicolon", TokenType.Semicolon);
				str_to_tokens.put("Comma", TokenType.Comma);
				str_to_tokens.put("Identifier", TokenType.Identifier);
				str_to_tokens.put("Integer", TokenType.Integer);
				str_to_tokens.put("String", TokenType.String);

				Scanner s = new Scanner(new File(args[0]));
				String source = " ";
				while (s.hasNext()) {
					String str = s.nextLine();
					StringTokenizer st = new StringTokenizer(str);
					line = Integer.parseInt(st.nextToken());
					pos = Integer.parseInt(st.nextToken());
					token = st.nextToken();
					value = "";
					while (st.hasMoreTokens()) {
						value += st.nextToken() + " ";
					}
					found = false;
					if (str_to_tokens.containsKey(token)) {
						found = true;
						list.add(new Token(str_to_tokens.get(token), value, line, pos));
					}
					if (found == false) {
						throw new Exception("Token not found: '" + token + "'");
					}
				}
				Parser p = new Parser(list);
				p.printAST(p.parse());
			} catch (FileNotFoundException e) {
				error(-1, -1, "Exception: " + e.getMessage());
			} catch (Exception e) {
				error(-1, -1, "Exception: " + e.getMessage());
			}
		} else {
			error(-1, -1, "No args");
		}
	}
}


Conjugate transpose

Suppose that a conjugate transpose of M is a matrix M^H containing the [[complex conjugate]]s of the [[matrix transposition]] of M.

::: (M^H)_{ji} = \overline{M_{ij}}

This means that   row j, column i of the conjugate transpose equals the
complex conjugate of row i, column j of the original matrix.

In the next list, M must also be a square matrix.

* A Hermitian matrix equals its own conjugate transpose: M^H = M.
* A multiplication with its conjugate transpose: M^HM = MM^H.
* A iff M^HM = I_n and iff MM^H = I_n, where I_n is the identity matrix.

;Task:
Given some matrix of complex numbers, find its conjugate transpose.

Also determine if the matrix is a:
::* Hermitian matrix,
::* normal matrix,  or
::* unitary matrix.

;See also:
* MathWorld entry: conjugate transpose
* MathWorld entry: Hermitian matrix
* MathWorld entry: normal matrix
* MathWorld entry: unitary matrix

Solution:
import java.util.Arrays;
import java.util.List;

public final class ConjugateTranspose {

	public static void main(String[] aArgs) {
		ComplexMatrix one = new ComplexMatrix( new Complex[][] { { new Complex(0, 4), new Complex(-1, 1) },
											                     { new Complex(1, -1), new Complex(0, 4) } } );

		ComplexMatrix two = new ComplexMatrix(
			new Complex[][] { { new Complex(1, 0), new Complex(1, 1), new Complex(0, 2) },
			     			  { new Complex(1, -1), new Complex(5, 0), new Complex(-3, 0) },
							  { new Complex(0, -2), new Complex(-3, 0), new Complex(0, 0) } } );

		final double term = 1.0 / Math.sqrt(2.0);
		ComplexMatrix three = new ComplexMatrix( new Complex[][] { { new Complex(term, 0), new Complex(term, 0) },
																   { new Complex(0, term), new Complex(0, -term) } } );

		List<ComplexMatrix> matricies = List.of( one, two, three );
		for ( ComplexMatrix matrix : matricies ) {
			System.out.println("Matrix:");
			matrix.display();
			System.out.println("Conjugate transpose:");
			matrix.conjugateTranspose().display();
			System.out.println("Hermitian: " + matrix.isHermitian());
			System.out.println("Normal: " + matrix.isNormal());
			System.out.println("Unitary: " + matrix.isUnitary() + System.lineSeparator());
		}
	}

}

final class ComplexMatrix {

	public ComplexMatrix(Complex[][] aData) {
		rowCount = aData.length;
        colCount = aData[0].length;
        data = Arrays.stream(aData).map( row -> Arrays.copyOf(row, row.length) ).toArray(Complex[][]::new);
	}

	public ComplexMatrix multiply(ComplexMatrix aOther) {
        if ( colCount != aOther.rowCount ) {
        	throw new RuntimeException("Incompatible matrix dimensions.");
        }
        Complex[][] newData = new Complex[rowCount][aOther.colCount];
        Arrays.stream(newData).forEach( row -> Arrays.fill(row, new Complex(0, 0)) );
        for ( int row = 0; row < rowCount; row++ ) {
            for ( int col = 0; col < aOther.colCount; col++ ) {
                for ( int k = 0; k < colCount; k++ ) {
                    newData[row][col] = newData[row][col].add(data[row][k].multiply(aOther.data[k][col]));
                }
            }
        }
        return new ComplexMatrix(newData);
    }

    public ComplexMatrix conjugateTranspose() {
    	if ( rowCount != colCount ) {
    		throw new IllegalArgumentException("Only applicable to a square matrix");
    	}
    	Complex[][] newData = new Complex[colCount][rowCount];
        for ( int row = 0; row < rowCount; row++ ) {
            for ( int col = 0; col < colCount; col++ ) {
                newData[col][row] = data[row][col].conjugate();
            }
        }
        return new ComplexMatrix(newData);
    }

    public static ComplexMatrix identity(int aSize) {
    	Complex[][] data = new Complex[aSize][aSize];
        for ( int row = 0; row < aSize; row++ ) {
        	for ( int col = 0; col < aSize; col++ ) {
        		data[row][col] = ( row == col ) ? new Complex(1, 0) : new Complex(0, 0);
        	}
        }
        return new ComplexMatrix(data);
    }

    public boolean equals(ComplexMatrix aOther) {
        if ( aOther.rowCount != rowCount || aOther.colCount != colCount ) {
        	return false;
        }
        for ( int row = 0; row < rowCount; row++ ) {
            for ( int col = 0; col < colCount; col++ ) {
            	if ( data[row][col].subtract(aOther.data[row][col]).modulus() > EPSILON ) {
                	return false;
                }
            }
        }
        return true;
    }

    public void display() {
        for ( int row = 0; row < rowCount; row++ ) {
        	System.out.print("[");
            for ( int col = 0; col < colCount - 1; col++ ) {
                System.out.print(data[row][col] + ", ");
            }
            System.out.println(data[row][colCount - 1] + " ]");
        }
    }

    public boolean isHermitian() {
    	return equals(conjugateTranspose());
    }

    public boolean isNormal() {
    	ComplexMatrix conjugateTranspose = conjugateTranspose();
    	return multiply(conjugateTranspose).equals(conjugateTranspose.multiply(this));
    }

    public boolean isUnitary() {
    	ComplexMatrix conjugateTranspose = conjugateTranspose();
    	return multiply(conjugateTranspose).equals(identity(rowCount)) &&
    		   conjugateTranspose.multiply(this).equals(identity(rowCount));
    }

    private final int rowCount;
    private final int colCount;
    private final Complex[][] data;

    private static final double EPSILON = 0.000_000_000_001;

}

final class Complex {

	public Complex(double aReal, double aImag) {
		real = aReal;
		imag = aImag;
	}

	public Complex add(Complex aOther) {
		return new Complex(real + aOther.real, imag + aOther.imag);
	}

	public Complex multiply(Complex aOther) {
		return new Complex(real * aOther.real - imag * aOther.imag, real * aOther.imag + imag * aOther.real);
	}

	public Complex negate() {
		return new Complex(-real, -imag);
	}

	public Complex subtract(Complex aOther) {
		return this.add(aOther.negate());
	}

	public Complex conjugate() {
		return new Complex(real, -imag);
	}

	public double modulus() {
		return Math.hypot(real, imag);
	}

	public boolean equals(Complex aOther) {
		return real == aOther.real && imag == aOther.imag;
	}

	@Override
	public String toString() {
		String prefix = ( real < 0.0 ) ? "" : " ";
		String realPart = prefix + String.format("%.3f", real);
		String sign = ( imag < 0.0 ) ? " - " : " + ";
		return realPart + sign + String.format("%.3f", Math.abs(imag)) + "i";
	}

	private final double real;
	private final double imag;

}


Continued fraction

A number may be represented as a continued fraction (see Mathworld for more information) as follows:
:a_0 + \cfrac{b_1}{a_1 + \cfrac{b_2}{a_2 + \cfrac{b_3}{a_3 + \ddots}}}

The task is to write a program which generates such a number and prints a real representation of it. The code should be tested by calculating and printing the square root of 2, Napier's Constant, and Pi, using the following coefficients:

For the square root of 2, use a_0 = 1 then a_N = 2. b_N is always 1.

:\sqrt{2} = 1 + \cfrac{1}{2 + \cfrac{1}{2 + \cfrac{1}{2 + \ddots}}}

For Napier's Constant, use a_0 = 2, then a_N = N. b_1 = 1 then b_N = N-1.

:e = 2 + \cfrac{1}{1 + \cfrac{1}{2 + \cfrac{2}{3 + \cfrac{3}{4 + \ddots}}}}

For Pi, use a_0 = 3 then a_N = 6. b_N = (2N-1)^2.

:\pi = 3 + \cfrac{1}{6 + \cfrac{9}{6 + \cfrac{25}{6 + \ddots}}}

;See also:
:*   [[Continued fraction/Arithmetic]] for tasks that do arithmetic over continued fractions.

Solution:
import static java.lang.Math.pow;
import java.util.*;
import java.util.function.Function;

public class Test {
    static double calc(Function<Integer, Integer[]> f, int n) {
        double temp = 0;

        for (int ni = n; ni >= 1; ni--) {
            Integer[] p = f.apply(ni);
            temp = p[1] / (double) (p[0] + temp);
        }
        return f.apply(0)[0] + temp;
    }

    public static void main(String[] args) {
        List<Function<Integer, Integer[]>> fList = new ArrayList<>();
        fList.add(n -> new Integer[]{n > 0 ? 2 : 1, 1});
        fList.add(n -> new Integer[]{n > 0 ? n : 2, n > 1 ? (n - 1) : 1});
        fList.add(n -> new Integer[]{n > 0 ? 6 : 3, (int) pow(2 * n - 1, 2)});

        for (Function<Integer, Integer[]> f : fList)
            System.out.println(calc(f, 200));
    }
}


Continued fraction/Arithmetic/Construct from rational number

To understand this task in context please see [[Continued fraction arithmetic]]
The purpose of this task is to write a function \mathit{r2cf}(\mathrm{int} N_1, \mathrm{int} N_2), or \mathit{r2cf}(\mathrm{Fraction} N), which will output a continued fraction assuming:
:N_1 is the numerator
:N_2 is the denominator

The function should output its results one digit at a time each time it is called, in a manner sometimes described as lazy evaluation.

To achieve this it must determine: the integer part; and remainder part, of N_1 divided by N_2. It then sets N_1 to N_2 and N_2 to the determined remainder part. It then outputs the determined integer part. It does this until \mathrm{abs}(N_2) is zero.

Demonstrate the function by outputing the continued fraction for:
: 1/2
: 3
: 23/8
: 13/11
: 22/7
: -151/77
\sqrt 2 should approach [1; 2, 2, 2, 2, \ldots] try ever closer rational approximations until boredom gets the better of you:
: 14142,10000
: 141421,100000
: 1414214,1000000
: 14142136,10000000

Try :
: 31,10
: 314,100
: 3142,1000
: 31428,10000
: 314285,100000
: 3142857,1000000
: 31428571,10000000
: 314285714,100000000

Observe how this rational number behaves differently to \sqrt 2 and convince yourself that, in the same way as 3.7 may be represented as 3.70 when an extra decimal place is required, [3;7] may be represented as [3;7,\infty] when an extra term is required.

Solution:
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ConstructFromRationalNumber {
    private static class R2cf implements Iterator<Integer> {
        private int num;
        private int den;

        R2cf(int num, int den) {
            this.num = num;
            this.den = den;
        }

        @Override
        public boolean hasNext() {
            return den != 0;
        }

        @Override
        public Integer next() {
            int div = num / den;
            int rem = num % den;
            num = den;
            den = rem;
            return div;
        }
    }

    private static void iterate(R2cf generator) {
        generator.forEachRemaining(n -> System.out.printf("%d ", n));
        System.out.println();
    }

    public static void main(String[] args) {
        List<Map.Entry<Integer, Integer>> fracs = List.of(
                Map.entry(1, 2),
                Map.entry(3, 1),
                Map.entry(23, 8),
                Map.entry(13, 11),
                Map.entry(22, 7),
                Map.entry(-151, 77)
        );
        for (Map.Entry<Integer, Integer> frac : fracs) {
            System.out.printf("%4d / %-2d = ", frac.getKey(), frac.getValue());
            iterate(new R2cf(frac.getKey(), frac.getValue()));
        }

        System.out.println("\nSqrt(2) ->");
        List<Map.Entry<Integer, Integer>> root2 = List.of(
                Map.entry(    14_142,     10_000),
                Map.entry(   141_421,    100_000),
                Map.entry( 1_414_214,  1_000_000),
                Map.entry(14_142_136, 10_000_000)
        );
        for (Map.Entry<Integer, Integer> frac : root2) {
            System.out.printf("%8d / %-8d = ", frac.getKey(), frac.getValue());
            iterate(new R2cf(frac.getKey(), frac.getValue()));
        }

        System.out.println("\nPi ->");
        List<Map.Entry<Integer, Integer>> pi = List.of(
                Map.entry(         31,        10),
                Map.entry(        314,       100),
                Map.entry(      3_142,      1_000),
                Map.entry(     31_428,     10_000),
                Map.entry(    314_285,    100_000),
                Map.entry(  3_142_857,   1_000_000),
                Map.entry( 31_428_571,  10_000_000),
                Map.entry(314_285_714, 100_000_000)
        );
        for (Map.Entry<Integer, Integer> frac : pi) {
            System.out.printf("%9d / %-9d = ", frac.getKey(), frac.getValue());
            iterate(new R2cf(frac.getKey(), frac.getValue()));
        }
    }
}


Convert decimal number to rational

The task is to write a program to transform a decimal number into a fraction in lowest terms.

It is not always possible to do this exactly. For instance, while rational numbers can be converted to decimal representation, some of them need an infinite number of digits to be represented exactly in decimal form. Namely, repeating decimals such as 1/3 = 0.333...

Because of this, the following fractions cannot be obtained (reliably) unless the language has some way of representing repeating decimals:
* 67 / 74 = 0.9(054) = 0.9054054...
* 14 / 27 = 0.(518)  = 0.518518...

Acceptable output:

* 0.9054054 - 4527027 / 5000000
* 0.518518  - 259259 / 500000

Finite decimals are of course no problem:

* 0.75      - 3 / 4

Solution:
double fractionToDecimal(String string) {
    int indexOf = string.indexOf(' ');
    int integer = 0;
    int numerator, denominator;
    if (indexOf != -1) {
        integer = Integer.parseInt(string.substring(0, indexOf));
        string = string.substring(indexOf + 1);
    }
    indexOf = string.indexOf('/');
    numerator = Integer.parseInt(string.substring(0, indexOf));
    denominator = Integer.parseInt(string.substring(indexOf + 1));
    return integer + ((double) numerator / denominator);
}

String decimalToFraction(double value) {
    String string = String.valueOf(value);
    string = string.substring(string.indexOf('.') + 1);
    int numerator = Integer.parseInt(string);
    int denominator = (int) Math.pow(10, string.length());
    int gcf = gcf(numerator, denominator);
    if (gcf != 0) {
        numerator /= gcf;
        denominator /= gcf;
    }
    int integer = (int) value;
    if (integer != 0)
        return "%d %d/%d".formatted(integer, numerator, denominator);
    return "%d/%d".formatted(numerator, denominator);
}

int gcf(int valueA, int valueB) {
    if (valueB == 0) return valueA;
    else return gcf(valueB, valueA % valueB);
}


Convert seconds to compound duration

Write a function or program which:
*   takes a positive integer representing a duration in seconds as input (e.g., 100), and
*   returns a string which shows the same duration decomposed into:
:::*   weeks,
:::*   days,
:::*   hours,
:::*   minutes,   and
:::*   seconds.

This is detailed below (e.g., "2 hr, 59 sec").

Demonstrate that it passes the following three test-cases:

'''''Test Cases'''''

:::::{| class="wikitable"
|-
! input number
! output string
|-
| 7259
| 2 hr, 59 sec
|-
| 86400
| 1 d
|-
| 6000000
| 9 wk, 6 d, 10 hr, 40 min
|}

'''''Details'''''

The following five units should be used:
:::::{| class="wikitable"
|-
! unit
! suffix used in output
! conversion
|-
| week
| wk
| 1 week = 7 days
|-
| day
| d
| 1 day = 24 hours
|-
| hour
| hr
| 1 hour = 60 minutes
|-
| minute
| min
| 1 minute = 60 seconds
|-
| second
| sec
|
|}

However, '''only''' include quantities with non-zero values in the output (e.g., return "1 d" and not "0 wk, 1 d, 0 hr, 0 min, 0 sec").

Give larger units precedence over smaller ones as much as possible (e.g., return 2 min, 10 sec and not 1 min, 70 sec or 130 sec)

Mimic the formatting shown in the test-cases (quantities sorted from largest unit to smallest and separated by comma+space; value and unit of each quantity separated by space).

Solution:
String duration(int seconds) {
    StringBuilder string = new StringBuilder();
    if (seconds >= 604_800 /* 1 wk */) {
        string.append("%,d wk".formatted(seconds / 604_800));
        seconds %= 604_800;
    }
    if (seconds >= 86_400 /* 1 d */) {
        if (!string.isEmpty()) string.append(", ");
        string.append("%d d".formatted(seconds / 86_400));
        seconds %= 86_400;
    }
    if (seconds >= 3600 /* 1 hr */) {
        if (!string.isEmpty()) string.append(", ");
        string.append("%d hr".formatted(seconds / 3600));
        seconds %= 3600;
    }
    if (seconds >= 60 /* 1 min */) {
        if (!string.isEmpty()) string.append(", ");
        string.append("%d min".formatted(seconds / 60));
        seconds %= 60;
    }
    if (seconds > 0) {
        if (!string.isEmpty()) string.append(", ");
        string.append("%d sec".formatted(seconds));
    }
    return string.toString();
}


Copy stdin to stdout

Create an executable file that copies stdin to stdout, or else a script that does so through the invocation of an interpreter at the command line.

Solution:
import java.util.Scanner;

public class CopyStdinToStdout {

    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in);) {
            String s;
            while ( (s = scanner.nextLine()).compareTo("") != 0 ) {
                System.out.println(s);
            }
        }
    }

}


Count the coins

There are four types of common coins in   US   currency:
:::#   quarters   (25 cents)
:::#   dimes   (10 cents)
:::#   nickels   (5 cents),   and
:::#   pennies   (1 cent)

There are six ways to make change for 15 cents:
:::#   A dime and a nickel
:::#   A dime and 5 pennies
:::#   3 nickels
:::#   2 nickels and 5 pennies
:::#   A nickel and 10 pennies
:::#   15 pennies

;Task:
How many ways are there to make change for a dollar using these common coins?     (1 dollar = 100 cents).

;Optional:
Less common are dollar coins (100 cents);   and very rare are half dollars (50 cents).   With the addition of these two coins, how many ways are there to make change for $1000?

(Note:   the answer is larger than   232).

;References:
* an algorithm from the book ''Structure and Interpretation of Computer Programs''.
* an article in the algorithmist.
* Change-making problem on Wikipedia.

Solution:
import java.util.Arrays;
import java.math.BigInteger;

class CountTheCoins {
    private static BigInteger countChanges(int amount, int[] coins){
        final int n = coins.length;
        int cycle = 0;
        for (int c : coins)
            if (c <= amount && c >= cycle)
                cycle = c + 1;
        cycle *= n;
        BigInteger[] table = new BigInteger[cycle];
        Arrays.fill(table, 0, n, BigInteger.ONE);
        Arrays.fill(table, n, cycle, BigInteger.ZERO);

        int pos = n;
        for (int s = 1; s <= amount; s++) {
            for (int i = 0; i < n; i++) {
                if (i == 0 && pos >= cycle)
                    pos = 0;
                if (coins[i] <= s) {
                    final int q = pos - (coins[i] * n);
                    table[pos] = (q >= 0) ? table[q] : table[q + cycle];
                }
                if (i != 0)
                    table[pos] = table[pos].add(table[pos - 1]);
                pos++;
            }
        }

        return table[pos - 1];
    }

    public static void main(String[] args) {
        final int[][] coinsUsEu = {{100, 50, 25, 10, 5, 1},
                                   {200, 100, 50, 20, 10, 5, 2, 1}};

        for (int[] coins : coinsUsEu) {
            System.out.println(countChanges(     100,
                Arrays.copyOfRange(coins, 2, coins.length)));
            System.out.println(countChanges(  100000, coins));
            System.out.println(countChanges( 1000000, coins));
            System.out.println(countChanges(10000000, coins) + "\n");
        }
    }
}


Create an HTML table

Create an HTML table.
* The table body should have at least three rows of three columns.
* Each of these three columns should be labelled "X", "Y", and "Z".
* An extra column should be added at either the extreme left or the extreme right of the table that has no heading, but is filled with sequential row numbers.
* The rows of the "X", "Y", and "Z" columns should be filled with random or sequential integers having 4 digits or less.
* The numbers should be aligned in the same fashion for all columns.

Solution:
String generateHTMLTable() {
    StringBuilder string = new StringBuilder();
    string.append("
");
    string.append(System.lineSeparator());
    string.append("
".indent(2));
    string.append("	".indent(4));
    string.append("X	".indent(4));
    string.append("Y	".indent(4));
    string.append("Z	".indent(4));
    string.append("
".indent(2));
    Random random = new Random();
    int number;
    for (int countA = 0; countA < 10; countA++) {
        string.append("
".indent(2));
        string.append("%d	".formatted(countA).indent(4));
        for (int countB = 0; countB < 3; countB++) {
            number = random.nextInt(1, 9999);
            string.append("%,d	".formatted(number).indent(4));
        }
        string.append("
".indent(2));
    }
    string.append("
");
    return string.toString();
}


Create an HTML table

Solution:
public class HTML {

	public static String array2HTML(Object[][] array){
		StringBuilder html = new StringBuilder(
				"
");
		for(Object elem:array[0]){
			html.append("" + elem.toString() + "	");
		}
		for(int i = 1; i < array.length; i++){
			Object[] row = array[i];
			html.append("
");
			for(Object elem:row){
				html.append("" + elem.toString() + "	");
			}
			html.append("
");
		}
		html.append("
");
		return html.toString();
	}

	public static void main(String[] args){
		Object[][] ints = {{"","X","Y","Z"},{1,1,2,3},{2,4,5,6},{3,7,8,9},{4,10,11,12}};
		System.out.println(array2HTML(ints));
	}
}


Cullen and Woodall numbers

A Cullen number is a number of the form '''n x 2n + 1''' where '''n''' is a natural number.

A Woodall number is very similar. It is a number of the form '''n x 2n - 1''' where '''n''' is a natural number.

So for each '''n''' the associated Cullen number and Woodall number differ by 2.

''Woodall numbers are sometimes referred to as Riesel numbers or Cullen numbers of the second kind.''

'''Cullen primes''' are Cullen numbers that are prime. Similarly, '''Woodall primes''' are Woodall numbers that are prime.

It is common to list the Cullen and Woodall primes by the value of '''n''' rather than the full evaluated expression. They tend to get very large very quickly. For example, the third Cullen prime, '''n''' == 4713, has 1423 digits when evaluated.

;Task

* Write procedures to find Cullen numbers and Woodall numbers.

* Use those procedures to find and show here, on this page the first 20 of each.

;Stretch

* Find and show the first '''5''' '''Cullen primes''' in terms of '''n'''.

* Find and show the first '''12''' '''Woodall primes''' in terms of '''n'''.

;See also

* OEIS:A002064 - Cullen numbers: a(n) = n*2^n + 1

* OEIS:A003261 - Woodall (or Riesel) numbers: n*2^n - 1

* OEIS:A005849 - Indices of prime Cullen numbers: numbers k such that k*2^k + 1 is prime

* OEIS:A002234 - Numbers k such that the Woodall number k*2^k - 1 is prime

Solution:
import java.math.BigInteger;

public final  class CullenAndWoodhall {

	public static void main(String[] aArgs) {
		numberSequence(20, NumberType.Cullen);

		numberSequence(20, NumberType.Woodhall);

		primeSequence(5, NumberType.Cullen);

		primeSequence(12, NumberType.Woodhall);
	}

	private enum NumberType { Cullen, Woodhall }

	private static void numberSequence(int aCount, NumberType aNumberType) {
		System.out.println();
		System.out.println("The first " + aCount + " " + aNumberType + " numbers are:");
		numberInitialise();
		for ( int index = 1; index <= aCount; index++ ) {
			System.out.print(nextNumber(aNumberType) + " ");
		}
		System.out.println();
	}

	private static void primeSequence(int aCount, NumberType aNumberType) {
		System.out.println();
		System.out.println("The indexes of the first " + aCount + " " + aNumberType + " primes are:");
		primeInitialise();

		while ( count < aCount ) {
			if ( nextNumber(aNumberType).isProbablePrime(CERTAINTY) ) {
				System.out.print(primeIndex + " ");
				count += 1;
			}

			primeIndex += 1;
		}
		System.out.println();
	}

	private static BigInteger nextNumber(NumberType aNumberType) {
		number = number.add(BigInteger.ONE);
		power = power.shiftLeft(1);
		return switch ( aNumberType ) {
			case Cullen -> number.multiply(power).add(BigInteger.ONE);
			case Woodhall -> number.multiply(power).subtract(BigInteger.ONE);
		};
	}

	private static void numberInitialise() {
		number = BigInteger.ZERO;
		power = BigInteger.ONE;
	}

	private static void primeInitialise() {
		count = 0;
		primeIndex = 1;
		numberInitialise();
	}

	private static BigInteger number;
	private static BigInteger power;
	private static int count;
	private static int primeIndex;

	private static final int CERTAINTY = 20;

}


Currency

Show how to represent currency in a simple example, using a data type that represent exact values of dollars and cents.

;Note:
The '''IEEE 754''' binary floating point representations of numbers like   '''2.86'''   and   '''.0765'''   are not exact.

For this example, data will be two items with prices in dollars and cents, a quantity for each, and a tax rate.

Use the values:
::* 4000000000000000 hamburgers at $5.50 each       (four quadrillion burgers)
::* 2 milkshakes at $2.86 each, and
::* a tax rate of 7.65%.

(That number of hamburgers is a 4 with 15 zeros after it.    The number is contrived to exclude naive task solutions using 64 bit floating point types.)

Compute and output (show results on this page):
::* the total price before tax
::* the tax
::* the total with tax

The tax value must be computed by rounding to the nearest whole cent and this exact value must be added to the total price before tax.

The output must show dollars and cents with a decimal point.

The three results displayed should be:
::* 22000000000000005.72
::* 1683000000000000.44
::* 23683000000000006.16

Dollar signs and thousands separators are optional.

Solution:
import java.math.*;
import java.util.*;

public class Currency {
    final static String taxrate = "7.65";

    enum MenuItem {

        Hamburger("5.50"), Milkshake("2.86");

        private MenuItem(String p) {
            price = new BigDecimal(p);
        }

        public final BigDecimal price;
    }

    public static void main(String[] args) {
        Locale.setDefault(Locale.ENGLISH);

        MathContext mc = MathContext.DECIMAL128;

        Map<MenuItem, BigDecimal> order = new HashMap<>();
        order.put(MenuItem.Hamburger, new BigDecimal("4000000000000000"));
        order.put(MenuItem.Milkshake, new BigDecimal("2"));

        BigDecimal subtotal = BigDecimal.ZERO;
        for (MenuItem it : order.keySet())
            subtotal = subtotal.add(it.price.multiply(order.get(it), mc));

        BigDecimal tax = new BigDecimal(taxrate, mc);
        tax = tax.divide(new BigDecimal("100"), mc);
        tax = subtotal.multiply(tax, mc);

        System.out.printf("Subtotal: %20.2f%n", subtotal);
        System.out.printf("     Tax: %20.2f%n", tax);
        System.out.printf("   Total: %20.2f%n", subtotal.add(tax));
    }
}


Currying

{{Wikipedia|Currying}}

;Task:
Create a simple demonstrative example of Currying in a specific language.

Add any historic details as to how the feature made its way into the language.

Solution:
public class Currier<ARG1, ARG2, RET> {
        public interface CurriableFunctor<ARG1, ARG2, RET> {
            RET evaluate(ARG1 arg1, ARG2 arg2);
        }

        public interface CurriedFunctor<ARG2, RET> {
            RET evaluate(ARG2 arg);
        }

        final CurriableFunctor<ARG1, ARG2, RET> functor;

        public Currier(CurriableFunctor<ARG1, ARG2, RET> fn) { functor = fn; }

        public CurriedFunctor<ARG2, RET> curry(final ARG1 arg1) {
            return new CurriedFunctor<ARG2, RET>() {
                public RET evaluate(ARG2 arg2) {
                    return functor.evaluate(arg1, arg2);
                }
            };
        }

        public static void main(String[] args) {
            Currier.CurriableFunctor<Integer, Integer, Integer> add
                = new Currier.CurriableFunctor<Integer, Integer, Integer>() {
                    public Integer evaluate(Integer arg1, Integer arg2) {
                        return new Integer(arg1.intValue() + arg2.intValue());
                    }
            };

            Currier<Integer, Integer, Integer> currier
                = new Currier<Integer, Integer, Integer>(add);

            Currier.CurriedFunctor<Integer, Integer> add5
                = currier.curry(new Integer(5));

            System.out.println(add5.evaluate(new Integer(2)));
        }
    }


Cut a rectangle

A given rectangle is made from ''m'' x ''n'' squares. If ''m'' and ''n'' are not both odd, then it is possible to cut a path through the rectangle along the square edges such that the rectangle splits into two connected pieces with the same shape (after rotating one of the pieces by 180deg). All such paths for 2 x 2 and 4 x 3 rectangles are shown below.

[[file:rect-cut.svg]]

Write a program that calculates the number of different ways to cut an ''m'' x ''n'' rectangle.  Optionally, show each of the cuts.

Possibly related task: [[Maze generation]] for depth-first search.

Solution:
import java.util.*;

public class CutRectangle {

    private static int[][] dirs = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};

    public static void main(String[] args) {
        cutRectangle(2, 2);
        cutRectangle(4, 3);
    }

    static void cutRectangle(int w, int h) {
        if (w % 2 == 1 && h % 2 == 1)
            return;

        int[][] grid = new int[h][w];
        Stack<Integer> stack = new Stack<>();

        int half = (w * h) / 2;
        long bits = (long) Math.pow(2, half) - 1;

        for (; bits > 0; bits -= 2) {

            for (int i = 0; i < half; i++) {
                int r = i / w;
                int c = i % w;
                grid[r][c] = (bits & (1 << i)) != 0 ? 1 : 0;
                grid[h - r - 1][w - c - 1] = 1 - grid[r][c];
            }

            stack.push(0);
            grid[0][0] = 2;
            int count = 1;
            while (!stack.empty()) {

                int pos = stack.pop();
                int r = pos / w;
                int c = pos % w;

                for (int[] dir : dirs) {

                    int nextR = r + dir[0];
                    int nextC = c + dir[1];

                    if (nextR >= 0 && nextR < h && nextC >= 0 && nextC < w) {

                        if (grid[nextR][nextC] == 1) {
                            stack.push(nextR * w + nextC);
                            grid[nextR][nextC] = 2;
                            count++;
                        }
                    }
                }
            }
            if (count == half) {
                printResult(grid);
            }
        }
    }

    static void printResult(int[][] arr) {
        for (int[] a : arr)
            System.out.println(Arrays.toString(a));
        System.out.println();
    }
}


Cyclotomic polynomial

The nth Cyclotomic polynomial, for any positive integer n, is the unique irreducible polynomial of largest degree with integer coefficients that is a divisor of x^n - 1, and is not a divisor of x^k - 1 for any k < n.

;Task:
*   Find and print the first 30 cyclotomic polynomials.
*   Find and print the order of the first 10 cyclotomic polynomials that have n or -n as a coefficient.

;See also
*   Wikipedia article, Cyclotomic polynomial, showing ways to calculate them.
*   The sequence A013594 with the smallest order of cyclotomic polynomial containing n or -n as a coefficient.

Solution:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class CyclotomicPolynomial {

    @SuppressWarnings("unused")
    private static int divisions = 0;
    private static int algorithm = 2;

    public static void main(String[] args) throws Exception {
        System.out.println("Task 1:  cyclotomic polynomials for n <= 30:");
        for ( int i = 1 ; i <= 30 ; i++ ) {
            Polynomial p = cyclotomicPolynomial(i);
            System.out.printf("CP[%d] = %s%n", i, p);
        }
        System.out.println("Task 2:  Smallest cyclotomic polynomial with n or -n as a coefficient:");
        int n = 0;
        for ( int i = 1 ; i <= 10 ; i++ ) {
            while ( true ) {
                n++;
                Polynomial cyclo = cyclotomicPolynomial(n);
                if ( cyclo.hasCoefficientAbs(i) ) {
                    System.out.printf("CP[%d] has coefficient with magnitude = %d%n", n, i);
                    n--;
                    break;
                }
            }
        }
    }

    private static final Map<Integer, Polynomial> COMPUTED = new HashMap<>();

    private static Polynomial cyclotomicPolynomial(int n) {
        if ( COMPUTED.containsKey(n) ) {
            return COMPUTED.get(n);
        }

        //System.out.println("COMPUTE:  n = " + n);

        if ( n == 1 ) {
            //  Polynomial:  x - 1
            Polynomial p = new Polynomial(1, 1, -1, 0);
            COMPUTED.put(1, p);
            return p;
        }

        Map<Integer,Integer> factors = getFactors(n);

        if ( factors.containsKey(n) ) {
            //  n prime
            List<Term> termList = new ArrayList<>();
            for ( int index = 0 ; index < n ; index++ ) {
                termList.add(new Term(1, index));
            }

            Polynomial cyclo = new Polynomial(termList);
            COMPUTED.put(n, cyclo);
            return cyclo;
        }
        else if ( factors.size() == 2 && factors.containsKey(2) && factors.get(2) == 1 && factors.containsKey(n/2) && factors.get(n/2) == 1 ) {
            //  n = 2p
            int prime = n/2;
            List<Term> termList = new ArrayList<>();
            int coeff = -1;
            for ( int index = 0 ; index < prime ; index++ ) {
                coeff *= -1;
                termList.add(new Term(coeff, index));
            }

            Polynomial cyclo = new Polynomial(termList);
            COMPUTED.put(n, cyclo);
            return cyclo;
        }
        else if ( factors.size() == 1 && factors.containsKey(2) ) {
            //  n = 2^h
            int h = factors.get(2);
            List<Term> termList = new ArrayList<>();
            termList.add(new Term(1, (int) Math.pow(2, h-1)));
            termList.add(new Term(1, 0));
            Polynomial cyclo = new Polynomial(termList);
            COMPUTED.put(n, cyclo);
            return cyclo;
        }
        else if ( factors.size() == 1 && ! factors.containsKey(n) ) {
            // n = p^k
            int p = 0;
            for ( int prime : factors.keySet() ) {
                p = prime;
            }
            int k = factors.get(p);
            List<Term> termList = new ArrayList<>();
            for ( int index = 0 ; index < p ; index++ ) {
                termList.add(new Term(1, index * (int) Math.pow(p, k-1)));
            }

            Polynomial cyclo = new Polynomial(termList);
            COMPUTED.put(n, cyclo);
            return cyclo;
        }
        else if ( factors.size() == 2 && factors.containsKey(2) ) {
            //  n = 2^h * p^k
            int p = 0;
            for ( int prime : factors.keySet() ) {
                if ( prime != 2 ) {
                    p = prime;
                }
            }
            List<Term> termList = new ArrayList<>();
            int coeff = -1;
            int twoExp = (int) Math.pow(2, factors.get(2)-1);
            int k = factors.get(p);
            for ( int index = 0 ; index < p ; index++ ) {
                coeff *= -1;
                termList.add(new Term(coeff, index * twoExp * (int) Math.pow(p, k-1)));
            }

            Polynomial cyclo = new Polynomial(termList);
            COMPUTED.put(n, cyclo);
            return cyclo;
        }
        else if ( factors.containsKey(2) && ((n/2) % 2 == 1) && (n/2) > 1 ) {
            //  CP(2m)[x] = CP(-m)[x], n odd integer > 1
            Polynomial cycloDiv2 = cyclotomicPolynomial(n/2);
            List<Term> termList = new ArrayList<>();
            for ( Term term : cycloDiv2.polynomialTerms ) {
                termList.add(term.exponent % 2 == 0 ? term : term.negate());
            }
            Polynomial cyclo = new Polynomial(termList);
            COMPUTED.put(n, cyclo);
            return cyclo;
        }

        //  General Case

        if ( algorithm == 0 ) {
            //  Slow - uses basic definition.
            List<Integer> divisors = getDivisors(n);
            //  Polynomial:  ( x^n - 1 )
            Polynomial cyclo = new Polynomial(1, n, -1, 0);
            for ( int i : divisors ) {
                Polynomial p = cyclotomicPolynomial(i);
                cyclo = cyclo.divide(p);
            }

            COMPUTED.put(n, cyclo);
            return cyclo;
        }
        else if ( algorithm == 1 ) {
            //  Faster.  Remove Max divisor (and all divisors of max divisor) - only one divide for all divisors of Max Divisor
            List<Integer> divisors = getDivisors(n);
            int maxDivisor = Integer.MIN_VALUE;
            for ( int div : divisors ) {
                maxDivisor = Math.max(maxDivisor, div);
            }
            List<Integer> divisorsExceptMax = new ArrayList<Integer>();
            for ( int div : divisors ) {
                if ( maxDivisor % div != 0 ) {
                    divisorsExceptMax.add(div);
                }
            }

            //  Polynomial:  ( x^n - 1 ) / ( x^m - 1 ), where m is the max divisor
            Polynomial cyclo = new Polynomial(1, n, -1, 0).divide(new Polynomial(1, maxDivisor, -1, 0));
            for ( int i : divisorsExceptMax ) {
                Polynomial p = cyclotomicPolynomial(i);
                cyclo = cyclo.divide(p);
            }

            COMPUTED.put(n, cyclo);

            return cyclo;
        }
        else if ( algorithm == 2 ) {
            //  Fastest
            //  Let p ; q be primes such that p does not divide n, and q q divides n.
            //  Then CP(np)[x] = CP(n)[x^p] / CP(n)[x]
            int m = 1;
            Polynomial cyclo = cyclotomicPolynomial(m);
            List<Integer> primes = new ArrayList<>(factors.keySet());
            Collections.sort(primes);
            for ( int prime : primes ) {
                //  CP(m)[x]
                Polynomial cycloM = cyclo;
                //  Compute CP(m)[x^p].
                List<Term> termList = new ArrayList<>();
                for ( Term t : cycloM.polynomialTerms ) {
                    termList.add(new Term(t.coefficient, t.exponent * prime));
                }
                cyclo = new Polynomial(termList).divide(cycloM);
                m = m * prime;
            }
            //  Now, m is the largest square free divisor of n
            int s = n / m;
            //  Compute CP(n)[x] = CP(m)[x^s]
            List<Term> termList = new ArrayList<>();
            for ( Term t : cyclo.polynomialTerms ) {
                termList.add(new Term(t.coefficient, t.exponent * s));
            }
            cyclo = new Polynomial(termList);
            COMPUTED.put(n, cyclo);

            return cyclo;
        }
        else {
            throw new RuntimeException("ERROR 103:  Invalid algorithm.");
        }
    }

    private static final List<Integer> getDivisors(int number) {
        List<Integer> divisors = new ArrayList<Integer>();
        long sqrt = (long) Math.sqrt(number);
        for ( int i = 1 ; i <= sqrt ; i++ ) {
            if ( number % i == 0 ) {
                divisors.add(i);
                int div = number / i;
                if ( div != i && div != number ) {
                    divisors.add(div);
                }
            }
        }
        return divisors;
    }

    private static final Map<Integer,Map<Integer,Integer>> allFactors = new TreeMap<Integer,Map<Integer,Integer>>();
    static {
        Map<Integer,Integer> factors = new TreeMap<Integer,Integer>();
        factors.put(2, 1);
        allFactors.put(2, factors);
    }

    public static Integer MAX_ALL_FACTORS = 100000;

    public static final Map<Integer,Integer> getFactors(Integer number) {
        if ( allFactors.containsKey(number) ) {
            return allFactors.get(number);
        }
        Map<Integer,Integer> factors = new TreeMap<Integer,Integer>();
        if ( number % 2 == 0 ) {
            Map<Integer,Integer> factorsdDivTwo = getFactors(number/2);
            factors.putAll(factorsdDivTwo);
            factors.merge(2, 1, (v1, v2) -> v1 + v2);
            if ( number < MAX_ALL_FACTORS )
                allFactors.put(number, factors);
            return factors;
        }
        boolean prime = true;
        long sqrt = (long) Math.sqrt(number);
        for ( int i = 3 ; i <= sqrt ; i += 2 ) {
            if ( number % i == 0 ) {
                prime = false;
                factors.putAll(getFactors(number/i));
                factors.merge(i, 1, (v1, v2) -> v1 + v2);
                if ( number < MAX_ALL_FACTORS )
                    allFactors.put(number, factors);
                return factors;
            }
        }
        if ( prime ) {
            factors.put(number, 1);
            if ( number < MAX_ALL_FACTORS )
                allFactors.put(number, factors);
        }
        return factors;
    }

    private static final class Polynomial {

        private List<Term> polynomialTerms;

        //  Format - coeff, exp, coeff, exp, (repeating in pairs) . . .
        public Polynomial(int ... values) {
            if ( values.length % 2 != 0 ) {
                throw new IllegalArgumentException("ERROR 102:  Polynomial constructor.  Length must be even.  Length = " + values.length);
            }
            polynomialTerms = new ArrayList<>();
            for ( int i = 0 ; i < values.length ; i += 2 ) {
                Term t = new Term(values[i], values[i+1]);
                polynomialTerms.add(t);
            }
            Collections.sort(polynomialTerms, new TermSorter());
        }

        public Polynomial() {
            //  zero
            polynomialTerms = new ArrayList<>();
            polynomialTerms.add(new Term(0,0));
        }

        private boolean hasCoefficientAbs(int coeff) {
            for ( Term term : polynomialTerms ) {
                if ( Math.abs(term.coefficient) == coeff ) {
                    return true;
                }
            }
            return false;
        }

        private Polynomial(List<Term> termList) {
            if ( termList.size() == 0 ) {
                //  zero
                termList.add(new Term(0,0));
            }
            else {
                //  Remove zero terms if needed
                for ( int i = 0 ; i < termList.size() ; i++ ) {
                    if ( termList.get(i).coefficient == 0 ) {
                        termList.remove(i);
                    }
                }
            }
            if ( termList.size() == 0 ) {
                //  zero
                termList.add(new Term(0,0));
            }
            polynomialTerms = termList;
            Collections.sort(polynomialTerms, new TermSorter());
        }

        public Polynomial divide(Polynomial v) {
            //long start = System.currentTimeMillis();
            divisions++;
            Polynomial q = new Polynomial();
            Polynomial r = this;
            long lcv = v.leadingCoefficient();
            long dv = v.degree();
            while ( r.degree() >= v.degree() ) {
                long lcr = r.leadingCoefficient();
                long s = lcr / lcv;  //  Integer division
                Term term = new Term(s, r.degree() - dv);
                q = q.add(term);
                r = r.add(v.multiply(term.negate()));
            }
            //long end = System.currentTimeMillis();
            //System.out.printf("Divide:  Elapsed = %d, Degree 1 = %d, Degree 2 = %d%n", (end-start), this.degree(), v.degree());
            return q;
        }

        public Polynomial add(Polynomial polynomial) {
            List<Term> termList = new ArrayList<>();
            int thisCount = polynomialTerms.size();
            int polyCount = polynomial.polynomialTerms.size();
            while ( thisCount > 0 || polyCount > 0 ) {
                Term thisTerm = thisCount == 0 ? null : polynomialTerms.get(thisCount-1);
                Term polyTerm = polyCount == 0 ? null : polynomial.polynomialTerms.get(polyCount-1);
                if ( thisTerm == null ) {
                    termList.add(polyTerm.clone());
                    polyCount--;
                }
                else if (polyTerm == null ) {
                    termList.add(thisTerm.clone());
                    thisCount--;
                }
                else if ( thisTerm.degree() == polyTerm.degree() ) {
                    Term t = thisTerm.add(polyTerm);
                    if ( t.coefficient != 0 ) {
                        termList.add(t);
                    }
                    thisCount--;
                    polyCount--;
                }
                else if ( thisTerm.degree() < polyTerm.degree() ) {
                    termList.add(thisTerm.clone());
                    thisCount--;
                }
                else {
                    termList.add(polyTerm.clone());
                    polyCount--;
                }
            }
            return new Polynomial(termList);
        }

        public Polynomial add(Term term) {
            List<Term> termList = new ArrayList<>();
            boolean added = false;
            for ( int index = 0 ; index < polynomialTerms.size() ; index++ ) {
                Term currentTerm = polynomialTerms.get(index);
                if ( currentTerm.exponent == term.exponent ) {
                    added = true;
                    if ( currentTerm.coefficient + term.coefficient != 0 ) {
                        termList.add(currentTerm.add(term));
                    }
                }
                else {
                    termList.add(currentTerm.clone());
                }
            }
            if ( ! added ) {
                termList.add(term.clone());
            }
            return new Polynomial(termList);
        }

        public Polynomial multiply(Term term) {
            List<Term> termList = new ArrayList<>();
            for ( int index = 0 ; index < polynomialTerms.size() ; index++ ) {
                Term currentTerm = polynomialTerms.get(index);
                termList.add(currentTerm.clone().multiply(term));
            }
            return new Polynomial(termList);
        }

        public Polynomial clone() {
            List<Term> clone = new ArrayList<>();
            for ( Term t : polynomialTerms ) {
                clone.add(new Term(t.coefficient, t.exponent));
            }
            return new Polynomial(clone);
        }

        public long leadingCoefficient() {
//            long coefficient = 0;
//            long degree = Integer.MIN_VALUE;
//            for ( Term t : polynomialTerms ) {
//                if ( t.degree() > degree ) {
//                    coefficient = t.coefficient;
//                    degree = t.degree();
//                }
//            }
            return polynomialTerms.get(0).coefficient;
        }

        public long degree() {
//            long degree = Integer.MIN_VALUE;
//            for ( Term t : polynomialTerms ) {
//                if ( t.degree() > degree ) {
//                    degree = t.degree();
//                }
//            }
            return polynomialTerms.get(0).exponent;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            boolean first = true;
            for ( Term term : polynomialTerms ) {
                if ( first ) {
                    sb.append(term);
                    first = false;
                }
                else {
                    sb.append(" ");
                    if ( term.coefficient > 0 ) {
                        sb.append("+ ");
                        sb.append(term);
                    }
                    else {
                        sb.append("- ");
                        sb.append(term.negate());
                    }
                }
            }
            return sb.toString();
        }
    }

    private static final class TermSorter implements Comparator<Term> {
        @Override
        public int compare(Term o1, Term o2) {
            return (int) (o2.exponent - o1.exponent);
        }
    }

    //  Note:  Cyclotomic Polynomials have small coefficients.  Not appropriate for general polynomial usage.
    private static final class Term {
        long coefficient;
        long exponent;

        public Term(long c, long e) {
            coefficient = c;
            exponent = e;
        }

        public Term clone() {
            return new Term(coefficient, exponent);
        }

        public Term multiply(Term term) {
            return new Term(coefficient * term.coefficient, exponent + term.exponent);
        }

        public Term add(Term term) {
            if ( exponent != term.exponent ) {
                throw new RuntimeException("ERROR 102:  Exponents not equal.");
            }
            return new Term(coefficient + term.coefficient, exponent);
        }

        public Term negate() {
            return new Term(-coefficient, exponent);
        }

        public long degree() {
            return exponent;
        }

        @Override
        public String toString() {
            if ( coefficient == 0 ) {
                return "0";
            }
            if ( exponent == 0 ) {
                return "" + coefficient;
            }
            if ( coefficient == 1 ) {
                if ( exponent == 1 ) {
                    return "x";
                }
                else {
                    return "x^" + exponent;
                }
            }
            if ( exponent == 1 ) {
                return coefficient + "x";
            }
            return coefficient + "x^" + exponent;
        }
    }

}


Damm algorithm

The '''Damm''' algorithm is a checksum algorithm which detects all single digit errors and adjacent transposition errors.

The algorithm is named after H. Michael Damm.

;Task:
Verify the checksum, stored as last digit of an input.

Solution:
public class DammAlgorithm {
    private static final int[][] table = {
        {0, 3, 1, 7, 5, 9, 8, 6, 4, 2},
        {7, 0, 9, 2, 1, 5, 4, 8, 6, 3},
        {4, 2, 0, 6, 8, 7, 1, 3, 5, 9},
        {1, 7, 5, 0, 9, 8, 3, 4, 2, 6},
        {6, 1, 2, 3, 0, 4, 5, 9, 7, 8},
        {3, 6, 7, 4, 2, 0, 9, 5, 8, 1},
        {5, 8, 6, 9, 7, 2, 0, 1, 3, 4},
        {8, 9, 4, 5, 3, 6, 2, 0, 1, 7},
        {9, 4, 3, 8, 6, 1, 7, 2, 0, 5},
        {2, 5, 8, 1, 4, 3, 6, 7, 9, 0},
    };

    private static boolean damm(String s) {
        int interim = 0;
        for (char c : s.toCharArray()) interim = table[interim][c - '0'];
        return interim == 0;
    }

    public static void main(String[] args) {
        int[] numbers = {5724, 5727, 112946, 112949};
        for (Integer number : numbers) {
            boolean isValid = damm(number.toString());
            if (isValid) {
                System.out.printf("%6d is valid\n", number);
            } else {
                System.out.printf("%6d is invalid\n", number);
            }
        }
    }
}


De Bruijn sequences

{{DISPLAYTITLE:de Bruijn sequences}}
The sequences are named after the Dutch mathematician   Nicolaas Govert de Bruijn.

A note on Dutch capitalization:   Nicolaas' last name is   '''de Bruijn''',   the   '''de'''   isn't normally capitalized
unless it's the first word in a sentence.   Rosetta Code (more or less by default or by fiat) requires the first word in the task name to be
capitalized.

In combinatorial mathematics,   a   '''de Bruijn sequence'''   of order    ''n''    on
a    size-''k''    alphabet (computer science)    ''A''    is a cyclic sequence in which every
possible    length-''n''    string (computer science, formal theory)   on    ''A''    occurs
exactly once as a contiguous substring.

Such a sequence is denoted by    ''B''(''k'', ''n'')    and has
length   ''k''''n'',   which is also the number of distinct substrings of
length   ''n''   on   ''A'';
de Bruijn sequences are therefore optimally short.

There are:
                          (k!)k(n-1)   /   kn
distinct de Bruijn sequences    ''B''(''k'', ''n'').

;Task:
For this Rosetta Code task,   a   '''de Bruijn'''   sequence is to be generated that can be used to shorten a brute-force attack on
a   PIN-like   code lock that does not have an "enter"
key and accepts the last    ''n''    digits entered.

Note:   automated teller machines (ATMs)   used to work like
this,   but their software has been updated to not allow a brute-force attack.

;Example:
A   digital door lock   with a 4-digit code would
have ''B'' (10, 4) solutions,   with a length of   '''10,000'''   (digits).

Therefore, only at most     '''10,000 + 3'''     (as the solutions are cyclic or ''wrap-around'')   presses are needed to
open the lock.

Trying all 4-digit codes separately would require   '''4 x 10,000'''   or   '''40,000'''   presses.

;Task requirements:
:*   Generate a de Bruijn sequence for a 4-digit (decimal) PIN code.
:::*   Show the length of the generated de Bruijn sequence.
:::*   (There are many possible de Bruijn sequences that solve this task,   one solution is shown on the ''discussion'' page).
:::*   Show the first and last   '''130'''   digits of the de Bruijn sequence.
:*   Verify that all four-digit (decimal)   '''1,000'''   PIN codes are contained within the de Bruijn sequence.
:::*   0000, 0001, 0002, 0003,   ...   9996, 9997, 9998, 9999   (note the leading zeros).
:*   Reverse the de Bruijn sequence.
:*   Again, perform the (above) verification test.
:*   Replace the 4,444th digit with a period (.) in the original de Bruijn sequence.
:::*   Perform the verification test (again).   There should be four PIN codes missing.

(The last requirement is to ensure that the verification tests performs correctly.   The verification processes should list
any and all missing PIN codes.)

Show all output here, on this page.

;References:
:*   Wikipedia           entry:   de Bruijn sequence.
:*   MathWorld           entry:   de Bruijn sequence.
:*   An  OEIS  entry:   A166315 lexicographically earliest binary de Bruijn sequences, B(2,n)     --- Not B(10,4),   but possibly relevant.

Solution:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiConsumer;

public class DeBruijn {
    public interface Recursable<T, U> {
        void apply(T t, U u, Recursable<T, U> r);
    }

    public static <T, U> BiConsumer<T, U> recurse(Recursable<T, U> f) {
        return (t, u) -> f.apply(t, u, f);
    }

    private static String deBruijn(int k, int n) {
        byte[] a = new byte[k * n];
        Arrays.fill(a, (byte) 0);

        List<Byte> seq = new ArrayList<>();

        BiConsumer<Integer, Integer> db = recurse((t, p, f) -> {
            if (t > n) {
                if (n % p == 0) {
                    for (int i = 1; i < p + 1; ++i) {
                        seq.add(a[i]);
                    }
                }
            } else {
                a[t] = a[t - p];
                f.apply(t + 1, p, f);
                int j = a[t - p] + 1;
                while (j < k) {
                    a[t] = (byte) (j & 0xFF);
                    f.apply(t + 1, t, f);
                    j++;
                }
            }
        });
        db.accept(1, 1);

        StringBuilder sb = new StringBuilder();
        for (Byte i : seq) {
            sb.append("0123456789".charAt(i));
        }

        sb.append(sb.subSequence(0, n - 1));
        return sb.toString();
    }

    private static boolean allDigits(String s) {
        for (int i = 0; i < s.length(); ++i) {
            char c = s.charAt(i);
            if (!Character.isDigit(c)) {
                return false;
            }
        }
        return true;
    }

    private static void validate(String db) {
        int le = db.length();
        int[] found = new int[10_000];
        Arrays.fill(found, 0);
        List<String> errs = new ArrayList<>();

        // Check all strings of 4 consecutive digits within 'db'
        // to see if all 10,000 combinations occur without duplication.
        for (int i = 0; i < le - 3; ++i) {
            String s = db.substring(i, i + 4);
            if (allDigits(s)) {
                int n = Integer.parseInt(s);
                found[n]++;
            }
        }

        for (int i = 0; i < 10_000; ++i) {
            if (found[i] == 0) {
                errs.add(String.format("    PIN number %d is missing", i));
            } else if (found[i] > 1) {
                errs.add(String.format("    PIN number %d occurs %d times", i, found[i]));
            }
        }

        if (errs.isEmpty()) {
            System.out.println("    No errors found");
        } else {
            String pl = (errs.size() == 1) ? "" : "s";
            System.out.printf("  %d error%s found:\n", errs.size(), pl);
            errs.forEach(System.out::println);
        }
    }

    public static void main(String[] args) {
        String db = deBruijn(10, 4);

        System.out.printf("The length of the de Bruijn sequence is %d\n\n", db.length());
        System.out.printf("The first 130 digits of the de Bruijn sequence are: %s\n\n", db.substring(0, 130));
        System.out.printf("The last 130 digits of the de Bruijn sequence are: %s\n\n", db.substring(db.length() - 130));

        System.out.println("Validating the de Bruijn sequence:");
        validate(db);

        StringBuilder sb = new StringBuilder(db);
        String rdb = sb.reverse().toString();
        System.out.println();
        System.out.println("Validating the de Bruijn sequence:");
        validate(rdb);

        sb = new StringBuilder(db);
        sb.setCharAt(4443, '.');
        System.out.println();
        System.out.println("Validating the overlaid de Bruijn sequence:");
        validate(sb.toString());
    }
}


Deepcopy

Demonstrate how to copy data structures containing complex heterogeneous and cyclic semantics.

This is often referred to as deep copying, and is normally required where structures are mutable and to ensure that independent copies can be manipulated without side-effects.

If this facility is not built into the language, it is permissible to use functions from a common library, or a coded procedure.

The task should show:

* Relevant semantics of structures, such as their homogeneous or heterogeneous properties, or containment of (self- or mutual-reference) cycles.

* Any limitations of the method.

* That the structure and its copy are different.

* Suitable links to external documentation for common libraries.

Solution:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DeepCopy {

    public static void main(String[] args) {
        Person p1 = new Person("Clark", "Kent", new Address("1 World Center", "Metropolis", "NY", "010101"));
        Person p2 = p1;

        System.out.printf("Demonstrate shallow copy.  Both are the same object.%n");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);
        System.out.printf("Set city on person 2.  City on both objects is changed.%n");
        p2.getAddress().setCity("New York");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);

        p1 = new Person("Clark", "Kent", new Address("1 World Center", "Metropolis", "NY", "010101"));
        p2 = new Person(p1);
        System.out.printf("%nDemonstrate copy constructor.  Object p2 is a deep copy of p1.%n");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);
        System.out.printf("Set city on person 2.  City on objects is different.%n");
        p2.getAddress().setCity("New York");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);

        p2 = (Person) deepCopy(p1);
        System.out.printf("%nDemonstrate serialization.  Object p2 is a deep copy of p1.%n");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);
        System.out.printf("Set city on person 2.  City on objects is different.%n");
        p2.getAddress().setCity("New York");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);

        p2 = (Person) p1.clone();
        System.out.printf("%nDemonstrate cloning.  Object p2 is a deep copy of p1.%n");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);
        System.out.printf("Set city on person 2.  City on objects is different.%n");
        p2.getAddress().setCity("New York");
        System.out.printf("Person p1 = %s%n", p1);
        System.out.printf("Person p2 = %s%n", p2);
    }

    /**
     * Makes a deep copy of any Java object that is passed.
     */
    private static Object deepCopy(Object object) {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ObjectOutputStream outputStrm = new ObjectOutputStream(outputStream);
            outputStrm.writeObject(object);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            ObjectInputStream objInputStream = new ObjectInputStream(inputStream);
            return objInputStream.readObject();
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static class Address implements Serializable, Cloneable {

        private static final long serialVersionUID = -7073778041809445593L;

        private String street;
        private String city;
        private String state;
        private String postalCode;
        public String getStreet() {
            return street;
        }
        public String getCity() {
            return city;
        }
        public void setCity(String city) {
            this.city = city;
        }
        public String getState() {
            return state;
        }
        public String getPostalCode() {
            return postalCode;
        }

        @Override
        public String toString() {
            return "[street=" + street + ", city=" + city + ", state=" + state + ", code=" + postalCode + "]";
        }

        public Address(String s, String c, String st, String p) {
            street = s;
            city = c;
            state = st;
            postalCode = p;
        }

        //  Copy constructor
        public Address(Address add) {
            street    = add.street;
            city       = add.city;
            state      = add.state;
            postalCode = add.postalCode;
        }

        //  Support Cloneable
        @Override
        public Object clone() {
            return new Address(this);
        }

    }

    public static class Person implements Serializable, Cloneable {
        private static final long serialVersionUID = -521810583786595050L;
        private String firstName;
        private String lastName;
        private Address address;
        public String getFirstName() {
            return firstName;
        }
        public String getLastName() {
            return lastName;
        }
        public Address getAddress() {
            return address;
        }

        @Override
        public String toString() {
            return "[first name=" + firstName + ", last name=" + lastName + ", address=" + address + "]";
        }

        public Person(String fn, String ln, Address add) {
            firstName = fn;
            lastName = ln;
            address = add;
        }

        //  Copy Constructor
        public Person(Person person) {
            firstName = person.firstName;
            lastName = person.lastName;
            address = new Address(person.address);  //  Invoke copy constructor of mutable sub-objects.
        }

        //  Support Cloneable
        @Override
        public Object clone() {
            return new Person(this);
        }
    }
}


Deming's funnel

W Edwards Deming was an American statistician and management guru who used physical demonstrations to illuminate his teachings.  In one demonstration Deming repeatedly dropped marbles through a funnel at a target, marking where they landed, and observing the resulting pattern.  He applied a sequence of "rules" to try to improve performance.  In each case the experiment begins with the funnel positioned directly over the target.

* '''Rule 1''': The funnel remains directly above the target.
* '''Rule 2''': Adjust the funnel position by shifting the target to compensate after each drop.  E.g. If the last drop missed 1 cm east, move the funnel 1 cm to the west of its current position.
* '''Rule 3''': As rule 2, but first move the funnel back over the target, before making the adjustment.  E.g. If the funnel is 2 cm north, and the marble lands 3 cm north, move the funnel 3 cm south of the target.
* '''Rule 4''': The funnel is moved directly over the last place a marble landed.

Apply the four rules to the set of 50 pseudorandom displacements provided (e.g in the Racket solution) for the dxs and dys.  '''Output''': calculate the mean and standard-deviations of the resulting x and y values for each rule.

Note that rules 2, 3, and 4 give successively worse results.  Trying to deterministically compensate for a random process is counter-productive, but -- according to Deming -- quite a popular pastime: see the Further Information, below for examples.

'''Stretch goal 1''': Generate fresh pseudorandom data.  The radial displacement of the drop from the funnel position is given by a Gaussian distribution (standard deviation is 1.0) and the angle of displacement is uniformly distributed.

'''Stretch goal 2''': Show scatter plots of all four results.

;Further information:
* Further explanation and interpretation
* Video demonstration of the funnel experiment at the Mayo Clinic.

Solution: Translation of [[Deming's_Funnel#Python|Python]] via [[Deming's_Funnel#D|D]]


Deming's funnel

Solution:
import static java.lang.Math.*;
import java.util.Arrays;
import java.util.function.BiFunction;

public class DemingsFunnel {

    public static void main(String[] args) {
        double[] dxs = {
            -0.533, 0.270, 0.859, -0.043, -0.205, -0.127, -0.071, 0.275,
            1.251, -0.231, -0.401, 0.269, 0.491, 0.951, 1.150, 0.001,
            -0.382, 0.161, 0.915, 2.080, -2.337, 0.034, -0.126, 0.014,
            0.709, 0.129, -1.093, -0.483, -1.193, 0.020, -0.051, 0.047,
            -0.095, 0.695, 0.340, -0.182, 0.287, 0.213, -0.423, -0.021,
            -0.134, 1.798, 0.021, -1.099, -0.361, 1.636, -1.134, 1.315,
            0.201, 0.034, 0.097, -0.170, 0.054, -0.553, -0.024, -0.181,
            -0.700, -0.361, -0.789, 0.279, -0.174, -0.009, -0.323, -0.658,
            0.348, -0.528, 0.881, 0.021, -0.853, 0.157, 0.648, 1.774,
            -1.043, 0.051, 0.021, 0.247, -0.310, 0.171, 0.000, 0.106,
            0.024, -0.386, 0.962, 0.765, -0.125, -0.289, 0.521, 0.017,
            0.281, -0.749, -0.149, -2.436, -0.909, 0.394, -0.113, -0.598,
            0.443, -0.521, -0.799, 0.087};

        double[] dys = {
            0.136, 0.717, 0.459, -0.225, 1.392, 0.385, 0.121, -0.395,
            0.490, -0.682, -0.065, 0.242, -0.288, 0.658, 0.459, 0.000,
            0.426, 0.205, -0.765, -2.188, -0.742, -0.010, 0.089, 0.208,
            0.585, 0.633, -0.444, -0.351, -1.087, 0.199, 0.701, 0.096,
            -0.025, -0.868, 1.051, 0.157, 0.216, 0.162, 0.249, -0.007,
            0.009, 0.508, -0.790, 0.723, 0.881, -0.508, 0.393, -0.226,
            0.710, 0.038, -0.217, 0.831, 0.480, 0.407, 0.447, -0.295,
            1.126, 0.380, 0.549, -0.445, -0.046, 0.428, -0.074, 0.217,
            -0.822, 0.491, 1.347, -0.141, 1.230, -0.044, 0.079, 0.219,
            0.698, 0.275, 0.056, 0.031, 0.421, 0.064, 0.721, 0.104,
            -0.729, 0.650, -1.103, 0.154, -1.720, 0.051, -0.385, 0.477,
            1.537, -0.901, 0.939, -0.411, 0.341, -0.411, 0.106, 0.224,
            -0.947, -1.424, -0.542, -1.032};

        experiment("Rule 1:", dxs, dys, (z, dz) -> 0.0);
        experiment("Rule 2:", dxs, dys, (z, dz) -> -dz);
        experiment("Rule 3:", dxs, dys, (z, dz) -> -(z + dz));
        experiment("Rule 4:", dxs, dys, (z, dz) -> z + dz);
    }

    static void experiment(String label, double[] dxs, double[] dys,
            BiFunction<Double, Double, Double> rule) {

        double[] resx = funnel(dxs, rule);
        double[] resy = funnel(dys, rule);
        System.out.println(label);
        System.out.printf("Mean x, y:    %.4f, %.4f%n", mean(resx), mean(resy));
        System.out.printf("Std dev x, y: %.4f, %.4f%n", stdDev(resx), stdDev(resy));
        System.out.println();
    }

    static double[] funnel(double[] input, BiFunction<Double, Double, Double> rule) {
        double x = 0;
        double[] result = new double[input.length];

        for (int i = 0; i < input.length; i++) {
            double rx = x + input[i];
            x = rule.apply(x, input[i]);
            result[i] = rx;
        }
        return result;
    }

    static double mean(double[] xs) {
        return Arrays.stream(xs).sum() / xs.length;
    }

    static double stdDev(double[] xs) {
        double m = mean(xs);
        return sqrt(Arrays.stream(xs).map(x -> pow((x - m), 2)).sum() / xs.length);
    }
}


Department numbers

There is a highly organized city that has decided to assign a number to each of their departments:
::*   police department
::*   sanitation department
::*   fire department

Each department can have a number between   '''1'''   and   '''7'''   (inclusive).

The three department numbers are to be unique (different from each other) and must add up to   '''12'''.

The Chief of the Police doesn't like odd numbers and wants to have an even number for his department.

;Task:
Write a computer program which outputs all valid combinations.

Possible output   (for the 1st and 14th solutions):

  --police--  --sanitation--  --fire--
      2             3            7
      6             5            1

Solution:
public class DepartmentNumbers {
    public static void main(String[] args) {
        System.out.println("Police  Sanitation  Fire");
        System.out.println("------  ----------  ----");
        int count = 0;
        for (int i = 2; i <= 6; i += 2) {
            for (int j = 1; j <= 7; ++j) {
                if (j == i) continue;
                for (int k = 1; k <= 7; ++k) {
                    if (k == i || k == j) continue;
                    if (i + j + k != 12) continue;
                    System.out.printf("  %d         %d         %d\n", i, j, k);
                    count++;
                }
            }
        }
        System.out.printf("\n%d valid combinations", count);
    }
}


Detect division by zero

Write a function to detect a   ''divide by zero error''   without checking if the denominator is zero.

Solution:
public static boolean except(double numer, double denom){
	try{
		int dummy = (int)numer / (int)denom;//ArithmeticException is only thrown from integer math
		return false;
	}catch(ArithmeticException e){return true;}
}


Determinant and permanent

permanent of the matrix.

The determinant is given by
:: \det(A) = \sum_\sigma\sgn(\sigma)\prod_{i=1}^n M_{i,\sigma_i}
while the permanent is given by
::  \operatorname{perm}(A)=\sum_\sigma\prod_{i=1}^n M_{i,\sigma_i}
In both cases the sum is over the permutations \sigma of the permutations of 1, 2, ..., ''n''. (A permutation's sign is 1 if there are an even number of inversions and -1 otherwise; see parity of a permutation.)

More efficient algorithms for the determinant are known: [[LU decomposition]], see for example [[wp:LU decomposition#Computing the determinant]]. Efficient methods for calculating the permanent are not known.

;Related task:
* [[Permutations by swapping]]

Solution:
import java.util.Scanner;

public class MatrixArithmetic {
	public static double[][] minor(double[][] a, int x, int y){
		int length = a.length-1;
		double[][] result = new double[length][length];
		for(int i=0;i<length;i++) for(int j=0;j<length;j++){
			if(i<x && j<y){
				result[i][j] = a[i][j];
			}else if(i>=x && j<y){
				result[i][j] = a[i+1][j];
			}else if(i<x && j>=y){
				result[i][j] = a[i][j+1];
			}else{ //i>x && j>y
				result[i][j] = a[i+1][j+1];
			}
		}
		return result;
	}
	public static double det(double[][] a){
		if(a.length == 1){
			return a[0][0];
		}else{
			int sign = 1;
			double sum = 0;
			for(int i=0;i<a.length;i++){
				sum += sign * a[0][i] * det(minor(a,0,i));
				sign *= -1;
			}
			return sum;
		}
	}
	public static double perm(double[][] a){
		if(a.length == 1){
			return a[0][0];
		}else{
			double sum = 0;
			for(int i=0;i<a.length;i++){
				sum += a[0][i] * perm(minor(a,0,i));
			}
			return sum;
		}
	}
	public static void main(String args[]){
		Scanner sc = new Scanner(System.in);
		int size = sc.nextInt();
		double[][] a = new double[size][size];
		for(int i=0;i<size;i++) for(int j=0;j<size;j++){
			a[i][j] = sc.nextDouble();
		}
		sc.close();
		System.out.println("Determinant: "+det(a));
		System.out.println("Permanent: "+perm(a));
	}
}


Determine if a string has all the same characters

Given a character string   (which may be empty, or have a length of zero characters):
::*   create a function/procedure/routine to:
::::*    determine if all the characters in the string are the same
::::*    indicate if or which character is different from the previous character
::*   display each string and its length   (as the strings are being examined)
::*   a zero-length (empty) string shall be considered as all the same character(s)
::*   process the strings from left-to-right
::*   if       all the same character,   display a message saying such
::*   if                  not all the same character,   then:
::::*    display a message saying such
::::*    display what character is different
::::*    only the 1st different character need be displayed
::::*    display where the different character is in the string
::::*    the above messages can be part of a single message
::::*    display the hexadecimal value of the different character

Use (at least) these seven test values   (strings):
:::*   a string of length   0   (an empty string)
:::*   a string of length   3   which contains three blanks
:::*   a string of length   1   which contains:   '''2'''
:::*   a string of length   3   which contains:   '''333'''
:::*   a string of length   3   which contains:   '''.55'''
:::*   a string of length   6   which contains:   '''tttTTT'''
:::*   a string of length   9   with a blank in the middle:   '''4444   444k'''

Show all output here on this page.

Solution:
public static void main(String[] args) {
    String[] strings = {
        "", "   ", "2", "333", ".55", "tttTTT", "5", "4444 444k"
    };
    for (String string : strings)
        System.out.println(printCompare(string));
}

static String printCompare(String string) {
    String stringA = "'%s' %d".formatted(string, string.length());
    Pattern pattern = Pattern.compile("(.)\\1*");
    Matcher matcher = pattern.matcher(string);
    StringBuilder stringB = new StringBuilder();
    /* 'Matcher' works dynamically, so we'll have to denote a change */
    boolean difference = false;
    char character;
    String newline = System.lineSeparator();
    while (matcher.find()) {
        if (matcher.start() != 0) {
            character = matcher.group(1).charAt(0);
            stringB.append(newline);
            stringB.append("  Char '%s' (0x%x)".formatted(character, (int) character));
            stringB.append(" @ index %d".formatted(matcher.start()));
            difference = true;
        }
    }
    if (!difference)
        stringB.append(newline).append("  All characters are the same");
    return stringA + stringB;
}


Given a character string   (which may be empty, or have a length of zero characters):
::*   create a function/procedure/routine to:
::::*    determine if all the characters in the string are unique
::::*    indicate if or which character is duplicated and where
::*   display each string and its length   (as the strings are being examined)
::*   a zero-length (empty) string shall be considered as unique
::*   process the strings from left-to-right
::*   if       unique,   display a message saying such
::*   if                  not unique,   then:
::::*    display a message saying such
::::*    display what character is duplicated
::::*    only the 1st non-unique character need be displayed
::::*    display where "both" duplicated characters are in the string
::::*    the above messages can be part of a single message
::::*    display the hexadecimal value of the duplicated character

Use (at least) these five test values   (strings):
:::*   a string of length     0   (an empty string)
:::*   a string of length     1   which is a single period   ('''.''')
:::*   a string of length     6   which contains:   '''abcABC'''
:::*   a string of length     7   which contains a blank in the middle:   '''XYZ  ZYX'''
:::*   a string of length         36   which   ''doesn't''   contain the letter "oh":
::::::::  '''1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'''

Show all output here on this page.

Solution:
import java.util.HashMap;
import java.util.Map;

//  Title:  Determine if a string has all unique characters

public class StringUniqueCharacters {

    public static void main(String[] args) {
        System.out.printf("%-40s  %2s  %10s  %8s  %s  %s%n", "String", "Length", "All Unique", "1st Diff", "Hex", "Positions");
        System.out.printf("%-40s  %2s  %10s  %8s  %s  %s%n", "------------------------", "------", "----------", "--------", "---", "---------");
        for ( String s : new String[] {"", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"} ) {
            processString(s);
        }
    }

    private static void processString(String input) {
        Map<Character,Integer> charMap = new HashMap<>();
        char dup = 0;
        int index = 0;
        int pos1 = -1;
        int pos2 = -1;
        for ( char key : input.toCharArray() ) {
            index++;
            if ( charMap.containsKey(key) ) {
                dup = key;
                pos1 = charMap.get(key);
                pos2 = index;
                break;
            }
            charMap.put(key, index);
        }
        String unique = dup == 0 ? "yes" : "no";
        String diff = dup == 0 ? "" : "'" + dup + "'";
        String hex = dup == 0 ? "" : Integer.toHexString(dup).toUpperCase();
        String position = dup == 0 ? "" : pos1 + " " + pos2;
        System.out.printf("%-40s  %-6d  %-10s  %-8s  %-3s  %-5s%n", input, input.length(), unique, diff, hex, position);
    }

}


Determine if a string is collapsible

Determine if a character string is   ''collapsible''.

And if so,   collapse the string   (by removing   ''immediately repeated''   characters).

If a character string has   ''immediately repeated''   character(s),   the repeated characters are to be
deleted (removed),   but not the primary (1st) character(s).

An   ''immediately repeated''   character is any character that is   immediately   followed by an
identical character (or characters).   Another word choice could've been   ''duplicated character'',   but that
might have ruled out   (to some readers)   triplicated characters   ***   or more.

{This Rosetta Code task was inspired by a newly introduced   (as of around November 2019)   '''PL/I'''   BIF:   '''collapse'''.}

;Examples:
In the following character string:

  The better the 4-wheel drive, the further you'll be from help when ya get stuck!

Only the 2nd   '''t''',   '''e''', and   '''l'''   are repeated characters,   indicated
by underscores (above),   even though they (those characters) appear elsewhere in the character string.

So, after ''collapsing'' the string, the result would be:

  The beter the 4-whel drive, the further you'l be from help when ya get stuck!

Another example:
In the following character string:

  headmistressship

The "collapsed" string would be:

  headmistreship

;Task:
Write a subroutine/function/procedure/routine***   to
locate   ''repeated''   characters and   ''collapse''   (delete)   them from the character
string.   The character string can be processed from either direction.

Show all output here, on this page:
:*   the   original string and its length
:*   the       resultant string and its length
:*   the above strings should be "bracketed" with   '''<<<'''   and   '''>>>'''   (to delineate blanks)
;*   <<<<<<Guillemets may be used instead for "bracketing" for the more artistic programmers,   shown used here>>>>>>

Use (at least) the following five strings,   all strings are length seventy-two (characters, including blanks),   except
the 1st string:

  string
  number
         ++
    1    |+-----------------------------------------------------------------------+   <######  a null string  (length zero)
    2    |"If I were two-faced, would I be wearing this one?" --- Abraham Lincoln |
    3    |..1111111111111111111111111111111111111111111111111111111111111117777888|
    4    |I never give 'em hell, I just tell the truth, and they think it's hell. |
    5    |                                                    --- Harry S Truman  |   <######  has many repeated blanks
         +------------------------------------------------------------------------+

Solution:
//  Title:  Determine if a string is collapsible

public class StringCollapsible {

    public static void main(String[] args) {
        for ( String s : new String[] {
              "",
              "\"If I were two-faced, would I be wearing this one?\" --- Abraham Lincoln ",
              "..1111111111111111111111111111111111111111111111111111111111111117777888",
              "I never give 'em hell, I just tell the truth, and they think it's hell. ",
              "                                                    --- Harry S Truman  ",
              "122333444455555666666777777788888888999999999",
              "The better the 4-wheel drive, the further you'll be from help when ya get stuck!",
              "headmistressship"}) {
            String result = collapse(s);
            System.out.printf("old:  %2d <<<%s>>>%nnew:  %2d <<<%s>>>%n%n", s.length(), s, result.length(), result);
        }
    }

    private static String collapse(String in) {
        StringBuilder sb = new StringBuilder();
        for ( int i = 0 ; i < in.length() ; i++ ) {
            if ( i == 0 || in.charAt(i-1) != in.charAt(i) ) {
                sb.append(in.charAt(i));
            }
        }
        return sb.toString();
    }

}