Skip to content

Instantly share code, notes, and snippets.

@iconifyit
Created January 31, 2020 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iconifyit/aca848be50baa599e5a0c75c5d73ce5c to your computer and use it in GitHub Desktop.
Save iconifyit/aca848be50baa599e5a0c75c5d73ce5c to your computer and use it in GitHub Desktop.
Solution to "Is it a valid number coding test". See the first comment below for test cases.
/**
* The main function.
* @param s
* @returns {boolean}
*/
function isNumber(s) {
s = s.trim();
var chars = new Set(s);
// Set a sequence point so we knoww
var kSEQ = ';';
if (chars.has(kSEQ)) return false;
s += kSEQ;
var tokens = new Set('0123456789+-.e'),
len = s.length,
c = '',
e = 'e',
p = '+',
m = '-',
d = '.',
i = 0,
hasE = false,
hasS = false,
hasD = false,
hasN = false;
c = s.charAt(i);
while (c !== kSEQ) {
// This is not a valid token
if (! tokens.has(c)) return false;
// Is this a sign?
else if (c === p || c === m) {
// 1 ) If we have seen the sign before, the number is invalid.
// 2 ) If we just saw a number, it is invalid.
// 3 ) If we have seen `.` but not `e`, it is invalid.
if (hasS) return false;
if (hasN) return false;
if (hasD && ! hasE) return false;
// 1 ) Mark the sign.
hasS = true;
}
// Is this a decimal?
else if (c === d) {
// 1 ) If we have seen the decimal already, the num is invalid.
if (hasD) return false;
// 1 ) Mark the `.`
hasD = true;
}
// Is this an `e`?
else if (c === e) {
// 1 ) If we have seen `e` before, the num is invalid.
// 2 ) If we have not seen a number, it is invalid.
if (hasE) return false;
if (! hasN) return false;
// 1 ) We can reset the sign value after `e`
// 2 ) Mark the `.` as seen (skips useless comparisons)
// 3 ) Reset the number marker.
// 4 ) Mark the `e`
hasS = false;
hasD = true;
hasN = false;
hasE = true;
}
// Otherwise, it must be a number, just keep reading.
else {
hasN = true;
}
c = s.charAt(++i);
}
return hasN;
}
@iconifyit
Copy link
Author

iconifyit commented Jan 31, 2020

var tests = [ ".e1", ".2e81", "46.e3", " -.", "-1.", "1.-", "1-2", " ", "3.", ".", "e", "+", "-", ".1", "0", " 0.1 ", "abc", "1 a", "2e10", " -90e3   ", " 1e", "e3", " 6e-1", " 6-e1", " 99e2.5 ", "53.5e93", " --6 ", "-+3", "95a54e53", "0.0", "1.2", "3", "0.0", "1.2.3", ".2", "1.", "1e2", "3.5e4e", ".2e81", "1.2345E-02", "1--2", "1++2", "1+-2", "1-+2", "2.3+e2", "2.3e+2", "2e.3", "3.456e4", "0", "0.0", "0.e0", "0.e-0", "0.e+0", "1-2", "1+2", "2e0", "2e-0", "2e+0", "2e1.2", ".e-0", "1..2", "1-.2", "1--", "1++", "+1+", "+1-", "-1-", "-1+", "-.3e6", " -.7e+0435", "166e-02767", "166e-02", "166e-027" ];  

var expects = [ false, true, true, false, true, false, false, false, true, false, false, false, false, true, true, true, false, false, true, true, false, false, true, false, false, true, false, false, false, true, true, true, true, false, true, true, true, false, true, false, false, false, false, false, false, true, false, true, true, true, true, true, true, false, false, true, true, true, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true ]; 

@iconifyit
Copy link
Author

To use the test data, create a loop to call isNumber(test) on each item in the tests array and compare the result to the same item in the expects array.

tests.map(function(test, i) {
    console.log(isNumber(test), expects(i));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment