Creating a chain of loops dynamically based on a List - java

I am practicing Java and I was trying to create a program to calculate the amount of ways an number could be divided using a set number of dividers.
For instance:
100 is the number and the dividers are 50,20,5. What are the possible divisions.
The answer would be:
Amount of 50 : 0, Amount of 20 : 0, Amount of 10 : 10
Amount of 50 : 0, Amount of 20 : 1, Amount of 10 : 8
Amount of 50 : 0, Amount of 20 : 2, Amount of 10 : 6
Amount of 50 : 0, Amount of 20 : 3, Amount of 10 : 4
Amount of 50 : 0, Amount of 20 : 4, Amount of 10 : 2
Amount of 50 : 1, Amount of 20 : 0, Amount of 10 : 5
Amount of 50 : 1, Amount of 20 : 1, Amount of 10 : 3
Amount of 50 : 1, Amount of 20 : 2, Amount of 10 : 1
Amount of 50 : 2
I wrote a code that asks the user an amount and 3 dividers. Now I am trying to figure out if there is a way to dynamically create a code for as many dividers as the user wants. The code is in a way very repetitive and there is a certain pattern to add another divider but I cannot figure out how to implement this dynamic change to the code.
The first code I came up with to do this is the following:
public class Test2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Insert the amount:");
int amount = scanner.nextInt();
List<Integer> dividers = new ArrayList<>();
System.out.println("Insert the first divider:");
int tempDivider = scanner.nextInt();
if (!dividers.contains(tempDivider)) {
dividers.add(tempDivider);
}
while (dividers.size()<3) {
System.out.println("Insert the next divider: (" + (3-dividers.size()) + " more to go)");
tempDivider = scanner.nextInt();
if (!dividers.contains(tempDivider)) {
dividers.add(tempDivider);
}
}
dividers.sort(Collections.reverseOrder());
System.out.print("Dividers are: ");
System.out.println(dividers);
int getal1 = dividers.get(0);
int getal2 = dividers.get(1);
int getal3 = dividers.get(2);
int fiftyAmount = amount / getal1;
int fiftyRemainder = amount % getal1;
for (int i = 0; i <= fiftyAmount; i++) {
int currentFiftyAmount = amount - (getal1 * i);
int twentyAmount = currentFiftyAmount / getal2;
int twentyRemainder = currentFiftyAmount % getal2;
if (twentyAmount == 0) {
StringBuilder output = new StringBuilder();
output.append("Amount of " + getal1 + " banknotes: " + i);
if (fiftyRemainder != 0) output.append(", Remainder: " + fiftyRemainder);
System.out.println(output);
} else {
for (int j = 0; j <= twentyAmount; j++) {
int currentTwentyAmount = currentFiftyAmount - (getal2 * j);
int tenAmount = currentTwentyAmount / getal3;
int tenRemainder = currentTwentyAmount % getal3;
if (tenAmount == 0) {
StringBuilder output = new StringBuilder();
output.append("Amount of " + getal1 + " banknotes: " + i + ", Amount of " + getal2 + " banknotes: " + j);
if (tenRemainder != 0) output.append(", Remainder: " + twentyRemainder);
} else {
StringBuilder output = new StringBuilder();
output.append("Amount of " + getal1 + " banknotes: " + i + ", Amount of " + getal2 + " banknotes: " + j +
", Amount of " + getal3 + " banknotes: " + tenAmount);
if (tenRemainder != 0) output.append(", Remainder: " + tenRemainder);
System.out.println(output);
}
}
}
}
}
}
I tried to make this more abstract to figure out a way to automate the creation of the extra dividing loops but I cannot figure it out.
The more abstract version I wrote is the following:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Insert the amount:");
int amount = scanner.nextInt();
List<Integer> dividers = new ArrayList<>();
System.out.println("Insert the first divider:");
dividers.add(scanner.nextInt());
int divider;
while (dividers.size()<2) {
System.out.println("Insert the next divider: (" + (2-dividers.size()) + " more to go)");
divider = scanner.nextInt();
if (!dividers.contains(divider)) {
dividers.add(divider);
}
}
dividers.sort(Collections.reverseOrder());
System.out.print("Dividers are: ");
System.out.println(dividers);
int divided1Amount = amount / dividers.get(0);
int divided1Remainder = amount % dividers.get(0);
for (int i = 0; i <= divided1Amount; i++) {
int currentDivided1Amount = amount - (dividers.get(0) * i);
int divided2Amount = currentDivided1Amount / dividers.get(1);
int divided2Remainder = currentDivided1Amount % dividers.get(1);
if (divided2Amount == 0) {
StringBuilder output = new StringBuilder();
output.append(dividers.get(0) + ":" + i);
if (divided1Remainder != 0) {
output.append(", Remainder: " + divided1Remainder);
}
System.out.println(output);
} else {
StringBuilder output = new StringBuilder();
output.append(dividers.get(0) + ":" + i + "," + dividers.get(1) + ":" + divided2Amount);
if (divided2Remainder != 0) {
output.append(", Remainder: " + divided2Remainder);
}
System.out.println(output);
}
}
}
}
This is also available on GitHub: https://github.com/realm1930/rekendin/blob/master/src/Main.java
Could anybody please enlighten me. I am sorry if I am not clear at my description of the issue.
Thanks

