import std.bigint, std.conv, std.exception, std.math, std.range, std.stdio, std.traits;

BigInt cantorPair(BigInt x, BigInt y)
{
	enforce(x >= 0);
	enforce(y >= 0);
	return ((x + y)*(x + y + 1))/2 + y;
}

BigInt cantorTuple(R)(R r)
	if(isInputRange!R && hasLength!R)
{
	enforce(r.length > 0);
	if(r.length == 1)
	{
		enforce(r[$-1] >= 0);
		return BigInt(r[$-1]);
	}
	else
		return cantorPair(cantorTuple(r[0 .. $-1]), BigInt(r[$-1]));
}


void main()
{
	foreach(n; iota(1, 10))
	{
		long[] x;
		x.length = n;
		foreach(i, ref val; x)
			val = i;

		BigInt c = cantorTuple(x);
		writeln(n, "\t", c);
	}
	writeln();

	writeln(cantorTuple([ulong.max, ulong.max]));
	writeln(cantorPair(BigInt(ulong.max), BigInt(ulong.max)));
}

