# Merchant's Guide to the Galaxy

This is my version of Merchant's Guide to the Galaxy:

A merchant buys and sells items in the galaxy. Buying and selling over the galaxy requires you to convert numbers and units. The numbers used for intergalactic transactions follows similar convention to the roman numerals. Roman numerals are based on seven symbols:

• I 1
• V 5
• X 10
• L 50
• C 100
• D 500
• M 1000

Numbers are formed by combining symbols together and adding the values. For example, MMVI is 1000 + 1000 + 5 + 1 = 2006. Generally, symbols are placed in order of value, starting with the largest values. When smaller values precede larger values, the smaller values are subtracted from the larger values, and the result is added to the total. For example MCMXLIV = 1000 + (1000 − 100) + (50 − 10) + (5 − 1) = 1944.

The symbols "I", "X", "C", and "M" can be repeated three times in succession, but no more. (They may appear four times if the third and fourth are separated by a smaller value, such as XXXIX.) "D", "L", and "V" can never be repeated. "I" can be subtracted from "V" and "X" only. "X" can be subtracted from "L" and "C" only. "C" can be subtracted from "D" and "M" only. "V", "L", and "D" can never be subtracted. Only one small-value symbol may be subtracted from any large-value symbol. A number written in [16]Arabic numerals can be broken into digits. For example, 1903 is composed of 1, 9, 0, and 3. To write the Roman numeral, each of the non-zero digits should be treated separately. Inthe above example, 1,000 = M, 900 = CM, and 3 = III. Therefore, 1903 = MCMIII. Input to your program consists of lines of text detailing your notes on the conversion between intergalactic units and roman numerals. You are expected to handle invalid queries appropriately.

Test input:

• glob is I
• prok is V
• pish is X
• tegj is L
• glob glob Silver is 34 Credits
• glob prok Gold is 57800 Credits
• pish pish Iron is 3910 Credits
• how much is pish tegj glob glob?
• how many Credits is glob prok Silver?
• how many Credits is glob prok Gold?
• how many Credits is glob prok Iron?
• how much wood could a woodchuck chuck if a woodchuck could chuck wood?

Test output:

• pish tegj glob glob is 42
• glob prok Silver is 68 Credits
• glob prok Gold is 57800 Credits
• glob prok Iron is 782 Credits
• I have no idea what you are talking about

I would appreciate suggestions on how to better break up my code into different classes, more efficient ways to have done it or a better way to have done it without using many if statements, or more ways to have used Java 8.

public class ParseInput {

public static void main(String [] args){

String filePath = "/Users/s/interviews/tw/testinput.txt";

try (Stream<String> lines = Files.lines(Paths.get(filePath))){
lines
.forEach(line -> RomanNumerals.parse(line));
}
catch (IOException io){
io.printStackTrace();
}

}
}

public class RomanNumerals {

static Map<String, String> howMuchMoney = new HashMap<>();

public static int romanToInt(String s) {
int nums[] = new int[s.length()];
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case 'M':
nums[i] = 1000;
break;
case 'D':
nums[i] = 500;
break;
case 'C':
nums[i] = 100;
break;
case 'L':
nums[i] = 50;
break;
case 'X':
nums[i] = 10;
break;
case 'V':
nums[i] = 5;
break;
case 'I':
nums[i] = 1;
break;

}

}
int sum = 0;
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i] < nums[i + 1])
sum -= nums[i];

else {
sum += nums[i];
}

} return sum + nums[nums.length - 1];
}

public static void whichMetal(String s, String metal) {

double sum = 0;

String[] output = s.split(Pattern.quote(metal));

// Galatic words before the type of metal

String individualWords = output[0];
String[] outputWords = individualWords.split(" ");

String romanNumeral = "";

// Convert galactic words to Roman numerals

for (String ow : outputWords) {
romanNumeral += howMuchMoney.get(ow);
}

// Convert Roman numerals to regular numbers

double convertedInt = romanToInt(romanNumeral);

String creditWords = output[1];

// Splits the part of the String before Credit so that we get the number

String[] creditOutputWords = creditWords.split(" ");

int money = creditOutputWords.length - 2;

double creditMoney = Double.parseDouble(creditOutputWords[money]);

// Divides the number of credits by the value before the metal so we get the value for one unit of that metal
double valueToInsert = 0;
if (convertedInt !=0 ) {
valueToInsert = creditMoney / convertedInt;
}

else {
System.out.println("creditMoney " + creditMoney);
System.out.println("convertedInt " + convertedInt);
}
// inserts the value of metal and the numeric value into the hashmap

howMuchMoney.put(metal, Double.toString(valueToInsert));
}

static void translate(String s, String separator){

double sum = 0;

DecimalFormat df2  = new DecimalFormat("");

// Splits the string based on whether we are asking how much or how many Credits

String[] output = s.split(Pattern.quote(separator));

// Intergalatic words (plus metal), ie glob prok Silver or tegj glob glob

String individualWords = output[1];

String[] outputWords = individualWords.split(" ");

String romanNumeral ="";

double value =0;

for (String ow: outputWords){

if (!ow.equals("")) {

if (!ow.equals("Silver") && (!ow.equals("Gold") && (!ow.equals("Iron")))) {

// Gets Roman numeral for the Galatic words ( sentence doesn't have Credits)

romanNumeral += howMuchMoney.get(ow);

}
else {

// Gets Roman numeral before the metal

value= Double.parseDouble(howMuchMoney.get(ow));
//  System.out.println("with metals " + romanNumeral);

// Multiplies the number of units of the metal by the value of the metal

sum = value * romanToInt(romanNumeral);

// Remove the last space and ? and also show without decimals

System.out.println(output[1].trim().replaceAll(" \\?", "") +" is " + df2.format(sum).toString().replaceAll(",", "") + " Credits");
}
}

}

// Only prints out if it is not How many credits (since that has already been printed out)

if (!output[1].contains("Silver") && !output[1].contains("Gold") && !output[1].contains("Iron"))
System.out.println(output[1].trim().replaceAll(" \\?", "") + " is " + romanToInt(romanNumeral));

}

public static boolean validate(String s){
if (s.contains("DD") || s.contains("LL") || s.contains("VV") || s.contains("MMMM") || s.contains("CCCC") || s.contains("XXXX"))
return false;
else
return true;
}

public static void parse(String s){

boolean validString = validate(s);

if (validString == true) {

if (s.contains("how many Credits")) {
translate(s, "how many Credits is");
} else if (s.contains("Silver")) {

whichMetal(s, "Silver");

} else if (s.contains("Gold")) {
whichMetal(s, "Gold");
} else if (s.contains("Iron")) {
whichMetal(s, "Iron");
} else if (s.contains("how much is")) {
translate(s, "how much is ");
} else if (!s.equals("") && s.contains("is")) {
String delimiter = " is ";

String[] output = s.split(Pattern.quote(delimiter));

howMuchMoney.put(output[0], output[1]);
} else System.out.println("I have no idea what you are talking about");

}

else {
System.out.println("The string is invalid");
}
}
}


## 1 Answer

You can use HashMap for storing the integer values aligned with the corresponding letters instead of using switch case.

i.e.

HashMap<String, Integer> hmap = new HashMap<String, Integer>();
hmap.put("M", 1000);
hmap.put("D", 500);
hmap.put("C", 100);
hmap.put("L", 50);
hmap.put("X", 10);
hmap.put("V", 5);
hmap.put("I", 1);


And retrieve them in the following manner:

String var = hmap.get("M"); //where you get 1000 in var.


You can iterate through the HashMap using an Iterator like this:

Set set = hmap.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry mentry = (Map.Entry)iterator.next();
}