While a fixed number of dividers can be well approached with nested loops, I suggest for the general case to write the solution as a recursive function.
This problem is a good fit for dynamic programming. What I mean by this is that the problem can be broken down into simpler subproblems, and in this way the solution is naturally implemented with recursion. For instance, in your example of expressing 100 as a sum of multiples of 50, 20, and 10, there are three solutions found that all use one 50:
Amount of 50 : 1, Amount of 20 : 0, Amount of 10 : 5
Amount of 50 : 1, Amount of 20 : 1, Amount of 10 : 3
Amount of 50 : 1, Amount of 20 : 2, Amount of 10 : 1
Look at this as solving the subproblem of finding the ways that value 50 can be expressed as multiples of 20 and 10 (that is, 50 is equal to 20*0 + 10*5, 20*1 + 10*3 and 20*2 + 10*1). So you can divide-and-conquer the original problem in this sense.
Let X be the number (e.g. 100) to express, and D1, D2, ... DN the dividers. Here is a possible outline:
If there is just one divider, N = 1, it is easy: there just zero or one solution depending on whether D1 divides X.
Otherwise, possible solutions might have D1 with any multiple from 0, 1, ..., X/D1. So make a loop m1 = 0, 1, ..., X/D1, and recursively solve the subproblem having X' = X - m1*D1 and the remaining dividers D2, ..., DN. This subproblem has one fewer divider, so after enough recursions it reduces to the N = 1 case.
That solves the problem. Note, though, that fully recursing may result in a combinatorially vast number of subproblems to solve. So for efficient solution it is a good idea to store or "memoize" the solutions of previously-solved subproblems in a table so that work isn't repeated.
Other thoughts:
Let Q be the greatest common divisor (GCD) of all the dividers {D1, ..., DN}. If X isn't divisible by Q, then there are no solutions, in which case we can skip the above recursive search entirely. E.g. there is no way to express X = 103 with dividers 50, 20, and 10. This GCD test can also be applied to every subproblem so that some recursive calls can return early.
This problem is a kind of Diophantine equation, more specifically, it is related to the Frobenius coin problem and Frobenius numbers. There is a mathoverflow post discussing it.

Related

WAP in java to input a three digit number and calculate each digit's frequency

