Calkin-Wilf sequence

The '''Calkin-Wilf sequence''' contains every nonnegative rational number exactly once.

It can be calculated recursively as follows:

        {{math|a1}}   =  {{math|1}}
 {{math|an+1}}  =  {{math|1/(2an+1-an)}} for n > 1

;Task part 1:
* Show on this page terms 1 through 20 of the Calkin-Wilf sequence.

To avoid floating point error, you may want to use a rational number data type.

It is also possible, given a non-negative rational number, to determine where it appears in the sequence without calculating the sequence. The procedure is to get the continued fraction representation of the rational and use it as the run-length encoding of the binary representation of the term number, beginning from the end of the continued fraction.
It only works if the number of terms in the continued fraction is odd- use either of the two equivalent representations to achieve this:

        {{math|[a0; a1, a2, ..., an]}}  =  {{math|[a0; a1, a2 ,..., an-1, 1]}}

;Example:
The fraction   '''9/4'''   has odd continued fraction representation      {{math|2; 3, 1}},     giving a binary representation of   '''100011''',
which means   '''9/4'''   appears as the   '''35th'''   term of the sequence.

;Task part 2:
* Find the position of the number   '''83116''''''/''''''51639'''   in the Calkin-Wilf sequence.

;See also:
* Wikipedia entry:  Calkin-Wilf tree
* [[Continued fraction]]
* [[Continued fraction/Arithmetic/Construct from rational number]]

Solution:
import java.util.ArrayDeque;
import java.util.Deque;

public final class CalkinWilfSequence {

	public static void main(String[] aArgs) {
		Rational term = Rational.ONE;
	    System.out.println("First 20 terms of the Calkin-Wilf sequence are:");
	    for ( int i = 1; i <= 20; i++ ) {
	    	System.out.println(String.format("%2d", i) + ": " + term);
	    	term = nextCalkinWilf(term);
	    }
	    System.out.println();

	    Rational rational = new Rational(83_116, 51_639);
	    System.out.println(" " + rational + " is the " + termIndex(rational) + "th term of the sequence.");

	}

	private static Rational nextCalkinWilf(Rational aTerm) {
		Rational divisor = Rational.TWO.multiply(aTerm.floor()).add(Rational.ONE).subtract(aTerm);
		return Rational.ONE.divide(divisor);
	}

	private static long termIndex(Rational aRational) {
	    long result = 0;
	    long binaryDigit = 1;
	    long power = 0;
	    for ( long term : continuedFraction(aRational) ) {
	        for ( long i = 0; i < term; power++, i++ ) {
	            result |= ( binaryDigit << power );
	        }
	        binaryDigit = ( binaryDigit == 0 ) ? 1 : 0;
	    }
	    return result;
	}

	private static Deque<Long> continuedFraction(Rational aRational) {
	    long numerator = aRational.numerator();
	    long denominator = aRational.denominator();
	    Deque<Long> result = new ArrayDeque<Long>();

	    while ( numerator != 1 ) {
	        result.addLast(numerator / denominator);
	        long copyNumerator = numerator;
	        numerator = denominator;
	        denominator = copyNumerator % denominator;
	    }

	    if ( ! result.isEmpty() && result.size() % 2 == 0 ) {
	    	final long back = result.removeLast();
	    	result.addLast(back - 1);
	        result.addLast(1L);
	    }
	    return result;
	}

}

final class Rational {

	public Rational(long aNumerator, long aDenominator) {
    	if ( aDenominator == 0 ) {
    		throw new ArithmeticException("Denominator cannot be zero");
    	}
    	if ( aNumerator == 0 ) {
    		aDenominator = 1;
    	}
    	if ( aDenominator < 0 ) {
    		numer = -aNumerator;
    		denom = -aDenominator;
    	} else {
    		numer = aNumerator;
    		denom = aDenominator;
    	}
    	final long gcd = gcd(numer, denom);
    	numer = numer / gcd;
    	denom = denom / gcd;
    }

	public Rational add(Rational aOther) {
    	return new Rational(numer * aOther.denom + aOther.numer * denom, denom * aOther.denom);
    }

	public Rational subtract(Rational aOther) {
		return new Rational(numer * aOther.denom - aOther.numer * denom, denom * aOther.denom);
	}

    public Rational multiply(Rational aOther) {
		return new Rational(numer * aOther.numer, denom * aOther.denom);
	}

    public Rational divide(Rational aOther) {
		return new Rational(numer * aOther.denom, denom * aOther.numer);
	}

    public Rational floor() {
    	return new Rational(numer / denom, 1);
    }

    public long numerator() {
    	return numer;
    }

    public long denominator() {
    	return denom;
    }

    @Override
    public String toString() {
    	return numer + "/" + denom;
    }

    public static final Rational ONE = new Rational(1, 1);
    public static final Rational TWO = new Rational(2, 1);

    private long gcd(long aOne, long aTwo) {
    	if ( aTwo == 0 ) {
    		return aOne;
    	}
    	return gcd(aTwo, aOne % aTwo);
    }

    private long numer;
    private long denom;

}


Call a function

Demonstrate the different syntax and semantics provided for calling a function.

This may include:
:*   Calling a function that requires no arguments
:*   Calling a function with a fixed number of arguments
:*   Calling a function with optional arguments
:*   Calling a function with a variable number of arguments
:*   Calling a function with named arguments
:*   Using a function in statement context
:*   Using a function in first-class context within an expression
:*   Obtaining the return value of a function
:*   Distinguishing built-in functions and user-defined functions
:*   Distinguishing subroutines and functions
;*   Stating whether arguments are passed by value or by reference
;*   Is partial application possible and how

This task is ''not'' about defining functions.

Solution:
int myMethod( Map<String,Object> params ){
    return
       ((Integer)params.get("x")).intValue()
       + ((Integer)params.get("y")).intValue();
}


Canonicalize CIDR

Implement a function or program that, given a range of IPv4 addresses in CIDR notation (dotted-decimal/network-bits), will return/output the same range in canonical form.

That is, the IP address portion of the output CIDR block must not contain any set (1) bits in the host part of the address.

;Example:
Given   '''87.70.141.1/22''',    your code should output    '''87.70.140.0/22'''

;Explanation:
An Internet Protocol version 4 address is a 32-bit value, conventionally represented as a number in base 256 using dotted-decimal notation, where each base-256 digit is given in decimal and the digits are separated by periods. Logically, this 32-bit value represents two components: the leftmost (most-significant) bits determine the network portion of the address, while the rightmost (least-significant) bits determine the host portion. Classless Internet Domain Routing block notation indicates where the boundary between these two components is for a given address by adding a slash followed by the number of bits in the network portion.

In general, CIDR blocks stand in for the entire set of IP addresses sharing the same network component, so it's common to see access control lists that specify individual IP addresses using /32 to indicate that only the one address is included. Software accepting this notation as input often expects it to be entered in canonical form, in which the host bits are all zeroes. But network admins sometimes skip this step and just enter the address of a specific host on the subnet with the network size, resulting in a non-canonical entry.

The example address, 87.70.141.1/22, represents binary 0101011101000110100011 / 0100000001, with the / indicating the network/host division. To canonicalize, clear all the bits to the right of the / and convert back to dotted decimal: 0101011101000110100011 / 0000000000 - 87.70.140.0.

;More examples for testing

        36.18.154.103/12    -  36.16.0.0/12
        62.62.197.11/29     -  62.62.197.8/29
        67.137.119.181/4    -  64.0.0.0/4
        161.214.74.21/24    -  161.214.74.0/24
        184.232.176.184/18  -  184.232.128.0/18

Solution:
import java.text.MessageFormat;
import java.text.ParseException;

public class CanonicalizeCIDR {
    public static void main(String[] args) {
        for (String test : TESTS) {
            try {
                CIDR cidr = new CIDR(test);
                System.out.printf("%-18s -> %s\n", test, cidr.toString());
            } catch (Exception ex) {
                System.err.printf("Error parsing '%s': %s\n", test, ex.getLocalizedMessage());
            }
        }
    }

    private static class CIDR {
        private CIDR(int address, int maskLength) {
            this.address = address;
            this.maskLength = maskLength;
        }

        private CIDR(String str) throws Exception {
            Object[] args = new MessageFormat(FORMAT).parse(str);
            int address = 0;
            for (int i = 0; i < 4; ++i) {
                int a = ((Number)args[i]).intValue();
                if (a < 0 || a > 255)
                    throw new Exception("Invalid IP address");
                address <<= 8;
                address += a;
            }
            int maskLength = ((Number)args[4]).intValue();
            if (maskLength < 1 || maskLength > 32)
                throw new Exception("Invalid mask length");
            int mask = ~((1 << (32 - maskLength)) - 1);
            this.address = address & mask;
            this.maskLength = maskLength;
        }

        public String toString() {
            int address = this.address;
            int d = address & 0xFF;
            address >>= 8;
            int c = address & 0xFF;
            address >>= 8;
            int b = address & 0xFF;
            address >>= 8;
            int a = address & 0xFF;
            Object[] args = { a, b, c, d, maskLength };
            return new MessageFormat(FORMAT).format(args);
        }

        private int address;
        private int maskLength;
        private static final String FORMAT = "{0,number,integer}.{1,number,integer}.{2,number,integer}.{3,number,integer}/{4,number,integer}";
    };

    private static final String[] TESTS = {
        "87.70.141.1/22",
        "36.18.154.103/12",
        "62.62.197.11/29",
        "67.137.119.181/4",
        "161.214.74.21/24",
        "184.232.176.184/18"
    };
}


Cantor set

Draw a Cantor set.

See details at this Wikipedia webpage:   Cantor set

Solution:
public class App {
    private static final int WIDTH = 81;
    private static final int HEIGHT = 5;

    private static char[][] lines;
    static {
        lines = new char[HEIGHT][WIDTH];
        for (int i = 0; i < HEIGHT; i++) {
            for (int j = 0; j < WIDTH; j++) {
                lines[i][j] = '*';
            }
        }
    }

    private static void cantor(int start, int len, int index) {
        int seg = len / 3;
        if (seg == 0) return;
        for (int i = index; i < HEIGHT; i++) {
            for (int j = start + seg; j < start + seg * 2; j++) {
                lines[i][j] = ' ';
            }
        }
        cantor(start, seg, index + 1);
        cantor(start + seg * 2, seg, index + 1);
    }

    public static void main(String[] args) {
        cantor(0, WIDTH, 1);
        for (int i = 0; i < HEIGHT; i++) {
            for (int j = 0; j < WIDTH; j++) {
                System.out.print(lines[i][j]);
            }
            System.out.println();
        }
    }
}


Cartesian product of two or more lists

Show one or more idiomatic ways of generating the Cartesian product of two arbitrary lists in your language.

Demonstrate that your function/method correctly returns:
::{1, 2} x {3, 4} = {(1, 3), (1, 4), (2, 3), (2, 4)}

and, in contrast:
::{3, 4} x {1, 2} = {(3, 1), (3, 2), (4, 1), (4, 2)}

Also demonstrate, using your function/method, that the product of an empty list with any other list is empty.
:: {1, 2} x {} = {}
:: {} x {1, 2} = {}

