ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# hyphenrf's solution

## to Bob in the OCaml Track

Published at May 02 2020 · 0 comments
Instructions
Test suite
Solution

Bob is a lackadaisical teenager. In conversation, his responses are very limited.

Bob answers 'Sure.' if you ask him a question, such as "How are you?".

He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).

He answers 'Calm down, I know what I'm doing!' if you yell a question at him.

He says 'Fine. Be that way!' if you address him without actually saying anything.

He answers 'Whatever.' to anything else.

Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.

## Getting Started

1. For library documentation, follow Useful OCaml resources.

## Running Tests

A `Makefile` is provided with a default target to compile your solution and run the tests. At the command line, type:

``````make
``````

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

## Feedback, Issues, Pull Requests

The exercism/ocaml repository on GitHub is the home for all of the Ocaml exercises.

If you have feedback about an exercise, or want to help implementing a new one, head over there and create an issue or submit a PR. We welcome new contributors!

## Source

Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. http://pine.fm/LearnToProgram/?Chapter=06

### test.ml

``````open OUnit2
open Bob

let ae exp got _test_ctxt = assert_equal ~printer:(fun x -> x) exp got

let tests = [
"stating something" >::
ae "Whatever." (response_for "Tom-ay-to, tom-aaaah-to.");
"shouting" >::
ae "Whoa, chill out!" (response_for "WATCH OUT!");
"shouting gibberish" >::
ae "Whoa, chill out!" (response_for "FCECDFCAAB");
"asking a question" >::
ae "Sure." (response_for "Does this cryogenic chamber make me look fat?");
"asking a numeric question" >::
ae "Sure." (response_for "You are, what, like 15?");
ae "Sure." (response_for "fffbbcbeab?");
"talking forcefully" >::
ae "Whatever." (response_for "Let's go make out behind the gym!");
"using acronyms in regular speech" >::
ae "Whatever." (response_for "It's OK if you don't want to go to the DMV.");
"forceful question" >::
ae "Calm down, I know what I'm doing!" (response_for "WHAT THE HELL WERE YOU THINKING?");
"shouting numbers" >::
ae "Whoa, chill out!" (response_for "1, 2, 3 GO!");
"no letters" >::
ae "Whatever." (response_for "1, 2, 3");
"question with no letters" >::
ae "Sure." (response_for "4?");
"shouting with special characters" >::
ae "Whoa, chill out!" (response_for "ZOMG THE %^*@#\$(*^ ZOMBIES ARE COMING!!11!!1!");
"shouting with no exclamation mark" >::
ae "Whoa, chill out!" (response_for "I HATE THE DMV");
"statement containing question mark" >::
ae "Whatever." (response_for "Ending with ? means a question.");
"non-letters with question" >::
ae "Sure." (response_for ":) ?");
"prattling on" >::
ae "Sure." (response_for "Wait! Hang on. Are you going to be OK?");
"silence" >::
ae "Fine. Be that way!" (response_for "");
"prolonged silence" >::
ae "Fine. Be that way!" (response_for "          ");
"alternate silence" >::
ae "Fine. Be that way!" (response_for "\t\t\t\t\t\t\t\t\t\t");
"multiple line question" >::
ae "Whatever." (response_for "\nDoes this cryogenic chamber make me look fat?\nNo.");
"starting with whitespace" >::
ae "Whatever." (response_for "         hmmmmmmm...");
"ending with whitespace" >::
ae "Sure." (response_for "Okay if like my  spacebar  quite a bit?   ");
"other whitespace" >::
ae "Fine. Be that way!" (response_for "\n\r \t");
"non-question ending with whitespace" >::
ae "Whatever." (response_for "This is a statement ending with whitespace      ");
]

let () =
run_test_tt_main ("bob tests" >::: tests)``````
``````let is_lower = function 'a'..'z' -> true | _ -> false
let is_upper = function 'A'..'Z' -> true | _ -> false

let rec string_any ?(i=0) (fn: char -> bool) str =
if i = String.length str then false
else fn str.[i] || string_any ~i:(i+1) fn str

let response_for s = match String.trim s with
| "" -> "Fine. Be that way!"
| cs ->
let cs_length  = String.length cs         in
let is_asking  = cs.[cs_length - 1] = '?' in
let is_yelling =
string_any is_upper cs && not (string_any is_lower cs)
in
match is_asking, is_yelling with
| false,     false      -> "Whatever."
| false,     true       -> "Whoa, chill out!"
| true,      false      -> "Sure."
| true,      true       -> "Calm down, I know what I'm doing!"``````