/*
 * Convert integer to string of roman numerals
 *
 * Copyright © 2001 Keith Packard
 * All Rights Reserved.  See the file COPYING in this directory
 * for licensing information.
 *
 * A classic, plus a good illustration of some
 * of the structuring, typing, and nesting
 * capabilities of the language.
 */

string roman (int i)
{
    if (i < 0)
	return "-" + roman (-i);

    typedef struct {
	string	ones, five, tens;
	int	base;
    } digit;

    digit[*]	digits = {
	(digit) { .ones = "C", .five = "D", .tens = "M", .base = 100 },
	(digit) { .ones = "X", .five = "L", .tens = "C", .base = 10 },
	(digit) { .ones = "I", .five = "V", .tens = "X", .base = 1 }
    };

    string place (int i, digit dig)
    {
	string lots (int i, string s)
	{
	    if (i != 0)
		return s + lots (i-1,s);
	    return "";
	}
	
	if (i < 4)
	    return lots (i, dig.ones);
	if (i == 4)
	    return dig.ones + dig.five;
	if (i < 9)
	    return dig.five + lots (i-5, dig.ones);
	if (i == 9)
	    return dig.ones + dig.tens;
	return lots (i // 10, dig.tens) + place (i % 10, dig);
    }

    int	d;

    for (d = 0; d < dim(digits); d++)
	if (i >= digits[d].base)
	    return (place (i // digits[d].base, digits[d]) + 
		    roman(i % digits[d].base));
    return "";
}

printf ("%s\n", roman (string_to_integer (argv[1])));
