aboutsummaryrefslogtreecommitdiff
path: root/bob/src/lib.rs
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2020-07-13 08:06:08 +0200
committerFederico Igne <git@federicoigne.com>2021-11-03 18:55:08 +0000
commit354a0ed1725ae5408e097164714599b6b1bb66c8 (patch)
treeed907fe660c2c7fae9521bdcb99658b1f3165f1c /bob/src/lib.rs
parent64cc39e6507a611366e1c3ddcf098b77c94a38db (diff)
downloadexercism-354a0ed1725ae5408e097164714599b6b1bb66c8.tar.gz
exercism-354a0ed1725ae5408e097164714599b6b1bb66c8.zip
[rust] Bob
Diffstat (limited to 'bob/src/lib.rs')
-rw-r--r--bob/src/lib.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/bob/src/lib.rs b/bob/src/lib.rs
new file mode 100644
index 0000000..ae18a3d
--- /dev/null
+++ b/bob/src/lib.rs
@@ -0,0 +1,75 @@
1/* The solution consists of an implementation of a simple Finite State Automaton whose states and
2 * transition messages are represented by the `State` and `Message` enums.
3 *
4 * `process(State, Message) -> State` represents the main transition function for the FSA. This
5 * allows us to compute the answer with a single visit of the input string.
6 *
7 * Note: some duplicate states (`QuestLow`, `ElseLow`) are needed in order to remember whether we
8 * have seen a lowercase character already or not. This is probably not the minimal number of
9 * states required to solve the problem.
10 */
11enum State { Nothing, QuestLow, Quest, Yell, YellQ, ElseLow, Else }
12enum Message { Whitespace, Upper, Lower, Symbol, Question }
13
14fn to_message(c: char) -> Message {
15 match c as u8 {
16 0..=32 => Message::Whitespace, // All controll characters are considered whitespace
17 63 => Message::Question,
18 65..=90 => Message::Upper,
19 97..=122 => Message::Lower,
20 _ => Message::Symbol // Anything else (numbers incl.) is a symbol
21 }
22}
23
24fn process(s: State, m: Message) -> State {
25 match s {
26 State::Nothing => match m {
27 Message::Whitespace => s,
28 Message::Upper => State::Yell,
29 Message::Lower => State::ElseLow,
30 Message::Question => State::Quest,
31 Message::Symbol => State::Else
32 },
33 State::QuestLow => match m {
34 Message::Whitespace | Message::Question => s,
35 _ => State::ElseLow
36 },
37 State::Quest => match m {
38 Message::Upper => State::Yell,
39 Message::Lower => State::ElseLow,
40 Message::Symbol => State::Else,
41 _ => s
42 },
43 State::Yell => match m {
44 Message::Lower => State::ElseLow,
45 Message::Question => State::YellQ,
46 _ => s
47 },
48 State::YellQ => match m {
49 Message::Symbol | Message::Upper => State::Yell,
50 Message::Lower => State::ElseLow,
51 _ => s
52 },
53 State::ElseLow => match m {
54 Message::Question => State::QuestLow,
55 _ => s
56 },
57 State::Else => match m {
58 Message::Upper => State::Yell,
59 Message::Lower => State::ElseLow,
60 Message::Question => State::Quest,
61 _ => s
62 }
63 }
64}
65
66pub fn reply(message: &str) -> &str {
67 let state = message.chars().fold(State::Nothing, |s, c| process(s,to_message(c)));
68 match state {
69 State::Nothing => "Fine. Be that way!",
70 State::QuestLow | State::Quest => "Sure.",
71 State::Yell => "Whoa, chill out!",
72 State::YellQ => "Calm down, I know what I'm doing!",
73 _ => "Whatever."
74 }
75}