For extra credit, show or write a function returning the n-ary product of an arbitrary number of lists, each of arbitrary length. Your function might, for example, accept a single argument which is itself a list of lists, and return the n-ary product of those lists.

Use your n-ary Cartesian product function to show the following products:
:: {1776, 1789} x {7, 12} x {4, 14, 23} x {0, 1}
:: {1, 2, 3} x {30} x {500, 100}
:: {1, 2, 3} x {} x {500, 100}

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

public class CartesianProduct<V> {

	public List<List<V>> product(List<List<V>> lists) {
		List<List<V>> product = new ArrayList<>();

		// We first create a list for each value of the first list
		product(product, new ArrayList<>(), lists);

		return product;
	}

	private void product(List<List<V>> result, List<V> existingTupleToComplete, List<List<V>> valuesToUse) {
		for (V value : valuesToUse.get(0)) {
			List<V> newExisting = new ArrayList<>(existingTupleToComplete);
			newExisting.add(value);

			// If only one column is left
			if (valuesToUse.size() == 1) {
				// We create a new list with the exiting tuple for each value with the value
				// added
				result.add(newExisting);
			} else {
				// If there are still several columns, we go into recursion for each value
				List<List<V>> newValues = new ArrayList<>();
				// We build the next level of values
				for (int i = 1; i < valuesToUse.size(); i++) {
					newValues.add(valuesToUse.get(i));
				}

				product(result, newExisting, newValues);
			}
		}
	}

	public static void main(String[] args) {
		List<Integer> list1 = new ArrayList<>(Arrays.asList(new Integer[] { 1776, 1789 }));
		List<Integer> list2 = new ArrayList<>(Arrays.asList(new Integer[] { 7, 12 }));
		List<Integer> list3 = new ArrayList<>(Arrays.asList(new Integer[] { 4, 14, 23 }));
		List<Integer> list4 = new ArrayList<>(Arrays.asList(new Integer[] { 0, 1 }));

		List<List<Integer>> input = new ArrayList<>();
		input.add(list1);
		input.add(list2);
		input.add(list3);
		input.add(list4);

		CartesianProduct<Integer> cartesianProduct = new CartesianProduct<>();
		List<List<Integer>> product = cartesianProduct.product(input);
		System.out.println(product);
	}
}


Casting out nines

Task   (in three parts):

;Part 1
Write a procedure (say \mathit{co9}(x)) which implements Casting Out Nines as described by returning the checksum for x. Demonstrate the procedure using the examples given there, or others you may consider lucky.

Note that this function does nothing more than calculate the least positive residue, modulo 9. Many of the solutions omit Part 1 for this reason. Many languages have a modulo operator, of which this is a trivial application.

With that understanding, solutions to Part 1, if given, are encouraged to follow the naive pencil-and-paper or mental arithmetic of repeated digit addition understood to be "casting out nines", or some approach other than just reducing modulo 9 using a built-in operator. Solutions for part 2 and 3 are not required to make use of the function presented in part 1.

