/* The solution consists of an implementation of a simple Finite State Automaton whose states and * transition messages are represented by the `State` and `Message` enums. * * `process(State, Message) -> State` represents the main transition function for the FSA. This * allows us to compute the answer with a single visit of the input string. * * Note: some duplicate states (`QuestLow`, `ElseLow`) are needed in order to remember whether we * have seen a lowercase character already or not. This is probably not the minimal number of * states required to solve the problem. */ enum State { Nothing, QuestLow, Quest, Yell, YellQ, ElseLow, Else } enum Message { Whitespace, Upper, Lower, Symbol, Question } fn to_message(c: char) -> Message { match c as u8 { 0..=32 => Message::Whitespace, // All controll characters are considered whitespace 63 => Message::Question, 65..=90 => Message::Upper, 97..=122 => Message::Lower, _ => Message::Symbol // Anything else (numbers incl.) is a symbol } } fn process(s: State, m: Message) -> State { match s { State::Nothing => match m { Message::Whitespace => s, Message::Upper => State::Yell, Message::Lower => State::ElseLow, Message::Question => State::Quest, Message::Symbol => State::Else }, State::QuestLow => match m { Message::Whitespace | Message::Question => s, _ => State::ElseLow }, State::Quest => match m { Message::Upper => State::Yell, Message::Lower => State::ElseLow, Message::Symbol => State::Else, _ => s }, State::Yell => match m { Message::Lower => State::ElseLow, Message::Question => State::YellQ, _ => s }, State::YellQ => match m { Message::Symbol | Message::Upper => State::Yell, Message::Lower => State::ElseLow, _ => s }, State::ElseLow => match m { Message::Question => State::QuestLow, _ => s }, State::Else => match m { Message::Upper => State::Yell, Message::Lower => State::ElseLow, Message::Question => State::Quest, _ => s } } } pub fn reply(message: &str) -> &str { let state = message.chars().fold(State::Nothing, |s, c| process(s,to_message(c))); match state { State::Nothing => "Fine. Be that way!", State::QuestLow | State::Quest => "Sure.", State::Yell => "Whoa, chill out!", State::YellQ => "Calm down, I know what I'm doing!", _ => "Whatever." } }