1

I am looking for a way to sort “number words” into numerical order. For example, suppose I had the list [“five”, “three”, “six”, “eight”], I would like to sort it as [“three’, “five”, “six”, “eight”] rather than in lexicographical order. I have looked around, including this site, and the closest/best solution is to use a map and sort the list based on key-value pairs.

I came up with other ideas similar to this as well but in the end all of them require building a big table/list to match up number words to the actual number. I would like a solution, if possible, that is automatically extendable – so if it works for the list above, it would also work for the list [“ten quadrillion nine hundred million five thousand and two”, “six”, “four”]. The more I think about it, the less sure I am that it can be done. Any help is greatly appreciated.

Ron
  • 21
  • 1
  • I'm not sure this is totally appropriate for the standard SO question format, but I think what you want to do is: A) Write a parser that can convert words to their numeric equivalent (Note that you might be able to leverage wolfram alpha, which would also allow you to sort ["ten plus five","three","six times eight"]) B) Create a dictionary to map between the word and number for each element in the list C) Sort that dictionary D) Remap to produce the sorted list I would suggest trying to do this and then if you still need help, show what you've tried and where you're stuck – Foon Mar 27 '15 at 15:49
  • @Foon - Thanks! The word parser is what I need mostly. There is a nice one on SO at http://stackoverflow.com/questions/70161/how-to-read-values-from-numbers-written-as-words and I will try to implement the algorithm given in java. When I get stuck, I will post my work. Thanks again! – Ron Mar 28 '15 at 04:02

2 Answers2

0

You can use the following function to convert the numbers and then just use any standard sorting algorithm to sort the numbers.

public static int convertNum(String input)
{       
    ArrayList<String> prefixTable = new ArrayList<String>();
    prefixTable.add("ZE");
    prefixTable.add("ON");
    prefixTable.add("TW");
    prefixTable.add("TH");
    prefixTable.add("FO");
    prefixTable.add("FI");
    prefixTable.add("SI");
    prefixTable.add("SE");
    prefixTable.add("EI");
    prefixTable.add("NI");
    prefixTable.add("TEN");
    prefixTable.add("ELEVEN");
    prefixTable.add("TWELVE"); //MUST BE AT END OTHERWISE TW REGISTERS AS PREFIX

    Map<String, Integer> delimTable = new HashMap<String, Integer>();
    delimTable.put("HUNDRED", 100);
    delimTable.put("THOUSAND", 1000);
    delimTable.put("MILLION", 1000000);
    delimTable.put("BILLION", 1000000000);

    String[] theWords = input.toUpperCase().split(" ");  
    int runningTotal = 0;
    int currentRunningNum = 0;
    int currentNum = 1;
    boolean skipTransfer = false;

    for(int i = 0; i < theWords.length; i++)
    {
        if(theWords[i].equals("AND") || theWords[i].equals("NEGATIVE"))
            continue;

        if(delimTable.containsKey(theWords[i]))
        {
            if(delimTable.get(theWords[i]) == 100)
                skipTransfer = true;
            else
                skipTransfer = false;
            currentRunningNum *= delimTable.get(theWords[i]);
            continue;
        }

        if(!skipTransfer)
        {
            runningTotal += currentRunningNum;
            currentRunningNum = 0;
        }
        skipTransfer = false;

        currentNum = 1;

        for(int j = prefixTable.size() - 1; j >= 0 && currentNum == 1; j--)
            if(theWords[i].startsWith(prefixTable.get(j)))
                currentNum *= j;

        if(theWords[i].endsWith("EEN"))
            currentNum += 10;
        if(theWords[i].endsWith("TY"))
        {
            currentNum *= 10;
            skipTransfer = true;
        }

        currentRunningNum += currentNum; //ADD TOTAL
    }
    runningTotal += currentRunningNum;
    if(theWords[0].equals("NEGATIVE"))
        runningTotal *= -1;

    return runningTotal;
}
abagshaw
  • 6,162
  • 4
  • 38
  • 76
0

Perhaps try this answer: https://stackoverflow.com/a/26951693/3663023. It worked for me when I was trying to solve this exact problem. As @abagshaw mentioned, sorting the array using any sorting algorithm would work after the numbers in word form are converted to number form.