I made a program for the question and it's working fine, but in some cases it's not working like when I enter 656, it's showing like this:
The error
The code is showed below:
public static void main(String[] args) {
Scanner rx = new Scanner(System.in);
int ui,uiy,troll3,troll1;
float uix,uis,uiz,uit;
System.out.println("Enter a valid three digit number to calculate the frequency of the digits in it. \n");
ui = rx.nextInt();
if(ui>99&&ui<=999) {
uis = (float) ui;
//System.out.println(uis+" uis");
uix = uis / 10;
//System.out.println(uix+" uix");
uiy = (int) uix;
//System.out.println(uiy+" uiy");
troll3 = (int) ((uix - uiy) * 10); //1st digit
//System.out.println("3d " + troll3);
uiz = uix / 10;
//System.out.println(uiz+ " uiz");
troll1 = (int) uiz;
//System.out.println("1d " + troll1);
uit = (uiz - troll1) * 10;
//System.out.println(uit+" uit");
int troll2 = (int) uit;
//System.out.println("2d " + troll2);
if (troll1 == troll2 && troll1 == troll3) {
System.out.println("The number " + troll1 + " appears three times.");
} else if (troll1 != troll2 && troll2 != troll3 && troll1 != troll3) {
System.out.println("The number " + troll1 + " appears one time.");
System.out.println("The number " + troll2 + " appears one time.");
System.out.println("The number " + troll3 + " appears one time.");
} else if (troll1 == troll2) {
System.out.println("The number " + troll1 + " appears two times.");
System.out.println("The number " + troll3 + " appears one time.");
} else if (troll1 == troll3) {
System.out.println("The number " + troll3 + " appears two times.");
System.out.println("The number " + troll2 + " appears one time.");
} else if (troll2 == troll3) {
System.out.println("The number " + troll2 + " appears two times.");
System.out.println("The number " + troll1 + " appears one time.");
}
}
else{
System.out.println("The entered number is invalid");
}
}
It mostly gives an error when it consists of digit 5 in the middle. It shows an increment in values and swap in values. Please do help.
Thanks in advance! :-)
Why are you converting to float? float and double attempts to represent an infinite infinity of numbers (there are an infinite amount of integers. Between 2 integers, there are an infinite amount of numbers too: An infinite amount of infinities)... using only 32 bits. This is obviously impossible so instead only a few numbers are representable, and anything else is silently rounded to one of the select few. This means float and double introduce rounding errors.
After any math done to any double or float, == is broken. You can't use those; at best, you can try 'delta equality' (not a == b, but Math.abs(a - b) < 0.00001) but making the claim that your code works for all possible inputs becomes very difficult indeed, it's not going to be very fast, and the code readability isn't great either. So, don't.
Stop using floats, problem solved.
Your 'math' to get the individual digits is a bit circumspect and isn't going to just work if you replace things with int either. What you're missing is the % operator: Module (a.k.a. remainder).
Given, say, 656:
int in = 657;
int digit1 = in % 10;
in = in / 10;
System.out.println(in); // 65
System.out.println(digit1); // 7
int digit2 = in % 10;
in = in / 10;
System.out.println(in); // 6
System.out.println(digit1); // 5
int digit3 = in;

Java Coin Change Problem Using Recursion -- not working

