diff options
| author | Federico Igne <git@federicoigne.com> | 2020-07-13 08:06:08 +0200 |
|---|---|---|
| committer | Federico Igne <git@federicoigne.com> | 2021-11-03 18:55:08 +0000 |
| commit | 354a0ed1725ae5408e097164714599b6b1bb66c8 (patch) | |
| tree | ed907fe660c2c7fae9521bdcb99658b1f3165f1c /bob/src | |
| parent | 64cc39e6507a611366e1c3ddcf098b77c94a38db (diff) | |
| download | exercism-354a0ed1725ae5408e097164714599b6b1bb66c8.tar.gz exercism-354a0ed1725ae5408e097164714599b6b1bb66c8.zip | |
[rust] Bob
Diffstat (limited to 'bob/src')
| -rw-r--r-- | bob/src/lib.rs | 75 |
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 | */ | ||
| 11 | enum State { Nothing, QuestLow, Quest, Yell, YellQ, ElseLow, Else } | ||
| 12 | enum Message { Whitespace, Upper, Lower, Symbol, Question } | ||
| 13 | |||
| 14 | fn 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 | |||
| 24 | fn 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 | |||
| 66 | pub 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 | } | ||
