rustgym/leetcode/
_65_valid_number.rs

1struct Solution;
2
3use std::cmp::Ordering::*;
4use std::iter::Peekable;
5use std::vec::IntoIter;
6
7#[derive(PartialEq, Eq, Clone, Copy)]
8enum Tok {
9    Num(i32),
10    Op(char),
11}
12
13impl Solution {
14    fn is_number(s: String) -> bool {
15        let s = s.trim();
16        let mut it = s.chars().peekable();
17        let mut tokens: Vec<Tok> = vec![];
18        let mut e_count = 0;
19        while let Some(c) = it.next() {
20            match c {
21                ' ' | '-' | '+' | '.' => {
22                    tokens.push(Tok::Op(c));
23                }
24                'e' => {
25                    e_count += 1;
26                    if e_count == 2 {
27                        return false;
28                    }
29                    tokens.push(Tok::Op(c));
30                }
31                '0'..='9' => {
32                    let mut x = (c as u8 - b'0') as i32;
33                    while let Some('0'..='9') = it.peek() {
34                        x *= 10;
35                        x += (it.next().unwrap() as u8 - b'0') as i32;
36                    }
37                    tokens.push(Tok::Num(x));
38                }
39                _ => {
40                    return false;
41                }
42            }
43        }
44
45        if let Some(e_pos) = tokens.iter().position(|&x| x == Tok::Op('e')) {
46            let mut left = vec![];
47            let mut right = vec![];
48            for (i, tok) in tokens.into_iter().enumerate() {
49                match i.cmp(&e_pos) {
50                    Less => {
51                        left.push(tok);
52                    }
53                    Greater => {
54                        right.push(tok);
55                    }
56                    _ => {}
57                }
58            }
59            Self::parse_float(&mut left.into_iter().peekable())
60                && Self::parse_int(&mut right.into_iter().peekable())
61        } else {
62            Self::parse_float(&mut tokens.into_iter().peekable())
63        }
64    }
65
66    fn parse_int(it: &mut Peekable<IntoIter<Tok>>) -> bool {
67        if let Some(Tok::Op('+')) | Some(Tok::Op('-')) = it.peek() {
68            it.next();
69        }
70        Self::parse_uint(it)
71    }
72
73    fn parse_uint(it: &mut Peekable<IntoIter<Tok>>) -> bool {
74        if let Some(Tok::Num(_)) = it.next() {
75            it.next().is_none()
76        } else {
77            false
78        }
79    }
80
81    fn parse_ufloat(it: &mut Peekable<IntoIter<Tok>>) -> bool {
82        match it.peek() {
83            Some(Tok::Op('.')) => {
84                it.next();
85                Self::parse_uint(it)
86            }
87            Some(Tok::Num(_)) => {
88                it.next();
89                match it.peek() {
90                    Some(Tok::Op('.')) => {
91                        it.next();
92                        if it.peek().is_none() {
93                            true
94                        } else {
95                            Self::parse_uint(it)
96                        }
97                    }
98                    None => true,
99                    _ => false,
100                }
101            }
102            _ => false,
103        }
104    }
105
106    fn parse_float(it: &mut Peekable<IntoIter<Tok>>) -> bool {
107        if let Some(Tok::Op('+')) | Some(Tok::Op('-')) = it.peek() {
108            it.next();
109        }
110
111        Self::parse_ufloat(it)
112    }
113}
114
115#[test]
116fn test() {
117    let s = "0".to_string();
118    let res = true;
119    assert_eq!(Solution::is_number(s), res);
120    let s = " 0.1 ".to_string();
121    let res = true;
122    assert_eq!(Solution::is_number(s), res);
123    let s = "abc".to_string();
124    let res = false;
125    assert_eq!(Solution::is_number(s), res);
126    let s = "1 a".to_string();
127    let res = false;
128    assert_eq!(Solution::is_number(s), res);
129    let s = "2e10".to_string();
130    let res = true;
131    assert_eq!(Solution::is_number(s), res);
132    let s = " -90e3".to_string();
133    let res = true;
134    assert_eq!(Solution::is_number(s), res);
135    let s = " 1e".to_string();
136    let res = false;
137    assert_eq!(Solution::is_number(s), res);
138    let s = "e3".to_string();
139    let res = false;
140    assert_eq!(Solution::is_number(s), res);
141    let s = " 6e-1".to_string();
142    let res = true;
143    assert_eq!(Solution::is_number(s), res);
144    let s = " 99e2.5".to_string();
145    let res = false;
146    assert_eq!(Solution::is_number(s), res);
147    let s = " 53.5e93".to_string();
148    let res = true;
149    assert_eq!(Solution::is_number(s), res);
150    let s = " --6 ".to_string();
151    let res = false;
152    assert_eq!(Solution::is_number(s), res);
153    let s = "-+3".to_string();
154    let res = false;
155    assert_eq!(Solution::is_number(s), res);
156    let s = "95a54e53".to_string();
157    let res = false;
158    assert_eq!(Solution::is_number(s), res);
159    let s = ".1".to_string();
160    let res = true;
161    assert_eq!(Solution::is_number(s), res);
162    let s = "3.".to_string();
163    let res = true;
164    assert_eq!(Solution::is_number(s), res);
165    let s = ". 1".to_string();
166    let res = false;
167    assert_eq!(Solution::is_number(s), res);
168}