/*-
 * Copyright (c) 2009, Diomidis Spinellis
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

import java.io.PrintWriter;
import java.io.OutputStreamWriter;

/**
 * A number whose string representation follows the Greek numbering system.
 * @see <a href="http://en.wikipedia.org/wiki/Greek_numerals">Wikipedia: Greek numerals</a>
 * @see <a href="http://books.google.com/books?id=_HZNr_mGFzQC&lpg=PR1&pg=PA18">Thomas Heath: A History of Greek Mathematics</a>
 * @see <a href="http://www.unicode.org/charts/PDF/Unicode-3.1/U31-0370.pdf">Unicode Greek and Coptic</a>
 * @author Diomidis Spinellis
 */
class GreekNumeral {
    /** The value to be represented in the Greek numbering system. */
    private int n;

    /** Construct a number given its integer value. */
    GreekNumeral(int a) {
	if (a <= 0)
	    throw new IllegalArgumentException("Greek numbers must be greater than zero");
	n = a;
    }

    /** Return the number's representation in the Greek numbering system. */
    public String toString() {
	int v = n;
	StringBuffer r = new StringBuffer();

	int myriadPower = 2;
	for (int divisor = MYRIAD * MYRIAD; divisor > 1; divisor /= MYRIAD, myriadPower--)
	    if (v > divisor - 1) {
		/*
		 * Follow the Diophantus representation of:
		 * a myriad sign, M (10000) as many times as the power,
		 * followed by the multiplier for the myriad
		 * followed by a dot,
		 * followed by the rest.
		 * This is enough for integer numbers.
		 */
		for (int i = 0; i < myriadPower; i++)
		    r.append(myriadSymbol);
		r.append(smallNumber(v / divisor));
		v %= divisor;
		if (v > 0)
		    r.append('.');
	    }

	r.append(smallNumber(v));

	if (v % 1000 > 0)
		r.append(greekNumeralSign);
	return r.toString();
    }

    /**
     * Return the 1-999999 number's representation in the Greek numbering system.
     * Adding a "left keraia" to represent numbers in the range 10000 ... 999999 is
     * not orthodox, so it's better to use the myriad notation and call this method
     * only for numbers up to 9999.
     */
    static private StringBuffer smallNumber(int n) {
	StringBuffer r = new StringBuffer();
	int i = 0;
	for (int v = n; v > 0; v /= 10, i++) {
	    int digit = v % 10;
	    if (digit == 0)
		continue;
	    r.insert(0, greekLowerLetter[(digit - 1) + 9 * (i % 3)]);
	    if (i > 2)
		r.insert(0, greekLowerNumeralSign);
	}
	return r;
    }

    private static int MYRIAD = 10000;
    private static char greekNumeralSign = '\u0374';
    private static char greekLowerNumeralSign = '\u0375';
    private static char myriadSymbol = '\u039c';

    static private char greekLowerLetter[] = {
	//   1       2       3       4       5       6       7       8       9
	0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03DB, 0x03B6, 0x03B7, 0x03B8,
	0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03DF,
	0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03E1
    };

    /** Prints an HTML table row with the number in decimal and Greek. */
    private static void printNumber(PrintWriter out, int n) {
	    out.println("<tr><td>" + n + "</td><td>" + new GreekNumeral(n) +
		    "</td></tr>");
    }

    /** Create an HTML document with representative output. */
    public static void main(String args[]) {
	PrintWriter out = null;
	try {
	    out = new PrintWriter(
		    new OutputStreamWriter(System.out, "UTF8"), true);
	} catch (java.io.UnsupportedEncodingException e) {
	    System.err.println(e);
	    System.exit(1);
	}

	out.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
	out.println("<!DOCTYPE html\n" +
		"PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" +
		"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
		"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"el\" lang=\"el\">\n" +
		"<html><body>\n" +
		"<table><tr><th>Decimal</th><th>Greek</th></tr>");
	for (int i = 1; i < 1099; i++)
	    printNumber(out, i);
	printNumber(out, 10000);
	printNumber(out, 10001);
	printNumber(out, 100000);
	printNumber(out, 100001);
	printNumber(out, 900001);
	printNumber(out, 999999);
	printNumber(out, 1000000);
	printNumber(out, 1200000);
	printNumber(out, 1201000);
	printNumber(out, 1200100);
	printNumber(out, 1201001);
	printNumber(out, 1507984);
	printNumber(out, 4095441);
	printNumber(out, 10098041);
	printNumber(out, 10301021);
	printNumber(out, 11413021);
	printNumber(out, 13111241);
	printNumber(out, 45820709);
	printNumber(out, 1629586560);
	printNumber(out, 0x7fffffff);
    }
}
