65. Valid Number

Validate if a given string can be interpreted as a decimal number.

Some examples:
`"0"` => `true`
`" 0.1 "` => `true`
`"abc"` => `false`
`"1 a"` => `false`
`"2e10"` => `true`
`" -90e3   "` => `true`
`" 1e"` => `false`
`"e3"` => `false`
`" 6e-1"` => `true`
`" 99e2.5 "` => `false`
`"53.5e93"` => `true`
`" --6 "` => `false`
`"-+3"` => `false`
`"95a54e53"` => `false`

Note: It is intended for the problem statement to be ambiguous. It would be best if you gathered all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number:

• Numbers 0-9
• Exponent - "e"
• Positive/negative sign - "+"/"-"
• Decimal point - "."

Of course, the context of these characters also matters in the input.

Example 1:

```Input: s = "0"
Output: true
```

Example 2:

```Input: s = "3"
Output: true
```

Constraints:

• `1 <= s.length <= 20`
• `s` consists of only English letters, digits, space `' '`, plus `'+'`, minus `'-'`, or dot `'.'`.

65. Valid Number
``````struct Solution;

use std::cmp::Ordering::*;
use std::iter::Peekable;
use std::vec::IntoIter;

#[derive(PartialEq, Eq, Clone, Copy)]
enum Tok {
Num(i32),
Op(char),
}

impl Solution {
fn is_number(s: String) -> bool {
let s = s.trim();
let mut it = s.chars().peekable();
let mut tokens: Vec<Tok> = vec![];
let mut e_count = 0;
while let Some(c) = it.next() {
match c {
' ' | '-' | '+' | '.' => {
tokens.push(Tok::Op(c));
}
'e' => {
e_count += 1;
if e_count == 2 {
return false;
}
tokens.push(Tok::Op(c));
}
'0'..='9' => {
let mut x = (c as u8 - b'0') as i32;
while let Some('0'..='9') = it.peek() {
x *= 10;
x += (it.next().unwrap() as u8 - b'0') as i32;
}
tokens.push(Tok::Num(x));
}
_ => {
return false;
}
}
}

if let Some(e_pos) = tokens.iter().position(|&x| x == Tok::Op('e')) {
let mut left = vec![];
let mut right = vec![];
for (i, tok) in tokens.into_iter().enumerate() {
match i.cmp(&e_pos) {
Less => {
left.push(tok);
}
Greater => {
right.push(tok);
}
_ => {}
}
}
Self::parse_float(&mut left.into_iter().peekable())
&& Self::parse_int(&mut right.into_iter().peekable())
} else {
Self::parse_float(&mut tokens.into_iter().peekable())
}
}

fn parse_int(it: &mut Peekable<IntoIter<Tok>>) -> bool {
if let Some(Tok::Op('+')) | Some(Tok::Op('-')) = it.peek() {
it.next();
}
Self::parse_uint(it)
}

fn parse_uint(it: &mut Peekable<IntoIter<Tok>>) -> bool {
if let Some(Tok::Num(_)) = it.next() {
it.next().is_none()
} else {
false
}
}

fn parse_ufloat(it: &mut Peekable<IntoIter<Tok>>) -> bool {
match it.peek() {
Some(Tok::Op('.')) => {
it.next();
Self::parse_uint(it)
}
Some(Tok::Num(_)) => {
it.next();
match it.peek() {
Some(Tok::Op('.')) => {
it.next();
if it.peek().is_none() {
true
} else {
Self::parse_uint(it)
}
}
None => true,
_ => false,
}
}
_ => false,
}
}

fn parse_float(it: &mut Peekable<IntoIter<Tok>>) -> bool {
if let Some(Tok::Op('+')) | Some(Tok::Op('-')) = it.peek() {
it.next();
}

Self::parse_ufloat(it)
}
}

#[test]
fn test() {
let s = "0".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = " 0.1 ".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = "abc".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = "1 a".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = "2e10".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = " -90e3".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = " 1e".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = "e3".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = " 6e-1".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = " 99e2.5".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = " 53.5e93".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = " --6 ".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = "-+3".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = "95a54e53".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
let s = ".1".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = "3.".to_string();
let res = true;
assert_eq!(Solution::is_number(s), res);
let s = ". 1".to_string();
let res = false;
assert_eq!(Solution::is_number(s), res);
}
``````