I searched up the code and logic for this and basically copied the code from https://www.youtube.com/watch?v=k4y5Pr0YVhg
and https://www.techiedelight.com/coin-change-problem-find-total-number-ways-get-denomination-coins/
But my program is wrong because there are definitely more than 2 ways to make 2 pounds.
public class TwoPounds
{
private static int[] coins = {1, 2, 5, 10, 20, 50, 100, 200};
private static int amount;
private static int count;
public TwoPounds()
{
amount = 2;
count = 0;
}
public static void main(String[] args)
{
TwoPounds run = new TwoPounds();
count = run.combos(amount);
run.printOut();
}
public int combos(int amountIn)
{
if (amountIn == 0)
{
return 1;
}
if (amountIn < 0)
{
return 0;
}
int combosCount = 0;
for(int i = 0; i < coins.length; i++)
{
System.out.println("amountIn now is " + amountIn);
combosCount += combos(amountIn - coins[i]);
}
return combosCount;
}
public void printOut()
{
System.out.println("\n\n\n");
System.out.println("There are " + count + " ways can 2 pounds be made, "
+ "using any number of coins");
System.out.println("\n\n\n");
}
}
Output:
There are 2 ways can 2 pounds be made, using any number of coins
Your coins are in cents (or pence, since I guess you are using GB Pounds), so since you are performing amountIn - coins[i] with them, that means that your amount is cents/pence as well.
So, change your amount to the :
amount = 200;
It is worth taking a moment to consider variable naming, and how that might have helped identify - or even avoid - this problem altogether. The terms "amount" and "amountIn" are ambiguous.
Nothing in the words suggests the units. So, get into the habit of making variable names as specific and unambiguous as possible - and include units where appropriate.
eg, if the variables were called 'amountInPounds', then the error becomes more obvious when writing amountInPounds - coins[i]
Now, before you do update to amount = 200;, be aware that :
1) There will be a LARGE number of results (200 pennies, 198 pennies+2p), that will take some time to iterate through one-penny-at-a-time, plus
2) Your code is currently written to go through EVERY discrete ordered combination - eg, it will be counting :
198 "1 cent" + 1 "2 cent"
197 "1 cent" + 1 "2 cent" + 1 "1 cent"
196 "1 cent" + 1 "2 cent" + 2 "1 cent"
195 "1 cent" + 1 "2 cent" + 3 "1 cent"
etc
Again, WAY too much execution time. What you want is to not start your for(int i = 0; i < coins.length; i++) from zero each time, but instead add an extra parameter to combos - so something like :
public int combos (int amountIn, int startCoin)
{
// blah ... existing code ... blah
for(int i = startCoin; i < coins.length; i++)
{
System.out.println("amountIn now is " + amountIn);
combosCount += combos(amountIn - coins[i], i);
}
Finally, as I said before, 200 will result in BIG numbers that will be effectively impossible for you to confirm correctness, so instead start with small amounts that you can check.
This algorithm allows the use of several coins of the same denomination, so there are 2 ways to make 2 pounds:
{1, 1}
{2}

Printing from a loop

I need to print the factors of a perfect number. Here's the gist of my main class:
ArrayList<Integer> perfNums = new ArrayList<>();
Scanner in = new Scanner(System.in);
System.out.print("Enter the upperbound: ");
upperbound = in.nextInt();
for (int i = 1; i <= upperbound; i++) {
if (isPerfect(i)) { //boolean to check if number is a perfect number
perfNums.add(i);
}
}
System.out.println("Perfect numbers between 1 and " + upperbound + " are:");
for (int i = 0; i < perfNums.size(); i++) {
System.out.print(perfNums.get(i) + " = ");
printFactor((int)perfNums.get(i));
System.out.println();
}
Here's the printFactor class.
private static void printFactor(int number){
int factor = 1;
while(factor < number){
if (number%factor == 0) System.out.print(factor+ " + ");
//I don't know how to print the + sign otherwise.
factor++;
}
}
And here's a sample output:
Enter the upperbound: 10000
Perfect numbers between 1 and 10000 are:
6 = 1 + 2 + 3 +
28 = 1 + 2 + 4 + 7 + 14 +
496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248 +
8128 = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 127 + 254 + 508 + 1016 + 2032 + 4064 +
I've got the main gist of it but I've struggled with an output issue. Due to the restrictions of my online submission system, my output needs to fit exact specifications.
My question is how do I go about printing all the factors of my perfect number but removing the + sign at the end? (e.g)6 = 1 + 2 + 3
I'm not too sure of many methods to print from a while loop. Would a for-loop be better for my goals? Or are there alternative methods to print the factors of a number?
The least amount of change to address this might be something like this:
private static void printFactor(int number)
System.out.print(1);
int factor = 2;
while (factor<number) {
if (number%factor == 0) System.out.print(" + " + factor);
factor++;
}
}
1 is always a factor, so you can print that before the loop and then prepend + to every subsequent factor.
You should cache the output you want to print into a StringBuilder. Then you are able to remove the last plus sign before you print the whole String. It also has a better performance.
private static void printFactor(int number)
{
StringBuilder output = new StringBuilder();
int factor = 1;
while (factor < number)
{
if (number % factor == 0)
output.append(factor + " + ");
factor++;
}
// remove last plus sign
output.deleteCharAt(output.length() - 1);
// print the whole string
System.out.print(output.toString());
}
Since factor starts from value 1 and number % 1 == 0 will always be true, you might print 1 first and then flip factor and + in System.out.print. Like this:
private static void printFactor(int number) {
if(number > 0) {
System.out.print(1);
}
int factor = 2;
while (factor<number) {
if (number % factor == 0) {
System.out.print(" + " + factor);
}
factor++;
}
}
Not the best solution, but it will do the job.
Try to create a variable String numb and use substring method like this:
String numb ="";
while(factor<number){
if(number%factor == 0)
numb= numb + factor+ " + ";
factor++;
}
System.out.print(numb.substring(0, numb.trim().length()-1));
Just for the sake of using Java 8 :)
private static void printFactor(int number){
System.out.println(IntStream.range(1, number)
.filter(p -> number % p == 0)
.mapToObj(i -> String.valueOf(i))
.collect(Collectors.joining(" + ")));
}
Thanks everyone for the quick response. You all have been a lifesaver, and I managed to pick up some new things to consider when I code in the future.
Anyway, while waiting for a reply I was fiddling with the code and came up with a rather inelegant solution, if anybody's interested. Here's the changes to the main class:
System.out.println("Perfect numbers between 1 and " + upperbound + " are:");
for(int i=0; i<perfNums.size(); i++){
System.out.print(perfNums.get(i) + " = ");
outputString = printFactor2(perfNums.get(i));
if(outStr.endsWith(" + ")) outStr = outStr.substring(0, outStr.length()-3);
//because the submission system would cry foul with even a single extra space
System.out.println(outStr);
}
And here's the changes to the printFactor class:
private static String printFactor2(int number){
String out = "";
int factor = 1;
while(factor<number){
if(number%factor == 0) out += factor + " + ";
factor++;
}
return out;
}
Basically, what I did was append the factors to a string, then removing the trailing + sign using the substring method. On hindsight, I probably should've called the substring method inside the printFactor class instead. Something like return out.substring(0, out.length()-3); perhaps?
Nevertheless, thanks everyone!

