Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript parse string to integer

Tags:

javascript

Working over at codewars I was trying to solve this problem:

In this kata we want to convert a string into an integer. The strings simply represent the numbers in words.

Examples:

  • "one" => 1
  • "twenty" => 20
  • "two hundred forty-six" => 246
  • "seven hundred eighty-three thousand nine hundred and nineteen" => 783919

==================================================================================

I came up with the code below to do this. On jsfiddle for you convience.

A problem I've run into is 'seven hundred thousand' gives you 10700.

I've spent a day looking around and trying to figure this out but am just flat stuck. The steps the program takes is:

  • string becomes 'thousand hundred seven' - good
  • first while loop finds 'thousand' and sets multiplier to 1000 - good
  • second while loop finds 'hundred' but then the mult.exec(a[0]) if statement resolves to null. - damn

So instead of the multiplier becoming 100000, the value becomes 100000, and we are doomed to get the wrong answer.

While trying to debug this I tried creating the a array being used during the second loop in the while in jsfiddle. There it worked and equated to 'hundred' instead of null. Anyone know why this would happen?

function parseInt(number) { 

    // reference array for english -> integer
    var ref = { one:1, two:2, three:3, four:4, five:5, six:6, seven:7, eight:8, nine:9, ten:10, eleven:11, twelve:12, thirteen:13, fourteen:14, fifteen:15, sixteen:16, seventeen:17, eighteen:18, nineteen:19, twenty:20, thirty: 30, forty: 40, fifty: 50, sixty: 60, seventy: 70, eighty: 80, ninety:90, hundred: 100, thousand: 1000, million: 1000000 };

    // regex to find number values from the string
    var find = new RegExp( "(one|t(wo|hree|en|welve|hirteen|wenty|hirty)|f(our|ive|ourteen|iftenn|orty|ifty)|s(ixteen|ixty|eventy|ix|even|eventeen|teen)|eigh(ty|t|teen)|nin(ety|e|eteen)|zero|hundred|thousand|million)", "gi" );

    // hundred/thousand/million etc. act as multipliers in this solution and need a seperate search
    var mult = new RegExp( "(hundred|thousand|million)", "gi" );

    // reversing the string allows us to add largest digits first
    number = number.split(' ').reverse().join(" ");

    // while there is a number in string number
    //   if that number is a multiplier
    //     if that number is 100 -> multiplier = multiplier * 100;
    //     else multiplier = reference value;
    //   else value = value + reference value * multiplier
    // end while
    value = 0; multiplier = 1;
    while( a = find.exec(number) ) {

        if( m = mult.exec(a[0]) ) {

            if( m[0] == 'hundred' ) { multiplier *= 100; }
            else { multiplier = ref[m[0]]; }

        }
        else {

            value += ref[a[0]] * multiplier;

        }

    }   
    return value;
}
like image 223
benwsmith Avatar asked Nov 09 '13 20:11

benwsmith


1 Answers

maybe you don't need regex

function parse(numbersInString){
    var ref = { one:1, two:2, three:3, four:4, five:5, six:6, seven:7, eight:8, nine:9, ten:10, eleven:11, twelve:12, thirteen:13, fourteen:14, fifteen:15, sixteen:16, seventeen:17, eighteen:18, nineteen:19, twenty:20, thirty: 30, forty: 40, fifty: 50, sixty: 60, seventy: 70, eighty: 80, ninety:90 },
        mult = { hundred: 100, thousand: 1000, million: 1000000 },
        strNums = numbersInString.split(' ').reverse(),
        number = 0,
        multiplier = 1;

    for(i in strNums){
        if( mult[strNums[i]] != undefined ) {
            if(mult[strNums[i]]==100) {
                multiplier*=mult[strNums[i]]
            }else{
                multiplier=mult[strNums[i]]
            }
        } else {
            if (!isNaN(parseFloat(strNums[i]))) {
                number += parseFloat(strNums[i]) * multiplier;
            } else {
                var nums = strNums[i].split('-');
                number += ((ref[nums[0]]||0) + (ref[nums[1]]||0)) * multiplier;
            }
        }
    }
    return number;
}
like image 166
Grundy Avatar answered Oct 07 '22 00:10

Grundy