-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.rs
77 lines (66 loc) · 1.93 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#[derive(Debug)]
enum Operations {
Add,
Sub,
Mul,
Div,
Exp,
Num(i32),
}
impl Operations {
fn try_get_num(&self) -> Option<i32> {
if let Operations::Num(num) = self {
return Some(*num);
}
None
}
}
fn word_to_operation(word: &str) -> Option<Operations> {
Some(match word {
"plus" => Operations::Add,
"minus" => Operations::Sub,
"multiplied" => Operations::Mul,
"divided" => Operations::Div,
"raised" => Operations::Exp,
_ => Operations::Num({
let word = word.strip_suffix("nd").unwrap_or(word);
word.strip_suffix("th")
.unwrap_or(word)
.parse::<i32>()
.ok()?
}),
})
}
fn parse(command: &str) -> Option<Vec<Operations>> {
let command = command.strip_prefix("What is ")?.strip_suffix('?')?;
command
.to_lowercase()
.split_whitespace()
.filter(|chunk| chunk != &"by" && chunk != &"to" && chunk != &"the" && chunk != &"power")
.map(word_to_operation)
.collect::<Option<Vec<Operations>>>()
}
fn eval(operations: &[Operations]) -> Option<i32> {
let mut result = operations.first()?.try_get_num()?;
// Check that we have enough tokens to perform all operations.
if operations.len() % 2 != 1 {
return None;
}
for chunk in operations[1..].chunks(2) {
let operation = &chunk[0];
let operand = chunk[1].try_get_num()?;
match operation {
Operations::Add => result += operand,
Operations::Sub => result -= operand,
Operations::Mul => result *= operand,
Operations::Div => result /= operand,
Operations::Exp => result = result.pow(operand as u32),
_ => return None,
};
}
Some(result)
}
pub fn answer(command: &str) -> Option<i32> {
let operations = parse(command)?;
eval(&operations)
}