How to improve the efficiency of the algorithm while using Iterator in java?

This is the question:
There are N boys and N girls. Only a boy and a girl can form a dancing pair (i.e. no same sex dancing pairs are allowed). The only other condition in making pairs is that their absolute difference in height should be less than or equal to K.
Find the maximum number of pairs that can be formed so that everyone has a unique partner.
I want to improve my algorithm to take less time..
first see the code:
//k is the maximum difference between pairs
int k = 5;
ArrayList<Integer> ArrBoys = new ArrayList<>(Arrays.asList(new Integer[]{28, 16, 22}));
ArrayList<Integer> ArrGirls = new ArrayList<>(Arrays.asList(new Integer[]{13, 10, 14}));
//sorting all arrays
Collections.sort(ArrBoys);
Collections.sort(ArrGirls);
System.out.println("After Sorting");
//printing arrays after sorting
for (Integer ArrBoy : ArrBoys) {
System.out.print(ArrBoy + " ");
}
System.out.println("");
for (Integer ArrGirl : ArrGirls) {
System.out.print(ArrGirl + " ");
}
System.out.println("");
//algorithm used to find the number of pairs
int count = 0;
for (Iterator<Integer> iteB = ArrBoys.iterator(); iteB.hasNext();) {
Integer ArrBoy = iteB.next();
for (Iterator<Integer> iteG = ArrGirls.iterator(); iteG.hasNext();) {
{
Integer ArrGirl = iteG.next();
int dif = (int) Math.abs(ArrBoy - ArrGirl);
if (dif <= k) {
System.out.println("we took " + ArrBoy + " from boys with "
+ ArrGirl + " from girls, thier dif < " + k);
ArrBoys.remove(ArrBoy);
ArrGirls.remove(ArrGirl);
iteB = ArrBoys.iterator();
count++;
break;
} else {
System.out.println("we try " + ArrBoy + " from boys with " + ArrGirl + " from grils but thier dif > " + (int) k);
//ArrGirls.remove(ArrGirl);
}
}
}
}
System.out.println("the number of pairs we can take is "+count);
the output of this code is:
As you see this algorithm inefficient since we don't need to start comparing the height from the first girl for the second boy, we should go to the girl which come after the previous girl we took as pair.
For example:
in the boy with 22 height, the algorithm must start comparing the boys'height with the girl with 14 height, because we already sort them, if the first boy (shorter) cant make a pair with the first girl so definitely the second boy (longer) cant also, we waste the time if we compare from the first girl.
We can solve this problem by two choices, either by making the iterator start with the girl after the previous boy has been stopped (i don't know how to do it with iterator), or by removing the girl from the arraylist once if it's not satisfy the condition and let the loop start with first girl (i tried this but it gives me an exception)
Solve it by these two ways if you can...
You have to add more conditions. Here it is, there are three options :
abs(dif) <= k : they can dance together
dif > k : even the current boy (the smallest) is too tall for her, no one can dance with her, exclude her
dif < -k : the first girl is far too tall for him, exclude him
Here is the code:
int count = 0;
int gLimit = 0;
for (int b = 0; b<ArrBoys.size();b++) {
if(gLimit == ArrGirls.size()) {
System.out.println("no more girl for boy " + ArrBoys.get(b));
}
for (int g = gLimit; g<ArrGirls.size();g++) {
{
int dif = ArrBoys.get(b) - ArrGirls.get(g);
if (Math.abs(dif) <= k) {
System.out.println("we took " + ArrBoys.get(b) + " from boys with "
+ ArrGirls.get(g) + " from girls, thier dif < " + k);
gLimit++;
count++;
break;
} else if (dif > k) {
System.out.println("we try " + ArrBoys.get(b) + " from boys with " + ArrGirls.get(g) + " from grils but thier dif > " + (int) k + ", girl too small, excluded");
gLimit++;
} else if (dif < -k) {
System.out.println("we try " + ArrBoys.get(b) + " from boys with " + ArrGirls.get(g) + " from grils but thier dif > " + (int) k + ", boy too small, excluded");
break;
}
}
}
}
I used get index for more maniability on lists content
Here is the ouput
After Sorting
16 22 28
10 13 14
we try 16 from boys with 10 from grils but thier dif > 5, girl too small, excluded
we took 16 from boys with 13 from girls, thier dif < 5
we try 22 from boys with 14 from grils but thier dif > 5, girl too small, excluded
no more girl for boy 28
the number of pairs we can take is 1

Converting text mathematical equations to number and signs

I actually have two questions.
first how do I convert text (ex. One) to actual numbers (1) and plus to +. As I am trying to take the speech which starts with calculate and do the maths within that speech.
But for some reason speech recognition write down numbers and signs in text ( one plus three ) rather than (1+3).
The other question, is their any API or libraries that carry out heavy math equation like sin,cos integration and all the a level math. and giving out the process that it carried out to reach the solution.
What you're asking is not particularly difficult, but gets trickier as you increase the complexity. Depending on how much you need to understand, this may become very complicated. However for simple number plus number or number minus number, it's reasonably easy. To get you started, the following code will be able to deal with these two scenarios. Feel free to expand it as you wish. Also note that it has minimal error checking - in a production system you'll need quite a bit more of it.
import java.util.Map;
import java.util.HashMap;
public class Nums {
private static Map<String, Integer> nums = new HashMap<String, Integer>();
public static void main(String[] args) {
nums.put("zero", 0);
nums.put("one", 1);
nums.put("two", 2);
nums.put("three", 3);
nums.put("four", 4);
nums.put("five", 5);
nums.put("six", 6);
nums.put("seven", 7);
nums.put("eight", 8);
nums.put("nine", 9);
nums.put("ten", 10);
nums.put("eleven", 11);
nums.put("twelve", 12);
nums.put("thirteen", 13);
nums.put("fourteen", 14);
nums.put("fifteen", 15);
nums.put("sixteen", 16);
nums.put("seventeen", 17);
nums.put("eighteen", 18);
nums.put("nineteen", 19);
nums.put("twenty", 20);
nums.put("thirty", 30);
nums.put("forty", 40);
nums.put("fifty", 50);
nums.put("sixty", 60);
nums.put("seventy", 70);
nums.put("eighty", 80);
nums.put("ninety", 90);
String input = args[0].toLowerCase();
int pos;
String num1, num2;
int res1, res2;
if((pos = input.indexOf(" plus ")) != -1) {
num1 = input.substring(0, pos);
num2 = input.substring(pos + 6);
res1 = getNumber(num1);
res2 = getNumber(num2);
System.out.println(args[0] + " => " + res1 + " + " + res2 + " = " + (res1 + res2));
}
else if((pos = input.indexOf(" minus ")) != -1) {
num1 = input.substring(0, pos);
num2 = input.substring(pos + 7);
res1 = getNumber(num1);
res2 = getNumber(num2);
System.out.println(args[0] + " => " + res1 + " - " + res2 + " = " + (res1 - res2));
}
else {
System.out.println(args[0] + " => " + getNumber(args[0]));
}
}
private static int getNumber(String input) {
String[] parts = input.split(" +");
int number = 0;
int mult = 1;
String fact;
for(int i=parts.length-1; i>=0; i--) {
parts[i] = parts[i].toLowerCase();
if(parts[i].equals("hundreds") || parts[i].equals("hundred")) {
mult *= 100;
}
else if(parts[i].equals("thousands") || parts[i].equals("thousand")) {
if(number >= 1000) {
throw new NumberFormatException("Invalid input (part " + (i + 1) + ")");
}
mult = 1000;
}
else if(parts[i].equals("millions") || parts[i].equals("million")) {
if(number >= 1000000) {
throw new NumberFormatException("Invalid input (part " + (i + 1) + ")");
}
mult = 1000000;
}
else if(!nums.containsKey(parts[i])) {
throw new NumberFormatException("Invalid input (part " + (i + 1) + ")");
}
else {
number += mult * nums.get(parts[i]);
}
}
if(!nums.containsKey(parts[0])) {
number += mult;
}
return number;
}
}
This code handles numbers from 0 to 999,999,999 and doesn't handle negative numbers. Again, it shouldn't be too difficult to extend it to increase the range or handle negative numbers. Note that if you extend it to handle billions, you may need to switch from integer to long variables to hold the results.
Here are some test runs:
$ java Nums "three hundred nineteen million five hundred twenty three thousand six hundred eighteen"
three hundred nineteen million five hundred twenty three thousand six hundred eighteen => 319523618
$ java Nums "five hundred minus three hundred ninety nine"
five hundred minus three hundred ninety nine => 500 - 399 = 101
$ java Nums "thirty three plus seventeen"
thirty three plus seventeen => 33 + 17 = 50
$ java Nums zero
zero => 0
$ java Nums "one plus three"
one plus three => 1 + 3 = 4
$ java Nums "hundred thousand"
hundred thousand => 100000
$ java Nums "hundred thousand minus ten thousand"
hundred thousand minus ten thousand => 100000 - 10000 = 90000

Categories