/*
 * [TestRoman.java]
 *
 * Summary: convert Roman Numerals to long.
 *
 * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2007-08-17
 */
package com.mindprod.example;

import static java.lang.System.*;

/**
 * convert Roman Numerals to long.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2007-08-17
 * @since 2007-08-17
 */
public final class TestRoman
    {
    /**
     * extended roman numeral digits we allow
     */
    private static final String VALID_NUMERALS = "IVXLCDMvxlcdm?!";

    /**
     * values for unit test
     */
    private static final String[] TESTS = { "MMVII", "MCMXCIX", "xv", "CIXMCMX" };

    /**
     * corresponding value of roman numeral digit
     */
    private static final long[] CORRESPONDING_VALUES = {
            /* I */
            1,
            /* V */
            5,
            /* X */
            10,
            /* L */
            50,
            /* C */
            100,
            /* D */
            500,
            /* M */
            1000,
            /* v */
            5000,
            /* x */
            10000,
            /* l */
            50000,
            /* c */
            100000,
            /* d */
            500000L,
            /* m */
            1000000L,
            /* ? */
            5000000L,
            /* ? */
            10000000L };

    /**
     * Test harness for romanToLong
     *
     * @param args not used
     */
    public static void main( String[] args )
        {
        for ( String test : TESTS )
            {
            out.println( test + " : " + romanToLong( test ) );
            }
        // prints:
        // MMVII > 2007
        // MCMXCIX > 1999
        // xv > 15000
        // CIXMCMX > 2001
        }

    /**
     * converts a Roman Numeral String to a long. Based on Pascal algorithm posted at
     * http://www.merlyn.demon.co.uk/programs/cvt_rome.pas Also accepts fake Roman numbers to extend the range: vxlcdm?!
     * v=5000 ... !=10,000,000 This code also accepts numbers that are malformed, in that the numerals are out of order
     * e.g. "CIXMCMX"
     *
     * @param romanNumerals string of roman numerals to convert. No spaces or commas.
     *
     * @return long equivalent.
     */
    @SuppressWarnings( { "WeakerAccess" } )
    public static long romanToLong( final String romanNumerals )
        {
        long sum = 0;
        long oldV = 0;
        // process the string right to left
        for ( int k = romanNumerals.length() - 1; k >= 0; k-- )
            {
            final char c = romanNumerals.charAt( k );
            final int pos = VALID_NUMERALS.indexOf( c );
            if ( pos < 0 )
                {
                throw new IllegalArgumentException( "invalid Roman numeral "
                                                    + c
                                                    + " in "
                                                    + romanNumerals );
                }
            long newV = CORRESPONDING_VALUES[ pos ];
            if ( newV < oldV )
                {
                newV = -newV;
                }
            sum += newV;
            oldV = newV;
            }
        return sum;
        }
    }