;Part 2
Notwithstanding past Intel microcode errors, checking computer calculations like this would not be sensible. To find a computer use for your procedure:
: Consider the statement "318682 is 101558 + 217124 and squared is 101558217124" (see: [[Kaprekar numbers#Casting Out Nines (fast)]]).
: note that 318682 has the same checksum as (101558 + 217124);
: note that 101558217124 has the same checksum as (101558 + 217124) because for a Kaprekar they are made up of the same digits (sometimes with extra zeroes);
: note that this implies that for Kaprekar numbers the checksum of k equals the checksum of k^2.

Demonstrate that your procedure can be used to generate or filter a range of numbers with the property \mathit{co9}(k) = \mathit{co9}(k^2) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;Part 3
Considering this MathWorld page, produce a efficient algorithm based on the more mathematical treatment of Casting Out Nines, and realizing:
: \mathit{co9}(x) is the residual of x mod 9;
: the procedure can be extended to bases other than 9.

Demonstrate your algorithm by generating or filtering a range of numbers with the property k%(\mathit{Base}-1) == (k^2)%(\mathit{Base}-1) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;related tasks
* [[First perfect square in base N with N unique digits]]
* [[Kaprekar numbers]]

Solution:
import java.util.*;
import java.util.stream.IntStream;

public class CastingOutNines {

    public static void main(String[] args) {
        System.out.println(castOut(16, 1, 255));
        System.out.println(castOut(10, 1, 99));
        System.out.println(castOut(17, 1, 288));
    }

    static List<Integer> castOut(int base, int start, int end) {
        int[] ran = IntStream
                .range(0, base - 1)
                .filter(x -> x % (base - 1) == (x * x) % (base - 1))
                .toArray();

        int x = start / (base - 1);

        List<Integer> result = new ArrayList<>();
        while (true) {
            for (int n : ran) {
                int k = (base - 1) * x + n;
                if (k < start)
                    continue;
                if (k > end)
                    return result;
                result.add(k);
            }
            x++;
        }
    }
}


Catalan numbers/Pascal's triangle

Print out the first   '''15'''   Catalan numbers by extracting them from Pascal's triangle.

;See:
*   Catalan Numbers and the Pascal Triangle.      This method enables calculation of Catalan Numbers using only addition and subtraction.

*   Catalan's Triangle for a Number Triangle that generates Catalan Numbers using only addition.
*   Sequence A000108 on OEIS has a lot of information on Catalan Numbers.

;Related Tasks:
[[Pascal's triangle]]

Solution:
public class Test {
    public static void main(String[] args) {
        int N = 15;
        int[] t = new int[N + 2];
        t[1] = 1;

        for (int i = 1; i <= N; i++) {

            for (int j = i; j > 1; j--)
                t[j] = t[j] + t[j - 1];

            t[i + 1] = t[i];

            for (int j = i + 1; j > 1; j--)
                t[j] = t[j] + t[j - 1];

            System.out.printf("%d ", t[i + 1] - t[i]);
        }
    }
}


Catamorphism

''Reduce'' is a function or method that is used to take the values in an array or a list and apply a function to successive members of the list to produce (or reduce them to), a single value.

;Task:
Show how ''reduce'' (or ''foldl'' or ''foldr'' etc), work (or would be implemented) in your language.

;See also:
* Wikipedia article:   Fold
* Wikipedia article:   Catamorphism

Solution:
import java.util.stream.Stream;

public class ReduceTask {

    public static void main(String[] args) {
        System.out.println(Stream.of(1, 2, 3, 4, 5).mapToInt(i -> i).sum());
        System.out.println(Stream.of(1, 2, 3, 4, 5).reduce(1, (a, b) -> a * b));
    }
}


Chaocipher

Description:
The Chaocipher was invented by J.F.Byrne in 1918 and, although simple by modern cryptographic standards, does not appear to have been broken until the algorithm was finally disclosed by his family in 2010.

The algorithm is described in this paper by M.Rubin in 2010 and there is a C# implementation here.

;Task:
Code the algorithm in your language and to test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself.

Solution:
import java.util.Arrays;

public class Chaocipher {
    private enum Mode {
        ENCRYPT,
        DECRYPT
    }

    private static final String L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
    private static final String R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";

    private static int indexOf(char[] a, char c) {
        for (int i = 0; i < a.length; ++i) {
            if (a[i] == c) {
                return i;
            }
        }
        return -1;
    }

    private static String exec(String text, Mode mode) {
        return exec(text, mode, false);
    }

    private static String exec(String text, Mode mode, Boolean showSteps) {
        char[] left = L_ALPHABET.toCharArray();
        char[] right = R_ALPHABET.toCharArray();
        char[] eText = new char[text.length()];
        char[] temp = new char[26];

        for (int i = 0; i < text.length(); ++i) {
            if (showSteps) {
                System.out.printf("%s  %s\n", new String(left), new String(right));
            }
            int index;
            if (mode == Mode.ENCRYPT) {
                index = indexOf(right, text.charAt(i));
                eText[i] = left[index];
            } else {
                index = indexOf(left, text.charAt(i));
                eText[i] = right[index];
            }
            if (i == text.length() - 1) {
                break;
            }

            // permute left

            if (26 - index >= 0) System.arraycopy(left, index, temp, 0, 26 - index);
            System.arraycopy(left, 0, temp, 26 - index, index);
            char store = temp[1];
            System.arraycopy(temp, 2, temp, 1, 12);
            temp[13] = store;
            left = Arrays.copyOf(temp, temp.length);

            // permute right

            if (26 - index >= 0) System.arraycopy(right, index, temp, 0, 26 - index);
            System.arraycopy(right, 0, temp, 26 - index, index);
            store = temp[0];
            System.arraycopy(temp, 1, temp, 0, 25);
            temp[25] = store;
            store = temp[2];
            System.arraycopy(temp, 3, temp, 2, 11);
            temp[13] = store;
            right = Arrays.copyOf(temp, temp.length);
        }

        return new String(eText);
    }

    public static void main(String[] args) {
        String plainText = "WELLDONEISBETTERTHANWELLSAID";
        System.out.printf("The original plaintext is : %s\n", plainText);
        System.out.println("\nThe left and right alphabets after each permutation during encryption are:");
        String cipherText = exec(plainText, Mode.ENCRYPT, true);
        System.out.printf("\nThe cipher text is : %s\n", cipherText);
        String plainText2 = exec(cipherText, Mode.DECRYPT);
        System.out.printf("\nThe recovered plaintext is : %s\n", plainText2);
    }
}


Chaos game

The Chaos Game is a method of generating the attractor of an iterated function system (IFS).

One of the best-known and simplest examples creates a fractal, using a polygon and an initial point selected at random.

;Task
Play the Chaos Game using the corners of an equilateral triangle as the reference points.   Add a starting point at random (preferably inside the triangle).   Then add the next point halfway between the starting point and one of the reference points.   This reference point is chosen at random.

After a sufficient number of iterations, the image of a Sierpinski Triangle should emerge.

;See also
* The Game of Chaos

Solution:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class ChaosGame extends JPanel {
    static class ColoredPoint extends Point {
        int colorIndex;

        ColoredPoint(int x, int y, int idx) {
            super(x, y);
            colorIndex = idx;
        }
    }

    Stack<ColoredPoint> stack = new Stack<>();
    Point[] points = new Point[3];
    Color[] colors = {Color.red, Color.green, Color.blue};
    Random r = new Random();

    public ChaosGame() {
        Dimension dim = new Dimension(640, 640);
        setPreferredSize(dim);
        setBackground(Color.white);

        int margin = 60;
        int size = dim.width - 2 * margin;

        points[0] = new Point(dim.width / 2, margin);
        points[1] = new Point(margin, size);
        points[2] = new Point(margin + size, size);

        stack.push(new ColoredPoint(-1, -1, 0));

        new Timer(10, (ActionEvent e) -> {
            if (stack.size() < 50_000) {
                for (int i = 0; i < 1000; i++)
                    addPoint();
                repaint();
            }
        }).start();
    }

    private void addPoint() {
        try {
            int colorIndex = r.nextInt(3);
            Point p1 = stack.peek();
            Point p2 = points[colorIndex];
            stack.add(halfwayPoint(p1, p2, colorIndex));
        } catch (EmptyStackException e) {
            e.printStackTrace();
        }
    }

    void drawPoints(Graphics2D g) {
        for (ColoredPoint p : stack) {
            g.setColor(colors[p.colorIndex]);
            g.fillOval(p.x, p.y, 1, 1);
        }
    }

    ColoredPoint halfwayPoint(Point a, Point b, int idx) {
        return new ColoredPoint((a.x + b.x) / 2, (a.y + b.y) / 2, idx);
    }

    @Override
    public void paintComponent(Graphics gg) {
        super.paintComponent(gg);
        Graphics2D g = (Graphics2D) gg;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        drawPoints(g);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setTitle("Chaos Game");
            f.setResizable(false);
            f.add(new ChaosGame(), BorderLayout.CENTER);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}


Check Machin-like formulas

Machin-like formulas   are useful for efficiently computing numerical approximations for \pi

;Task:
Verify the following Machin-like formulas are correct by calculating the value of '''tan'''   (''right hand side)'' for each equation using exact arithmetic and showing they equal '''1''':

: {\pi\over4} = \arctan{1\over2} + \arctan{1\over3}
: {\pi\over4} = 2 \arctan{1\over3} + \arctan{1\over7}
: {\pi\over4} = 4 \arctan{1\over5} - \arctan{1\over239}
: {\pi\over4} = 5 \arctan{1\over7} + 2 \arctan{3\over79}
: {\pi\over4} = 5 \arctan{29\over278} + 7 \arctan{3\over79}
: {\pi\over4} = \arctan{1\over2} + \arctan{1\over5} + \arctan{1\over8}
: {\pi\over4} = 4 \arctan{1\over5} - \arctan{1\over70} + \arctan{1\over99}
: {\pi\over4} = 5 \arctan{1\over7} + 4 \arctan{1\over53} + 2 \arctan{1\over4443}
: {\pi\over4} = 6 \arctan{1\over8} + 2 \arctan{1\over57} + \arctan{1\over239}
: {\pi\over4} = 8 \arctan{1\over10} - \arctan{1\over239} - 4 \arctan{1\over515}
: {\pi\over4} = 12 \arctan{1\over18} + 8 \arctan{1\over57} - 5 \arctan{1\over239}
: {\pi\over4} = 16 \arctan{1\over21} + 3 \arctan{1\over239} + 4 \arctan{3\over1042}
: {\pi\over4} = 22 \arctan{1\over28} + 2 \arctan{1\over443} - 5 \arctan{1\over1393} - 10 \arctan{1\over11018}
: {\pi\over4} = 22 \arctan{1\over38} + 17 \arctan{7\over601} + 10 \arctan{7\over8149}
: {\pi\over4} = 44 \arctan{1\over57} + 7 \arctan{1\over239} - 12 \arctan{1\over682} + 24 \arctan{1\over12943}
: {\pi\over4} = 88 \arctan{1\over172} + 51 \arctan{1\over239} + 32 \arctan{1\over682} + 44 \arctan{1\over5357} + 68 \arctan{1\over12943}

and confirm that the following formula is ''incorrect'' by showing   '''tan'''   (''right hand side)''   is ''not''   '''1''':

: {\pi\over4} = 88 \arctan{1\over172} + 51 \arctan{1\over239} + 32 \arctan{1\over682} + 44 \arctan{1\over5357} + 68 \arctan{1\over12944}

These identities are useful in calculating the values:
: \tan(a + b) = {\tan(a) + \tan(b) \over 1 - \tan(a) \tan(b)}

: \tan\left(\arctan{a \over b}\right) = {a \over b}

: \tan(-a) = -\tan(a)

You can store the equations in any convenient data structure, but for extra credit parse them from human-readable text input.

Note: to formally prove the formula correct, it would have to be shown that ''{-3 pi \over 4} < right hand side < {5 pi \over 4}'' due to ''\tan()'' periodicity.

Solution:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CheckMachinFormula {

    private static String FILE_NAME = "MachinFormula.txt";

    public static void main(String[] args) {
        try {
            runPrivate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void runPrivate() throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(new File(FILE_NAME)));) {
            String inLine = null;
            while ( (inLine = reader.readLine()) != null ) {
                String[] split = inLine.split("=");
                System.out.println(tanLeft(split[0].trim()) + " = " + split[1].trim().replaceAll("\\s+", " ") + " = " + tanRight(split[1].trim()));
            }
        }
    }

    private static String tanLeft(String formula) {
        if ( formula.compareTo("pi/4") == 0 ) {
            return "1";
        }
        throw new RuntimeException("ERROR 104:  Unknown left side: " + formula);
    }

    private static final Pattern ARCTAN_PATTERN = Pattern.compile("(-{0,1}\\d+)\\*arctan\\((\\d+)/(\\d+)\\)");

    private static Fraction tanRight(String formula) {
        Matcher matcher = ARCTAN_PATTERN.matcher(formula);
        List<Term> terms = new ArrayList<>();
        while ( matcher.find() ) {
            terms.add(new Term(Integer.parseInt(matcher.group(1)), new Fraction(matcher.group(2), matcher.group(3))));
        }
        return evaluateArctan(terms);
    }

    private static Fraction evaluateArctan(List<Term> terms) {
        if ( terms.size() == 1 ) {
            Term term = terms.get(0);
            return evaluateArctan(term.coefficient, term.fraction);
        }
        int size = terms.size();
        List<Term> left = terms.subList(0, (size+1) / 2);
        List<Term> right = terms.subList((size+1) / 2, size);
        return arctanFormula(evaluateArctan(left), evaluateArctan(right));
    }

    private static Fraction evaluateArctan(int coefficient, Fraction fraction) {
        //System.out.println("C = " + coefficient + ", F = " + fraction);
        if ( coefficient == 1 ) {
            return fraction;
        }
        else if ( coefficient < 0 ) {
            return evaluateArctan(-coefficient, fraction).negate();
        }
        if ( coefficient % 2 == 0 ) {
            Fraction f = evaluateArctan(coefficient/2, fraction);
            return arctanFormula(f, f);
        }
        Fraction a = evaluateArctan(coefficient/2, fraction);
        Fraction b = evaluateArctan(coefficient - (coefficient/2), fraction);
        return arctanFormula(a, b);
    }

    private static Fraction arctanFormula(Fraction f1, Fraction f2) {
        return f1.add(f2).divide(Fraction.ONE.subtract(f1.multiply(f2)));
    }

    private static class Fraction {

        public static final Fraction ONE = new Fraction("1", "1");

        private BigInteger numerator;
        private BigInteger denominator;

        public Fraction(String num, String den) {
            numerator = new BigInteger(num);
            denominator = new BigInteger(den);
        }

        public Fraction(BigInteger num, BigInteger den) {
            numerator = num;
            denominator = den;
        }

        public Fraction negate() {
            return new Fraction(numerator.negate(), denominator);
        }

        public Fraction add(Fraction f) {
            BigInteger gcd = denominator.gcd(f.denominator);
            BigInteger first = numerator.multiply(f.denominator.divide(gcd));
            BigInteger second = f.numerator.multiply(denominator.divide(gcd));
            return new Fraction(first.add(second), denominator.multiply(f.denominator).divide(gcd));
        }

        public Fraction subtract(Fraction f) {
            return add(f.negate());
        }

        public Fraction multiply(Fraction f) {
            BigInteger num = numerator.multiply(f.numerator);
            BigInteger den = denominator.multiply(f.denominator);
            BigInteger gcd = num.gcd(den);
            return new Fraction(num.divide(gcd), den.divide(gcd));
        }

        public Fraction divide(Fraction f) {
            return multiply(new Fraction(f.denominator, f.numerator));
        }

        @Override
        public String toString() {
            if ( denominator.compareTo(BigInteger.ONE) == 0 ) {
                return numerator.toString();
            }
            return numerator + " / " + denominator;
        }
    }

    private static class Term {

        private int coefficient;
        private Fraction fraction;

        public Term(int c, Fraction f) {
            coefficient = c;
            fraction = f;
        }
    }

}


Cheryl's birthday

Albert and Bernard just became friends with Cheryl, and they want to know when her birthday is.

Cheryl gave them a list of ten possible dates:
      May 15,     May 16,     May 19
      June 17,    June 18
      July 14,    July 16
      August 14,  August 15,  August 17

Cheryl then tells Albert the   ''month''   of birth,   and Bernard the   ''day''   (of the month)   of birth.
  1)  Albert:   I don't know when Cheryl's birthday is, but I know that Bernard does not know too.
  2)  Bernard:  At first I don't know when Cheryl's birthday is, but I know now.
  3)  Albert:   Then I also know when Cheryl's birthday is.

;Task
Write a computer program to deduce, by successive elimination, Cheryl's birthday.

;Related task:
* [[Sum and Product Puzzle]]

;References
* Wikipedia article of the same name.
* Tuple Relational Calculus

Solution:
import java.time.Month;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Main {
    private static class Birthday {
        private Month month;
        private int day;

        public Birthday(Month month, int day) {
            this.month = month;
            this.day = day;
        }

        public Month getMonth() {
            return month;
        }

        public int getDay() {
            return day;
        }

        @Override
        public String toString() {
            return month + " " + day;
        }
    }

    public static void main(String[] args) {
        List<Birthday> choices = List.of(
            new Birthday(Month.MAY, 15),
            new Birthday(Month.MAY, 16),
            new Birthday(Month.MAY, 19),
            new Birthday(Month.JUNE, 17),
            new Birthday(Month.JUNE, 18),
            new Birthday(Month.JULY, 14),
            new Birthday(Month.JULY, 16),
            new Birthday(Month.AUGUST, 14),
            new Birthday(Month.AUGUST, 15),
            new Birthday(Month.AUGUST, 17)
        );
        System.out.printf("There are %d candidates remaining.\n", choices.size());

        // The month cannot have a unique day because Albert knows the month, and knows that Bernard does not know the answer
        Set<Month> uniqueMonths = choices.stream()
            .collect(Collectors.groupingBy(Birthday::getDay))
            .values()
            .stream()
            .filter(g -> g.size() == 1)
            .flatMap(Collection::stream)
            .map(Birthday::getMonth)
            .collect(Collectors.toSet());
        List<Birthday> f1List = choices.stream()
            .filter(birthday -> !uniqueMonths.contains(birthday.month))
            .collect(Collectors.toList());
        System.out.printf("There are %d candidates remaining.\n", f1List.size());

        // Bernard now knows the answer, so the day must be unique within the remaining choices
        List<Birthday> f2List = f1List.stream()
            .collect(Collectors.groupingBy(Birthday::getDay))
            .values()
            .stream()
            .filter(g -> g.size() == 1)
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
        System.out.printf("There are %d candidates remaining.\n", f2List.size());

        // Albert knows the answer too, so the month must be unique within the remaining choices
        List<Birthday> f3List = f2List.stream()
            .collect(Collectors.groupingBy(Birthday::getMonth))
            .values()
            .stream()
            .filter(g -> g.size() == 1)
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
        System.out.printf("There are %d candidates remaining.\n", f3List.size());

        if (f3List.size() == 1) {
            System.out.printf("Cheryl's birthday is %s\n", f3List.get(0));
        } else {
            System.out.println("No unique choice found");
        }
    }
}


Chinese remainder theorem

Suppose   n_1,   n_2,   \ldots,   n_k   are positive [[integer]]s that are pairwise co-prime.

Then, for any given sequence of integers   a_1,   a_2,   \dots,   a_k,   there exists an integer   x   solving the following system of simultaneous congruences:

::: \begin{align}
  x &\equiv a_1 \pmod{n_1} \\
  x &\equiv a_2 \pmod{n_2} \\
    &{}\  \  \vdots \\
  x &\equiv a_k \pmod{n_k}
\end{align}

Furthermore, all solutions   x   of this system are congruent modulo the product,    N=n_1n_2\ldots n_k.

;Task:
Write a program to solve a system of linear congruences by applying the   Chinese Remainder Theorem.

If the system of equations cannot be solved, your program must somehow indicate this.

(It may throw an exception or return a special false value.)

Since there are infinitely many solutions, the program should return the unique solution   s   where   0 \leq s \leq n_1n_2\ldots n_k.

''Show the functionality of this program'' by printing the result such that the   n's   are   [3,5,7]   and the   a's   are   [2,3,2].

'''Algorithm''':   The following algorithm only applies if the   n_i's   are pairwise co-prime.

Suppose, as above, that a solution is required for the system of congruences:

::: x \equiv a_i \pmod{n_i} \quad\mathrm{for}\; i = 1, \ldots, k

Again, to begin, the product   N = n_1n_2 \ldots n_k   is defined.

Then a solution   x   can be found as follows:

For each   i,   the integers   n_i   and   N/n_i   are co-prime.

Using the   Extended Euclidean algorithm,   we can find integers   r_i   and   s_i   such that   r_i n_i + s_i N/n_i = 1.

Then, one solution to the system of simultaneous congruences is:

::: x = \sum_{i=1}^k a_i s_i N/n_i

and the minimal solution,

::: x \pmod{N}.

Solution: Translation of [[Chinese_remainder_theorem#Python|Python]] via [[Chinese_remainder_theorem#D|D]]


Chinese remainder theorem

Solution:
import static java.util.Arrays.stream;

public class ChineseRemainderTheorem {

    public static int chineseRemainder(int[] n, int[] a) {

        int prod = stream(n).reduce(1, (i, j) -> i * j);

        int p, sm = 0;
        for (int i = 0; i < n.length; i++) {
            p = prod / n[i];
            sm += a[i] * mulInv(p, n[i]) * p;
        }
        return sm % prod;
    }

    private static int mulInv(int a, int b) {
        int b0 = b;
        int x0 = 0;
        int x1 = 1;

        if (b == 1)
            return 1;

        while (a > 1) {
            int q = a / b;
            int amb = a % b;
            a = b;
            b = amb;
            int xqx = x1 - q * x0;
            x1 = x0;
            x0 = xqx;
        }

        if (x1 < 0)
            x1 += b0;

        return x1;
    }

    public static void main(String[] args) {
        int[] n = {3, 5, 7};
        int[] a = {2, 3, 2};
        System.out.println(chineseRemainder(n, a));
    }
}


Chinese zodiac

Determine the Chinese zodiac sign and related associations for a given year.
Traditionally, the Chinese have counted years using two lists of labels, one of length 10 (the "celestial stems") and one of length 12 (the "terrestrial branches"). The labels do not really have any meaning outside their positions in the two lists; they're simply a traditional enumeration device, used much as Westerners use letters and numbers. They were historically used for months and days as well as years, and the stems are still sometimes used for school grades.

Years cycle through both lists concurrently, so that both stem and branch advance each year; if we used Roman letters for the stems and numbers for the branches, consecutive years would be labeled A1, B2, C3, etc. Since the two lists are different lengths, they cycle back to their beginning at different points: after J10 we get A11, and then after B12 we get C1. The result is a repeating 60-year pattern within which each pair of names occurs only once.

Mapping the branches to twelve traditional animal deities results in the well-known "Chinese zodiac", assigning each year to a given animal. For example, Sunday, January 22, 2023 CE (in the common Gregorian calendar) began the lunisolar Year of the Rabbit.

The celestial stems do not have a one-to-one mapping like that of the branches to animals; however, the five pairs of consecutive stems are each associated with one of the five traditional Chinese elements (Wood, Fire, Earth, Metal, and Water). Further, one of the two years within each element is assigned to yin, the other to yang.

Thus, the Chinese year beginning in 2023 CE is also the yin year of Water. Since 12 is an even number, the association between animals and yin/yang doesn't change; consecutive Years of the Rabbit will cycle through the five elements, but will always be yin.

;Task: Create a subroutine or program that will return or output the animal, yin/yang association, and element for the lunisolar year that begins in a given CE year.

You may optionally provide more information in the form of the year's numerical position within the 60-year cycle and/or its actual Chinese stem-branch name (in Han characters or Pinyin transliteration).

;Requisite information:
* The animal cycle runs in this order: Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Goat, Monkey, Rooster, Dog, Pig.
* The element cycle runs in this order: Wood, Fire, Earth, Metal, Water.
* Each element gets two consecutive years; a yang followed by a yin.
* The current 60-year cycle began in 1984; any multiple of 60 years from that point may be used to reckon from.

Thus, year 1 of a cycle is the year of the Wood Rat (yang), year 2 the Wood Ox (yin), and year 3 the Fire Tiger (yang). The year 2023 - which, as already noted, is the year of the Water Rabbit (yin) - is the 40th year of the current cycle.

;Information for optional task:
* The ten celestial stems are '''Jia ''' ''jia'', '''Yi ''' ''yi'', '''Bing ''' ''bing'', '''Ding ''' ''ding'', '''Wu ''' ''wu'', '''Ji ''' ''ji'', '''Geng ''' ''geng'', '''Xin ''' ''xin'', '''Ren ''' ''ren'', and '''Gui ''' ''gui''. With the ASCII version of Pinyin tones, the names are written "jia3", "yi3", "bing3", "ding1", "wu4", "ji3", "geng1", "xin1", "ren2", and "gui3".
* The twelve terrestrial branches are '''Zi ''' ''zi'', '''Chou ''' ''chou'', '''Yin ''' ''yin'', '''Mao ''' ''mao'', '''Chen ''' ''chen'', '''Si ''' ''si'', '''Wu ''' ''wu'', '''Wei ''' ''wei'', '''Shen ''' ''shen'', '''You ''' ''you'', '''Xu ''' ''xu'', '''Hai ''' ''hai''. In ASCII Pinyin, those are "zi3", "chou3", "yin2", "mao3", "chen2", "si4", "wu3", "wei4", "shen1", "you3", "xu1", and "hai4".

Therefore 1984 was '''Jia Zi ''' (''jia-zi'', or jia3-zi3).  2023 is '''Gui Mao ''' (''gui-mao'' or gui3-mao3).

Solution:
public class Zodiac {

	final static String animals[]={"Rat","Ox","Tiger","Rabbit","Dragon","Snake","Horse","Goat","Monkey","Rooster","Dog","Pig"};
	final static String elements[]={"Wood","Fire","Earth","Metal","Water"};
	final static String animalChars[]={"子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"};
	static String elementChars[][]={{"甲","丙","戊","庚","壬"},{"乙","丁","己","辛","癸"}};

	static String getYY(int year)
	{
	    if(year%2==0)
	    {
	        return "yang";
	    }
	    else
	    {
	        return "yin";
	    }
	}

	public static void main(String[] args)
	{
		int years[]={1935,1938,1968,1972,1976,1984,1985,2017};
		for(int i=0;i<years.length;i++)
		{
			System.out.println(years[i]+" is the year of the "+elements[(int) Math.floor((years[i]-4)%10/2)]+" "+animals[(years[i]-4)%12]+" ("+getYY(years[i])+"). "+elementChars[years[i]%2][(int) Math.floor((years[i]-4)%10/2)]+animalChars[(years[i]-4)%12]);
		}
	}
}


Church numerals

In the Church encoding of natural numbers, the number N is encoded by a function that applies its first argument N times to its second argument.

* '''Church zero''' always returns the identity function, regardless of its first argument. In other words, the first argument is not applied to the second argument at all.
* '''Church one''' applies its first argument f just once to its second argument x, yielding '''f(x)'''
* '''Church two''' applies its first argument f twice to its second argument x, yielding '''f(f(x))'''
* and each successive Church numeral applies its first argument one additional time to its second argument, '''f(f(f(x)))''', '''f(f(f(f(x))))''' ...  The Church numeral 4, for example, returns a quadruple composition of the function supplied as its first argument.

Arithmetic operations on natural numbers can be similarly represented as functions on Church numerals.

In your language define:

* Church Zero,
* a Church successor function (a function on a Church numeral which returns the next Church numeral in the series),
* functions for Addition, Multiplication and Exponentiation over Church numerals,
* a function to convert integers to corresponding Church numerals,
* and a function to convert Church numerals to corresponding integers.

You should:

* Derive Church numerals three and four in terms of Church zero and a Church successor function.
* use Church numeral arithmetic to obtain the the sum and the product of Church 3 and Church 4,
* similarly obtain 4^3 and 3^4 in terms of Church numerals, using a Church numeral exponentiation function,
* convert each result back to an integer, and return it or print it to the console.

Solution:
package lvijay;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;

public class Church {
    public static interface ChurchNum extends Function<ChurchNum, ChurchNum> {
    }

    public static ChurchNum zero() {
        return f -> x -> x;
    }

    public static ChurchNum next(ChurchNum n) {
        return f -> x -> f.apply(n.apply(f).apply(x));
    }

    public static ChurchNum plus(ChurchNum a) {
        return b -> f -> x -> b.apply(f).apply(a.apply(f).apply(x));
    }

    public static ChurchNum pow(ChurchNum m) {
        return n -> m.apply(n);
    }

    public static ChurchNum mult(ChurchNum a) {
        return b -> f -> x -> b.apply(a.apply(f)).apply(x);
    }

    public static ChurchNum toChurchNum(int n) {
        if (n <= 0) {
            return zero();
        }
        return next(toChurchNum(n - 1));
    }

    public static int toInt(ChurchNum c) {
        AtomicInteger counter = new AtomicInteger(0);
        ChurchNum funCounter = f -> {
            counter.incrementAndGet();
            return f;
        };

        plus(zero()).apply(c).apply(funCounter).apply(x -> x);

        return counter.get();
    }

    public static void main(String[] args) {
        ChurchNum zero  = zero();
        ChurchNum three = next(next(next(zero)));
        ChurchNum four  = next(next(next(next(zero))));

        System.out.println("3+4=" + toInt(plus(three).apply(four))); // prints 7
        System.out.println("4+3=" + toInt(plus(four).apply(three))); // prints 7

        System.out.println("3*4=" + toInt(mult(three).apply(four))); // prints 12
        System.out.println("4*3=" + toInt(mult(four).apply(three))); // prints 12

        // exponentiation.  note the reversed order!
        System.out.println("3^4=" + toInt(pow(four).apply(three))); // prints 81
        System.out.println("4^3=" + toInt(pow(three).apply(four))); // prints 64

        System.out.println("  8=" + toInt(toChurchNum(8))); // prints 8
    }
}


Circles of given radius through two points

2 circles with a given radius through 2 points in 2D space.

Given two points on a plane and a radius, usually two circles of given radius can be drawn through the points.
;Exceptions:
# r==0.0 should be treated as never describing circles (except in the case where the points are coincident).
# If the points are coincident then an infinite number of circles with the point on their circumference can be drawn, unless r==0.0 as well which then collapses the circles to a point.
# If the points form a diameter then return two identical circles ''or'' return a single circle, according to which is the most natural mechanism for the implementation language.
# If the points are too far apart then no circles can be drawn.

;Task detail:
* Write a function/subroutine/method/... that takes two points and a radius and returns the two circles through those points, ''or some indication of special cases where two, possibly equal, circles cannot be returned''.
* Show here the output for the following inputs:

      p1                p2           r
0.1234, 0.9876    0.8765, 0.2345    2.0
0.0000, 2.0000    0.0000, 0.0000    1.0
0.1234, 0.9876    0.1234, 0.9876    2.0
0.1234, 0.9876    0.8765, 0.2345    0.5
0.1234, 0.9876    0.1234, 0.9876    0.0

;Related task:
*   [[Total circles area]].

;See also:
*   Finding the Center of a Circle from 2 Points and Radius from Math forum @ Drexel

Solution:
import java.util.Objects;

public class Circles {
    private static class Point {
        private final double x, y;

        public Point(Double x, Double y) {
            this.x = x;
            this.y = y;
        }

        public double distanceFrom(Point other) {
            double dx = x - other.x;
            double dy = y - other.y;
            return Math.sqrt(dx * dx + dy * dy);
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) return true;
            if (other == null || getClass() != other.getClass()) return false;
            Point point = (Point) other;
            return x == point.x && y == point.y;
        }

        @Override
        public String toString() {
            return String.format("(%.4f, %.4f)", x, y);
        }
    }

    private static Point[] findCircles(Point p1, Point p2, double r) {
        if (r < 0.0) throw new IllegalArgumentException("the radius can't be negative");
        if (r == 0.0 && p1 != p2) throw new IllegalArgumentException("no circles can ever be drawn");
        if (r == 0.0) return new Point[]{p1, p1};
        if (Objects.equals(p1, p2)) throw new IllegalArgumentException("an infinite number of circles can be drawn");
        double distance = p1.distanceFrom(p2);
        double diameter = 2.0 * r;
        if (distance > diameter) throw new IllegalArgumentException("the points are too far apart to draw a circle");
        Point center = new Point((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0);
        if (distance == diameter) return new Point[]{center, center};
        double mirrorDistance = Math.sqrt(r * r - distance * distance / 4.0);
        double dx = (p2.x - p1.x) * mirrorDistance / distance;
        double dy = (p2.y - p1.y) * mirrorDistance / distance;
        return new Point[]{
            new Point(center.x - dy, center.y + dx),
            new Point(center.x + dy, center.y - dx)
        };
    }

    public static void main(String[] args) {
        Point[] p = new Point[]{
            new Point(0.1234, 0.9876),
            new Point(0.8765, 0.2345),
            new Point(0.0000, 2.0000),
            new Point(0.0000, 0.0000)
        };
        Point[][] points = new Point[][]{
            {p[0], p[1]},
            {p[2], p[3]},
            {p[0], p[0]},
            {p[0], p[1]},
            {p[0], p[0]},
        };
        double[] radii = new double[]{2.0, 1.0, 2.0, 0.5, 0.0};
        for (int i = 0; i < radii.length; ++i) {
            Point p1 = points[i][0];
            Point p2 = points[i][1];
            double r = radii[i];
            System.out.printf("For points %s and %s with radius %f\n", p1, p2, r);
            try {
                Point[] circles = findCircles(p1, p2, r);
                Point c1 = circles[0];
                Point c2 = circles[1];
                if (Objects.equals(c1, c2)) {
                    System.out.printf("there is just one circle with center at %s\n", c1);
                } else {
                    System.out.printf("there are two circles with centers at %s and %s\n", c1, c2);
                }
            } catch (IllegalArgumentException ex) {
                System.out.println(ex.getMessage());
            }
            System.out.println();
        }
    }
}


Cistercian numerals

Cistercian numerals were used across Europe by Cistercian monks during the Late Medieval Period as an alternative to Roman numerals. They were used to represent base 10 integers from '''0''' to '''9999'''.

;How they work
All Cistercian numerals begin with a vertical line segment, which by itself represents the number '''0'''. Then, glyphs representing the digits '''1''' through '''9''' are optionally added to the four quadrants surrounding the vertical line segment. These glyphs are drawn with vertical and horizontal symmetry about the initial line segment. Each quadrant corresponds to a digit place in the number:

:* The '''upper-right''' quadrant represents the '''ones''' place.
:* The '''upper-left''' quadrant represents the '''tens''' place.
:* The '''lower-right''' quadrant represents the '''hundreds''' place.
:* The '''lower-left''' quadrant represents the '''thousands''' place.

Please consult the following image for examples of Cistercian numerals showing each glyph: [https://upload.wikimedia.org/wikipedia/commons/6/67/Cistercian_digits_%28vertical%29.svg]

;Task

:* Write a function/procedure/routine to display any given Cistercian numeral. This could be done by drawing to the display, creating an image, or even as text (as long as it is a reasonable facsimile).

:* Use the routine to show the following Cistercian numerals:

::* 0
::* 1
::* 20
::* 300
::* 4000
::* 5555
::* 6789
::* And a number of your choice!

;Notes
Due to the inability to upload images to Rosetta Code as of this task's creation, showing output here on this page is not required. However, it is welcomed -- especially for text output.

;See also

:* '''Numberphile - The Forgotten Number System'''
:* '''dcode.fr - Online Cistercian numeral converter'''

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

public class Cistercian {
    private static final int SIZE = 15;
    private final char[][] canvas = new char[SIZE][SIZE];

    public Cistercian(int n) {
        initN();
        draw(n);
    }

    public void initN() {
        for (var row : canvas) {
            Arrays.fill(row, ' ');
            row[5] = 'x';
        }
    }

    private void horizontal(int c1, int c2, int r) {
        for (int c = c1; c <= c2; c++) {
            canvas[r][c] = 'x';
        }
    }

    private void vertical(int r1, int r2, int c) {
        for (int r = r1; r <= r2; r++) {
            canvas[r][c] = 'x';
        }
    }

    private void diagd(int c1, int c2, int r) {
        for (int c = c1; c <= c2; c++) {
            canvas[r + c - c1][c] = 'x';
        }
    }

    private void diagu(int c1, int c2, int r) {
        for (int c = c1; c <= c2; c++) {
            canvas[r - c + c1][c] = 'x';
        }
    }

    private void draw(int v) {
        var thousands = v / 1000;
        v %= 1000;

        var hundreds = v / 100;
        v %= 100;

        var tens = v / 10;
        var ones = v % 10;

        drawPart(1000 * thousands);
        drawPart(100 * hundreds);
        drawPart(10 * tens);
        drawPart(ones);
    }

    private void drawPart(int v) {
        switch (v) {
            case 1:
                horizontal(6, 10, 0);
                break;
            case 2:
                horizontal(6, 10, 4);
                break;
            case 3:
                diagd(6, 10, 0);
                break;
            case 4:
                diagu(6, 10, 4);
                break;
            case 5:
                drawPart(1);
                drawPart(4);
                break;
            case 6:
                vertical(0, 4, 10);
                break;
            case 7:
                drawPart(1);
                drawPart(6);
                break;
            case 8:
                drawPart(2);
                drawPart(6);
                break;
            case 9:
                drawPart(1);
                drawPart(8);
                break;

            case 10:
                horizontal(0, 4, 0);
                break;
            case 20:
                horizontal(0, 4, 4);
                break;
            case 30:
                diagu(0, 4, 4);
                break;
            case 40:
                diagd(0, 4, 0);
                break;
            case 50:
                drawPart(10);
                drawPart(40);
                break;
            case 60:
                vertical(0, 4, 0);
                break;
            case 70:
                drawPart(10);
                drawPart(60);
                break;
            case 80:
                drawPart(20);
                drawPart(60);
                break;
            case 90:
                drawPart(10);
                drawPart(80);
                break;

            case 100:
                horizontal(6, 10, 14);
                break;
            case 200:
                horizontal(6, 10, 10);
                break;
            case 300:
                diagu(6, 10, 14);
                break;
            case 400:
                diagd(6, 10, 10);
                break;
            case 500:
                drawPart(100);
                drawPart(400);
                break;
            case 600:
                vertical(10, 14, 10);
                break;
            case 700:
                drawPart(100);
                drawPart(600);
                break;
            case 800:
                drawPart(200);
                drawPart(600);
                break;
            case 900:
                drawPart(100);
                drawPart(800);
                break;

            case 1000:
                horizontal(0, 4, 14);
                break;
            case 2000:
                horizontal(0, 4, 10);
                break;
            case 3000:
                diagd(0, 4, 10);
                break;
            case 4000:
                diagu(0, 4, 14);
                break;
            case 5000:
                drawPart(1000);
                drawPart(4000);
                break;
            case 6000:
                vertical(10, 14, 0);
                break;
            case 7000:
                drawPart(1000);
                drawPart(6000);
                break;
            case 8000:
                drawPart(2000);
                drawPart(6000);
                break;
            case 9000:
                drawPart(1000);
                drawPart(8000);
                break;

        }
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        for (var row : canvas) {
            builder.append(row);
            builder.append('\n');
        }
        return builder.toString();
    }

    public static void main(String[] args) {
        for (int number : List.of(0, 1, 20, 300, 4000, 5555, 6789, 9999)) {
            System.out.printf("%d:\n", number);
            var c = new Cistercian(number);
            System.out.println(c);
        }
    }
}


Closures/Value capture

Create a list of ten functions, in the simplest manner possible   (anonymous functions are encouraged),   such that the function at index   '' i ''    (you may choose to start    '' i ''    from either    '''0'''    or    '''1'''),     when run, should return the square of the index,   that is,    '' i '' 2.

Display the result of running any but the last function, to demonstrate that the function indeed remembers its value.

;Goal:
Demonstrate how to create a series of independent closures based on the same template but maintain separate copies of the variable closed over.

In imperative languages, one would generally use a loop with a mutable counter variable.

For each function to maintain the correct number, it has to capture the ''value'' of the variable at the time it was created, rather than just a reference to the variable, which would have a different value by the time the function was run.

See also: [[Multiple distinct objects]]

Solution:
import java.util.List;
import java.util.function.IntSupplier;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.toList;

public interface ValueCapture {
  public static void main(String... arguments) {
    List<IntSupplier> closures = IntStream.rangeClosed(0, 10)
      .<IntSupplier>mapToObj(i -> () -> i * i)
      .collect(toList())
    ;

    IntSupplier closure = closures.get(3);
    System.out.println(closure.getAsInt()); // prints "9"
  }
}


Colorful numbers

A '''colorful number''' is a non-negative base 10 integer where the product of every sub group of consecutive digits is unique.

;E.G.

24753 is a colorful number. 2, 4, 7, 5, 3, (2x4)8, (4x7)28, (7x5)35, (5x3)15, (2x4x7)56, (4x7x5)140, (7x5x3)105, (2x4x7x5)280, (4x7x5x3)420, (2x4x7x5x3)840

Every product is unique.

2346 is '''not''' a colorful number. 2, 3, 4, '''6''', (2x3)'''6''', (3x4)12, (4x6)24, (2x3x4)48, (3x4x6)72, (2x3x4x6)144

The product '''6''' is repeated.

Single digit numbers '''are''' considered to be colorful. A colorful number larger than 9 cannot contain a repeated digit, the digit 0 or the digit 1. As a consequence, there is a firm upper limit for colorful numbers; no colorful number can have more than 8 digits.

;Task

* Write a routine (subroutine, function, procedure, whatever it may be called in your language) to test if a number is a colorful number or not.
* Use that routine to find all of the colorful numbers less than 100.
* Use that routine to find the largest possible colorful number.

;Stretch

* Find and display the count of colorful numbers in each order of magnitude.
* Find and show the total count of '''all''' colorful numbers.

''Colorful numbers have no real number theory application. They are more a recreational math puzzle than a useful tool.''

Solution:
public class ColorfulNumbers {
    private int count[] = new int[8];
    private boolean used[] = new boolean[10];
    private int largest = 0;

    public static void main(String[] args) {
        System.out.printf("Colorful numbers less than 100:\n");
        for (int n = 0, count = 0; n < 100; ++n) {
            if (isColorful(n))
                System.out.printf("%2d%c", n, ++count % 10 == 0 ? '\n' : ' ');
        }

        ColorfulNumbers c = new ColorfulNumbers();

        System.out.printf("\n\nLargest colorful number: %,d\n", c.largest);

        System.out.printf("\nCount of colorful numbers by number of digits:\n");
        int total = 0;
        for (int d = 0; d < 8; ++d) {
            System.out.printf("%d   %,d\n", d + 1, c.count[d]);
            total += c.count[d];
        }
        System.out.printf("\nTotal: %,d\n", total);
    }

    private ColorfulNumbers() {
        countColorful(0, 0, 0);
    }

    public static boolean isColorful(int n) {
        // A colorful number cannot be greater than 98765432.
        if (n < 0 || n > 98765432)
            return false;
        int digit_count[] = new int[10];
        int digits[] = new int[8];
        int num_digits = 0;
        for (int m = n; m > 0; m /= 10) {
            int d = m % 10;
            if (n > 9 && (d == 0 || d == 1))
                return false;
            if (++digit_count[d] > 1)
                return false;
            digits[num_digits++] = d;
        }
        // Maximum number of products is (8 x 9) / 2.
        int products[] = new int[36];
        for (int i = 0, product_count = 0; i < num_digits; ++i) {
            for (int j = i, p = 1; j < num_digits; ++j) {
                p *= digits[j];
                for (int k = 0; k < product_count; ++k) {
                    if (products[k] == p)
                        return false;
                }
                products[product_count++] = p;
            }
        }
        return true;
    }

    private void countColorful(int taken, int n, int digits) {
        if (taken == 0) {
            for (int d = 0; d < 10; ++d) {
                used[d] = true;
                countColorful(d < 2 ? 9 : 1, d, 1);
                used[d] = false;
            }
        } else {
            if (isColorful(n)) {
                ++count[digits - 1];
                if (n > largest)
                    largest = n;
            }
            if (taken < 9) {
                for (int d = 2; d < 10; ++d) {
                    if (!used[d]) {
                        used[d] = true;
                        countColorful(taken + 1, n * 10 + d, digits + 1);
                        used[d] = false;
                    }
                }
            }
        }
    }
}


Colour bars/Display

Display a series of vertical color bars across the width of the display.

The color bars should either use:
:::*   the system palette,   or
:::*   the sequence of colors:
::::::*   black
::::::*   red
::::::*   green
::::::*   blue
::::::*   magenta
::::::*   cyan
::::::*   yellow
::::::*   white

Solution:
import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;

public class ColorFrame extends JFrame {
	public ColorFrame(int width, int height) {
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setSize(width, height);
		this.setVisible(true);
	}

	@Override
	public void paint(Graphics g) {
		Color[] colors = { Color.black, Color.red, Color.green, Color.blue,
				Color.pink, Color.CYAN, Color.yellow, Color.white };

		for (int i = 0; i < colors.length; i++) {
			g.setColor(colors[i]);
			g.fillRect(this.getWidth() / colors.length * i, 0, this.getWidth()
					/ colors.length, this.getHeight());
		}
	}

	public static void main(String args[]) {
		new ColorFrame(200, 200);
	}
}


Comma quibbling

Comma quibbling is a task originally set by Eric Lippert in his blog.

;Task:

Write a function to generate a string output which is the concatenation of input words from a list/sequence where:
# An input of no words produces the output string of just the two brace characters "{}".
# An input of just one word, e.g. ["ABC"], produces the output string of the word inside the two braces, e.g. "{ABC}".
# An input of two words, e.g. ["ABC", "DEF"], produces the output string of the two words inside the two braces with the words separated by the string " and ", e.g. "{ABC and DEF}".
# An input of three or more words, e.g. ["ABC", "DEF", "G", "H"], produces the output string of all but the last word separated by ", " with the last word separated by " and " and all within braces; e.g. "{ABC, DEF, G and H}".

Test your function with the following series of inputs showing your output here on this page:
* []                       # (No input words).
* ["ABC"]
* ["ABC", "DEF"]
* ["ABC", "DEF", "G", "H"]

Note: Assume words are non-empty strings of uppercase characters for this task.

Solution:
public class Quibbler {

	public static String quibble(String[] words) {
		String qText = "{";
		for(int wIndex = 0; wIndex < words.length; wIndex++) {
			qText += words[wIndex] + (wIndex == words.length-1 ? "" :
						  wIndex == words.length-2 ? " and " :
						  ", ";
		}
		qText += "}";
		return qText;
	}

	public static void main(String[] args) {
		System.out.println(quibble(new String[]{}));
		System.out.println(quibble(new String[]{"ABC"}));
		System.out.println(quibble(new String[]{"ABC", "DEF"}));
		System.out.println(quibble(new String[]{"ABC", "DEF", "G"}));
		System.out.println(quibble(new String[]{"ABC", "DEF", "G", "H"}));
	}
}


Command-line arguments

{{selection|Short Circuit|Console Program Basics}} Retrieve the list of command-line arguments given to the program. For programs that only print the arguments when run directly, see [[Scripted main]].
See also [[Program name]].

For parsing command line arguments intelligently, see [[Parsing command-line arguments]].

Example command line:

 myprogram -c "alpha beta" -h "gamma"

Solution:
public class Arguments {
  public static void main(String[] args) {
     System.out.println("There are " + args.length + " arguments given.");
     for(int i = 0; i < args.length; i++)
        System.out.println("The argument #" + (i+1) + " is " + args[i] + " and is at index " + i);
  }
}


Compare a list of strings

Given a   list   of arbitrarily many strings, show how to:

*   test if they are all lexically '''equal'''
*   test if every string is lexically '''less than''' the one after it  ''(i.e. whether the list is in strict ascending order)''

Each of those two tests should result in a single true or false value, which could be used as the condition of an    if    statement or similar.

If the input list has less than two elements, the tests should always return true.

There is ''no'' need to provide a complete program and output.

Assume that the strings are already stored in an array/list/sequence/tuple variable (whatever is most idiomatic) with the name   strings,   and just show the expressions for performing those two tests on it (plus of course any includes and custom functions etc. that it needs),   with as little distractions as possible.

Try to write your solution in a way that does not modify the original list,   but if it does then please add a note to make that clear to readers.

If you need further guidance/clarification,   see [[#Perl]] and [[#Python]] for solutions that use implicit short-circuiting loops,   and [[#Raku]] for a solution that gets away with simply using a built-in language feature.

Solution:
boolean isAscending(String[] strings) {
    String previous = strings[0];
    int index = 0;
    for (String string : strings) {
        if (index++ == 0)
            continue;
        if (string.compareTo(previous) < 0)
            return false;
        previous = string;
    }
    return true;
}


Compare a list of strings

Solution:
import java.util.Arrays;

public class CompareListOfStrings {

    public static void main(String[] args) {
        String[][] arr = {{"AA", "AA", "AA", "AA"}, {"AA", "ACB", "BB", "CC"}};
        for (String[] a : arr) {
            System.out.println(Arrays.toString(a));
            System.out.println(Arrays.stream(a).distinct().count() < 2);
            System.out.println(Arrays.equals(Arrays.stream(a).distinct().sorted().toArray(), a));
        }
    }
}


Compiler/AST interpreter

The C and Python versions can be considered reference implementations.

;Related Tasks

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

__TOC__

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

class Interpreter {
	static Map<String, Integer> globals = new HashMap<>();
	static Scanner s;
	static List<Node> list = new ArrayList<>();
	static Map<String, NodeType> str_to_nodes = new HashMap<>();

	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 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 String str(String s) {
		String result = "";
		int i = 0;
		s = s.replace("\"", "");
		while (i < s.length()) {
			if (s.charAt(i) == '\\' && i + 1 < s.length()) {
				if (s.charAt(i + 1) == 'n') {
					result += '\n';
					i += 2;
				} else if (s.charAt(i) == '\\') {
					result += '\\';
					i += 2;
				}
			} else {
				result += s.charAt(i);
				i++;
			}
		}
		return result;
	}
	static boolean itob(int i) {
		return i != 0;
	}
	static int btoi(boolean b) {
		return b ? 1 : 0;
	}
	static int fetch_var(String name) {
		int result;
		if (globals.containsKey(name)) {
			result = globals.get(name);
		} else {
			globals.put(name, 0);
			result = 0;
		}
		return result;
	}
	static Integer interpret(Node n) throws Exception {
		if (n == null) {
			return 0;
		}
		switch (n.nt) {
			case nd_Integer:
				return Integer.parseInt(n.value);
			case nd_Ident:
				return fetch_var(n.value);
			case nd_String:
				return 1;//n.value;
			case nd_Assign:
				globals.put(n.left.value, interpret(n.right));
				return 0;
			case nd_Add:
				return interpret(n.left) + interpret(n.right);
			case nd_Sub:
				return interpret(n.left) - interpret(n.right);
			case nd_Mul:
				return interpret(n.left) * interpret(n.right);
			case nd_Div:
				return interpret(n.left) / interpret(n.right);
			case nd_Mod:
				return interpret(n.left) % interpret(n.right);
			case nd_Lss:
				return btoi(interpret(n.left) < interpret(n.right));
			case nd_Leq:
				return btoi(interpret(n.left) <= interpret(n.right));
			case nd_Gtr:
				return btoi(interpret(n.left) > interpret(n.right));
			case nd_Geq:
				return btoi(interpret(n.left) >= interpret(n.right));
			case nd_Eql:
				return btoi(interpret(n.left) == interpret(n.right));
			case nd_Neq:
				return btoi(interpret(n.left) != interpret(n.right));
			case nd_And:
				return btoi(itob(interpret(n.left)) && itob(interpret(n.right)));
			case nd_Or:
				return btoi(itob(interpret(n.left)) || itob(interpret(n.right)));
			case nd_Not:
				if (interpret(n.left) == 0) {
					return 1;
				} else {
					return 0;
				}
			case nd_Negate:
				return -interpret(n.left);
			case nd_If:
				if (interpret(n.left) != 0) {
					interpret(n.right.left);
				} else {
					interpret(n.right.right);
				}
				return 0;
			case nd_While:
				while (interpret(n.left) != 0) {
					interpret(n.right);
				}
				return 0;
			case nd_Prtc:
				System.out.printf("%c", interpret(n.left));
				return 0;
			case nd_Prti:
				System.out.printf("%d", interpret(n.left));
				return 0;
			case nd_Prts:
				System.out.print(str(n.left.value));//interpret(n.left));
				return 0;
			case nd_Sequence:
				interpret(n.left);
				interpret(n.right);
				return 0;
			default:
				throw new Exception("Error: '" + n.nt + "' found, expecting operator");
		}
	}
	static Node load_ast() throws Exception {
		String command, value;
		String line;
		Node left, right;

		while (s.hasNext()) {
			line = s.nextLine();
			value = null;
			if (line.length() > 16) {
				command = line.substring(0, 15).trim();
				value = line.substring(15).trim();
			} else {
				command = line.trim();
			}
			if (command.equals(";")) {
				return null;
			}
			if (!str_to_nodes.containsKey(command)) {
				throw new Exception("Command not found: '" + command + "'");
			}
			if (value != null) {
				return Node.make_leaf(str_to_nodes.get(command), value);
			}
			left = load_ast(); right = load_ast();
			return Node.make_node(str_to_nodes.get(command), left, right);
		}
		return null; // for the compiler, not needed
	}
	public static void main(String[] args) {
		Node n;

		str_to_nodes.put(";", NodeType.nd_None);
		str_to_nodes.put("Sequence", NodeType.nd_Sequence);
		str_to_nodes.put("Identifier", NodeType.nd_Ident);
		str_to_nodes.put("String", NodeType.nd_String);
		str_to_nodes.put("Integer", NodeType.nd_Integer);
		str_to_nodes.put("If", NodeType.nd_If);
		str_to_nodes.put("While", NodeType.nd_While);
		str_to_nodes.put("Prtc", NodeType.nd_Prtc);
		str_to_nodes.put("Prts", NodeType.nd_Prts);
		str_to_nodes.put("Prti", NodeType.nd_Prti);
		str_to_nodes.put("Assign", NodeType.nd_Assign);
		str_to_nodes.put("Negate", NodeType.nd_Negate);
		str_to_nodes.put("Not", NodeType.nd_Not);
		str_to_nodes.put("Multiply", NodeType.nd_Mul);
		str_to_nodes.put("Divide", NodeType.nd_Div);
		str_to_nodes.put("Mod", NodeType.nd_Mod);
		str_to_nodes.put("Add", NodeType.nd_Add);
		str_to_nodes.put("Subtract", NodeType.nd_Sub);
		str_to_nodes.put("Less", NodeType.nd_Lss);
		str_to_nodes.put("LessEqual", NodeType.nd_Leq);
		str_to_nodes.put("Greater", NodeType.nd_Gtr);
		str_to_nodes.put("GreaterEqual", NodeType.nd_Geq);
		str_to_nodes.put("Equal", NodeType.nd_Eql);
		str_to_nodes.put("NotEqual", NodeType.nd_Neq);
		str_to_nodes.put("And", NodeType.nd_And);
		str_to_nodes.put("Or", NodeType.nd_Or);

		if (args.length > 0) {
			try {
				s = new Scanner(new File(args[0]));
				n = load_ast();
				interpret(n);
			} catch (Exception e) {
				System.out.println("Ex: "+e.getMessage());
			}
		}
	}
}


Compiler/code generator

The C and Python versions can be considered reference implementations.

;Related Tasks

* Lexical Analyzer task
* Syntax Analyzer task
* Virtual Machine Interpreter task
* AST Interpreter task

__TOC__

Solution:
package codegenerator;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class CodeGenerator {
    final static int WORDSIZE = 4;

    static byte[] code = {};

    static Map<String, NodeType> str_to_nodes = new HashMap<>();
    static List<String> string_pool = new ArrayList<>();
    static List<String> variables = new ArrayList<>();
    static int string_count = 0;
    static int var_count = 0;

    static Scanner s;
    static NodeType[] unary_ops = {
        NodeType.nd_Negate, NodeType.nd_Not
    };
    static NodeType[] operators = {
        NodeType.nd_Mul, NodeType.nd_Div, NodeType.nd_Mod, NodeType.nd_Add, NodeType.nd_Sub,
        NodeType.nd_Lss, NodeType.nd_Leq, NodeType.nd_Gtr, NodeType.nd_Geq,
        NodeType.nd_Eql, NodeType.nd_Neq, NodeType.nd_And, NodeType.nd_Or
    };

    static enum Mnemonic {
        NONE, FETCH, STORE, PUSH, ADD, SUB, MUL, DIV, MOD, LT, GT, LE, GE, EQ, NE, AND, OR, NEG, NOT,
        JMP, JZ, PRTC, PRTS, PRTI, HALT
    }
    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 enum NodeType {
        nd_None("", Mnemonic.NONE), nd_Ident("Identifier", Mnemonic.NONE), nd_String("String", Mnemonic.NONE), nd_Integer("Integer", Mnemonic.NONE), nd_Sequence("Sequence", Mnemonic.NONE),
        nd_If("If", Mnemonic.NONE),
        nd_Prtc("Prtc", Mnemonic.NONE), nd_Prts("Prts", Mnemonic.NONE), nd_Prti("Prti", Mnemonic.NONE), nd_While("While", Mnemonic.NONE),
        nd_Assign("Assign", Mnemonic.NONE),
        nd_Negate("Negate", Mnemonic.NEG), nd_Not("Not", Mnemonic.NOT), nd_Mul("Multiply", Mnemonic.MUL), nd_Div("Divide", Mnemonic.DIV), nd_Mod("Mod", Mnemonic.MOD), nd_Add("Add", Mnemonic.ADD),
        nd_Sub("Subtract", Mnemonic.SUB), nd_Lss("Less", Mnemonic.LT), nd_Leq("LessEqual", Mnemonic.LE),
        nd_Gtr("Greater", Mnemonic.GT), nd_Geq("GreaterEqual", Mnemonic.GE), nd_Eql("Equal", Mnemonic.EQ),
        nd_Neq("NotEqual", Mnemonic.NE), nd_And("And", Mnemonic.AND), nd_Or("Or", Mnemonic.OR);

        private final String name;
        private final Mnemonic m;

        NodeType(String name, Mnemonic m) {
            this.name = name;
            this.m = m;
        }
        Mnemonic getMnemonic() { return this.m; }

        @Override
        public String toString() { return this.name; }
    }
    static void appendToCode(int b) {
        code = Arrays.copyOf(code, code.length + 1);
        code[code.length - 1] = (byte) b;
    }
    static void emit_byte(Mnemonic m) {
        appendToCode(m.ordinal());
    }
    static void emit_word(int n) {
        appendToCode(n >> 24);
        appendToCode(n >> 16);
        appendToCode(n >> 8);
        appendToCode(n);
    }
    static void emit_word_at(int pos, int n) {
        code[pos] = (byte) (n >> 24);
        code[pos + 1] = (byte) (n >> 16);
        code[pos + 2] = (byte) (n >> 8);
        code[pos + 3] = (byte) n;
    }
    static int get_word(int pos) {
        int result;
        result = ((code[pos] & 0xff) << 24) + ((code[pos + 1] & 0xff)  << 16) + ((code[pos + 2] & 0xff)  << 8) + (code[pos + 3] & 0xff) ;

        return result;
    }
    static int fetch_var_offset(String name) {
        int n;
        n = variables.indexOf(name);
        if (n == -1) {
            variables.add(name);
            n = var_count++;
        }
        return n;
    }
    static int fetch_string_offset(String str) {
        int n;
        n = string_pool.indexOf(str);
        if (n == -1) {
            string_pool.add(str);
            n = string_count++;
        }
        return n;
    }
    static int hole() {
        int t = code.length;
        emit_word(0);
        return t;
    }
    static boolean arrayContains(NodeType[] a, NodeType n) {
        boolean result = false;
        for (NodeType test: a) {
            if (test.equals(n)) {
                result = true;
                break;
            }
        }
        return result;
    }
    static void code_gen(Node x) throws Exception {
        int n, p1, p2;
        if (x == null) return;

        switch (x.nt) {
            case nd_None: return;
            case nd_Ident:
                emit_byte(Mnemonic.FETCH);
                n = fetch_var_offset(x.value);
                emit_word(n);
                break;
            case nd_Integer:
                emit_byte(Mnemonic.PUSH);
                emit_word(Integer.parseInt(x.value));
                break;
            case nd_String:
                emit_byte(Mnemonic.PUSH);
                n = fetch_string_offset(x.value);
                emit_word(n);
                break;
            case nd_Assign:
                n = fetch_var_offset(x.left.value);
                code_gen(x.right);
                emit_byte(Mnemonic.STORE);
                emit_word(n);
                break;
            case nd_If:
                p2 = 0; // to avoid NetBeans complaining about 'not initialized'
                code_gen(x.left);
                emit_byte(Mnemonic.JZ);
                p1 = hole();
                code_gen(x.right.left);
                if (x.right.right != null) {
                    emit_byte(Mnemonic.JMP);
                    p2 = hole();
                }
                emit_word_at(p1, code.length - p1);
                if (x.right.right != null) {
                    code_gen(x.right.right);
                    emit_word_at(p2, code.length - p2);
                }
                break;
            case nd_While:
                p1 = code.length;
                code_gen(x.left);
                emit_byte(Mnemonic.JZ);
                p2 = hole();
                code_gen(x.right);
                emit_byte(Mnemonic.JMP);
                emit_word(p1 - code.length);
                emit_word_at(p2, code.length - p2);
                break;
            case nd_Sequence:
                code_gen(x.left);
                code_gen(x.right);
                break;
            case nd_Prtc:
                code_gen(x.left);
                emit_byte(Mnemonic.PRTC);
                break;
            case nd_Prti:
                code_gen(x.left);
                emit_byte(Mnemonic.PRTI);
                break;
            case nd_Prts:
                code_gen(x.left);
                emit_byte(Mnemonic.PRTS);
                break;
            default:
                if (arrayContains(operators, x.nt)) {
                    code_gen(x.left);
                    code_gen(x.right);
                    emit_byte(x.nt.getMnemonic());
                } else if (arrayContains(unary_ops, x.nt)) {
                    code_gen(x.left);
                    emit_byte(x.nt.getMnemonic());
                } else {
                    throw new Exception("Error in code generator! Found " + x.nt + ", expecting operator.");
                }
        }
    }
    static void list_code() throws Exception {
        int pc = 0, x;
        Mnemonic op;
        System.out.println("Datasize: " + var_count + " Strings: " + string_count);
        for (String s: string_pool) {
            System.out.println(s);
        }
        while (pc < code.length) {
            System.out.printf("%4d ", pc);
            op = Mnemonic.values()[code[pc++]];
            switch (op) {
                case FETCH:
                    x = get_word(pc);
                    System.out.printf("fetch [%d]", x);
                    pc += WORDSIZE;
                    break;
                case STORE:
                    x = get_word(pc);
                    System.out.printf("store [%d]", x);
                    pc += WORDSIZE;
                    break;
                case PUSH:
                    x = get_word(pc);
                    System.out.printf("push  %d", x);
                    pc += WORDSIZE;
                    break;
                case ADD: case SUB: case MUL: case DIV: case MOD:
                case LT: case GT: case LE: case GE: case EQ: case NE:
                case AND: case OR: case NEG: case NOT:
                case PRTC: case PRTI: case PRTS: case HALT:
                    System.out.print(op.toString().toLowerCase());
                    break;
                case JMP:
                    x = get_word(pc);
                    System.out.printf("jmp     (%d) %d", x, pc + x);
                    pc += WORDSIZE;
                    break;
                case JZ:
                    x = get_word(pc);
                    System.out.printf("jz      (%d) %d", x, pc + x);
                    pc += WORDSIZE;
                    break;
                default:
                    throw new Exception("Unknown opcode " + code[pc] + "@" + (pc - 1));
            }
            System.out.println();
        }
    }
    static Node load_ast() throws Exception {
        String command, value;
        String line;
        Node left, right;

        while (s.hasNext()) {
            line = s.nextLine();
            value = null;
            if (line.length() > 16) {
                command = line.substring(0, 15).trim();
                value = line.substring(15).trim();
            } else {
                command = line.trim();
            }
            if (command.equals(";")) {
                return null;
            }
            if (!str_to_nodes.containsKey(command)) {
                throw new Exception("Command not found: '" + command + "'");
            }
            if (value != null) {
                return Node.make_leaf(str_to_nodes.get(command), value);
            }
            left = load_ast(); right = load_ast();
            return Node.make_node(str_to_nodes.get(command), left, right);
        }
        return null; // for the compiler, not needed
    }
    public static void main(String[] args) {
        Node n;

        str_to_nodes.put(";", NodeType.nd_None);
        str_to_nodes.put("Sequence", NodeType.nd_Sequence);
        str_to_nodes.put("Identifier", NodeType.nd_Ident);
        str_to_nodes.put("String", NodeType.nd_String);
        str_to_nodes.put("Integer", NodeType.nd_Integer);
        str_to_nodes.put("If", NodeType.nd_If);
        str_to_nodes.put("While", NodeType.nd_While);
        str_to_nodes.put("Prtc", NodeType.nd_Prtc);
        str_to_nodes.put("Prts", NodeType.nd_Prts);
        str_to_nodes.put("Prti", NodeType.nd_Prti);
        str_to_nodes.put("Assign", NodeType.nd_Assign);
        str_to_nodes.put("Negate", NodeType.nd_Negate);
        str_to_nodes.put("Not", NodeType.nd_Not);
        str_to_nodes.put("Multiply", NodeType.nd_Mul);
        str_to_nodes.put("Divide", NodeType.nd_Div);
        str_to_nodes.put("Mod", NodeType.nd_Mod);
        str_to_nodes.put("Add", NodeType.nd_Add);
        str_to_nodes.put("Subtract", NodeType.nd_Sub);
        str_to_nodes.put("Less", NodeType.nd_Lss);
        str_to_nodes.put("LessEqual", NodeType.nd_Leq);
        str_to_nodes.put("Greater", NodeType.nd_Gtr);
        str_to_nodes.put("GreaterEqual", NodeType.nd_Geq);
        str_to_nodes.put("Equal", NodeType.nd_Eql);
        str_to_nodes.put("NotEqual", NodeType.nd_Neq);
        str_to_nodes.put("And", NodeType.nd_And);
        str_to_nodes.put("Or", NodeType.nd_Or);

        if (args.length > 0) {
            try {
                s = new Scanner(new File(args[0]));
                n = load_ast();
                code_gen(n);
                emit_byte(Mnemonic.HALT);
                list_code();
            } catch (Exception e) {
                System.out.println("Ex: "+e);//.getMessage());
            }
        }
    }
}


Compiler/lexical analyzer

The C and Python versions can be considered reference implementations.

;Related Tasks
* Syntax Analyzer task
* Code Generator task
* Virtual Machine Interpreter task
* AST Interpreter task

Solution:
// Translated from python source

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Lexer {
    private int line;
    private int pos;
    private int position;
    private char chr;
    private String s;

    Map<String, TokenType> keywords = new HashMap<>();

    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() {
            String result = String.format("%5d  %5d %-15s", this.line, this.pos, this.tokentype);
            switch (this.tokentype) {
                case Integer:
                    result += String.format("  %4s", value);
                    break;
                case Identifier:
                    result += String.format(" %s", value);
                    break;
                case String:
                    result += String.format(" \"%s\"", value);
                    break;
            }
            return result;
        }
    }

    static enum TokenType {
        End_of_input, Op_multiply,  Op_divide, Op_mod, Op_add, Op_subtract,
        Op_negate, Op_not, Op_less, Op_lessequal, Op_greater, Op_greaterequal,
        Op_equal, Op_notequal, Op_assign, Op_and, Op_or, Keyword_if,
        Keyword_else, Keyword_while, Keyword_print, Keyword_putc, LeftParen, RightParen,
        LeftBrace, RightBrace, Semicolon, Comma, Identifier, Integer, String
    }

    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);
    }

    Lexer(String source) {
        this.line = 1;
        this.pos = 0;
        this.position = 0;
        this.s = source;
        this.chr = this.s.charAt(0);
        this.keywords.put("if", TokenType.Keyword_if);
        this.keywords.put("else", TokenType.Keyword_else);
        this.keywords.put("print", TokenType.Keyword_print);
        this.keywords.put("putc", TokenType.Keyword_putc);
        this.keywords.put("while", TokenType.Keyword_while);

    }
    Token follow(char expect, TokenType ifyes, TokenType ifno, int line, int pos) {
        if (getNextChar() == expect) {
            getNextChar();
            return new Token(ifyes, "", line, pos);
        }
        if (ifno == TokenType.End_of_input) {
            error(line, pos, String.format("follow: unrecognized character: (%d) '%c'", (int)this.chr, this.chr));
        }
        return new Token(ifno, "", line, pos);
    }
    Token char_lit(int line, int pos) {
        char c = getNextChar(); // skip opening quote
        int n = (int)c;
        if (c == '\'') {
            error(line, pos, "empty character constant");
        } else if (c == '\\') {
            c = getNextChar();
            if (c == 'n') {
                n = 10;
            } else if (c == '\\') {
                n = '\\';
            } else {
                error(line, pos, String.format("unknown escape sequence \\%c", c));
            }
        }
        if (getNextChar() != '\'') {
            error(line, pos, "multi-character constant");
        }
        getNextChar();
        return new Token(TokenType.Integer, "" + n, line, pos);
    }
    Token string_lit(char start, int line, int pos) {
        String result = "";
        while (getNextChar() != start) {
            if (this.chr == '\u0000') {
                error(line, pos, "EOF while scanning string literal");
            }
            if (this.chr == '\n') {
                error(line, pos, "EOL while scanning string literal");
            }
            result += this.chr;
        }
        getNextChar();
        return new Token(TokenType.String, result, line, pos);
    }
    Token div_or_comment(int line, int pos) {
        if (getNextChar() != '*') {
            return new Token(TokenType.Op_divide, "", line, pos);
        }
        getNextChar();
        while (true) {
            if (this.chr == '\u0000') {
                error(line, pos, "EOF in comment");
            } else if (this.chr == '*') {
                if (getNextChar() == '/') {
                    getNextChar();
                    return getToken();
                }
            } else {
                getNextChar();
            }
        }
    }
    Token identifier_or_integer(int line, int pos) {
        boolean is_number = true;
        String text = "";

        while (Character.isAlphabetic(this.chr) || Character.isDigit(this.chr) || this.chr == '_') {
            text += this.chr;
            if (!Character.isDigit(this.chr)) {
                is_number = false;
            }
            getNextChar();
        }

        if (text.equals("")) {
            error(line, pos, String.format("identifer_or_integer unrecognized character: (%d) %c", (int)this.chr, this.chr));
        }

        if (Character.isDigit(text.charAt(0))) {
            if (!is_number) {
                error(line, pos, String.format("invalid number: %s", text));
            }
            return new Token(TokenType.Integer, text, line, pos);
        }

        if (this.keywords.containsKey(text)) {
            return new Token(this.keywords.get(text), "", line, pos);
        }
        return new Token(TokenType.Identifier, text, line, pos);
    }
    Token getToken() {
        int line, pos;
        while (Character.isWhitespace(this.chr)) {
            getNextChar();
        }
        line = this.line;
        pos = this.pos;

        switch (this.chr) {
            case '\u0000': return new Token(TokenType.End_of_input, "", this.line, this.pos);
            case '/': return div_or_comment(line, pos);
            case '\'': return char_lit(line, pos);
            case '<': return follow('=', TokenType.Op_lessequal, TokenType.Op_less, line, pos);
            case '>': return follow('=', TokenType.Op_greaterequal, TokenType.Op_greater, line, pos);
            case '=': return follow('=', TokenType.Op_equal, TokenType.Op_assign, line, pos);
            case '!': return follow('=', TokenType.Op_notequal, TokenType.Op_not, line, pos);
            case '&': return follow('&', TokenType.Op_and, TokenType.End_of_input, line, pos);
            case '|': return follow('|', TokenType.Op_or, TokenType.End_of_input, line, pos);
            case '"': return string_lit(this.chr, line, pos);
            case '{': getNextChar(); return new Token(TokenType.LeftBrace, "", line, pos);
            case '}': getNextChar(); return new Token(TokenType.RightBrace, "", line, pos);
            case '(': getNextChar(); return new Token(TokenType.LeftParen, "", line, pos);
            case ')': getNextChar(); return new Token(TokenType.RightParen, "", line, pos);
            case '+': getNextChar(); return new Token(TokenType.Op_add, "", line, pos);
            case '-': getNextChar(); return new Token(TokenType.Op_subtract, "", line, pos);
            case '*': getNextChar(); return new Token(TokenType.Op_multiply, "", line, pos);
            case '%': getNextChar(); return new Token(TokenType.Op_mod, "", line, pos);
            case ';': getNextChar(); return new Token(TokenType.Semicolon, "", line, pos);
            case ',': getNextChar(); return new Token(TokenType.Comma, "", line, pos);

            default: return identifier_or_integer(line, pos);
        }
    }

    char getNextChar() {
        this.pos++;
        this.position++;
        if (this.position >= this.s.length()) {
            this.chr = '\u0000';
            return this.chr;
        }
        this.chr = this.s.charAt(this.position);
        if (this.chr == '\n') {
            this.line++;
            this.pos = 0;
        }
        return this.chr;
    }

    void printTokens() {
        Token t;
        while ((t = getToken()).tokentype != TokenType.End_of_input) {
            System.out.println(t);
        }
        System.out.println(t);
    }
    public static void main(String[] args) {
        if (args.length > 0) {
            try {

                File f = new File(args[0]);
                Scanner s = new Scanner(f);
                String source = " ";
                while (s.hasNext()) {
                    source += s.nextLine() + "\n";
                }
                Lexer l = new Lexer(source);
                l.printTokens();
            } catch(FileNotFoundException e) {
                error(-1, -1, "Exception: " + e.getMessage());
            }
        } else {
            error(-1, -1, "No args");
        }
    }
}