The code from @Kartic is as follows:

boolean isValidInput = true;
long result = 0;
long finalResult = 0;
List<String> allowedStrings = Arrays.asList
(
        "zero","one","two","three","four","five","six","seven",
        "eight","nine","ten","eleven","twelve","thirteen","fourteen",
        "fifteen","sixteen","seventeen","eighteen","nineteen","twenty",
        "thirty","forty","fifty","sixty","seventy","eighty","ninety",
        "hundred","thousand","million","billion","trillion"
        );

String input="One hundred two thousand and thirty four";

if(input != null && input.length()> 0)
{
    input = input.replaceAll("-", " ");
    input = input.toLowerCase().replaceAll(" and", " ");
    String[] splittedParts = input.trim().split("\\s+");

    for(String str : splittedParts)
    {
        if(!allowedStrings.contains(str))
        {
            isValidInput = false;
            System.out.println("Invalid word found : "+str);
            break;
        }
    }
    if(isValidInput)
    {
        for(String str : splittedParts)
        {
            if(str.equalsIgnoreCase("zero")) {
                result += 0;
            }
            else if(str.equalsIgnoreCase("one")) {
                result += 1;
            }
            else if(str.equalsIgnoreCase("two")) {
                result += 2;
            }
            else if(str.equalsIgnoreCase("three")) {
                result += 3;
            }
            else if(str.equalsIgnoreCase("four")) {
                result += 4;
            }
            else if(str.equalsIgnoreCase("five")) {
                result += 5;
            }
            else if(str.equalsIgnoreCase("six")) {
                result += 6;
            }
            else if(str.equalsIgnoreCase("seven")) {
                result += 7;
            }
            else if(str.equalsIgnoreCase("eight")) {
                result += 8;
            }
            else if(str.equalsIgnoreCase("nine")) {
                result += 9;
            }
            else if(str.equalsIgnoreCase("ten")) {
                result += 10;
            }
            else if(str.equalsIgnoreCase("eleven")) {
                result += 11;
            }
            else if(str.equalsIgnoreCase("twelve")) {
                result += 12;
            }
            else if(str.equalsIgnoreCase("thirteen")) {
                result += 13;
            }
            else if(str.equalsIgnoreCase("fourteen")) {
                result += 14;
            }
            else if(str.equalsIgnoreCase("fifteen")) {
                result += 15;
            }
            else if(str.equalsIgnoreCase("sixteen")) {
                result += 16;
            }
            else if(str.equalsIgnoreCase("seventeen")) {
                result += 17;
            }
            else if(str.equalsIgnoreCase("eighteen")) {
                result += 18;
            }
            else if(str.equalsIgnoreCase("nineteen")) {
                result += 19;
            }
            else if(str.equalsIgnoreCase("twenty")) {
                result += 20;
            }
            else if(str.equalsIgnoreCase("thirty")) {
                result += 30;
            }
            else if(str.equalsIgnoreCase("forty")) {
                result += 40;
            }
            else if(str.equalsIgnoreCase("fifty")) {
                result += 50;
            }
            else if(str.equalsIgnoreCase("sixty")) {
                result += 60;
            }
            else if(str.equalsIgnoreCase("seventy")) {
                result += 70;
            }
            else if(str.equalsIgnoreCase("eighty")) {
                result += 80;
            }
            else if(str.equalsIgnoreCase("ninety")) {
                result += 90;
            }
            else if(str.equalsIgnoreCase("hundred")) {
                result *= 100;
            }
            else if(str.equalsIgnoreCase("thousand")) {
                result *= 1000;
                finalResult += result;
                result=0;
            }
            else if(str.equalsIgnoreCase("million")) {
                result *= 1000000;
                finalResult += result;
                result=0;
            }
            else if(str.equalsIgnoreCase("billion")) {
                result *= 1000000000;
                finalResult += result;
                result=0;
            }
            else if(str.equalsIgnoreCase("trillion")) {
                result *= 1000000000000L;
                finalResult += result;
                result=0;
            }
        }

        finalResult += result;
        result=0;
        System.out.println(finalResult);
    }
}
Community
  • 1
  • 1
Katherine
  • 639
  • 5
  • 16