Ruby, 57 48 bytes
Expects input to be all uppercase.
->s{!s.gsub(/.(?=(.)(.))/){($&<$1)^($1<$2)}[?f]}
See it on repl.it: https://repl.it/D7SB
Explanation
The regular expression /.(?=(.)(.))/
matches each character that's followed by two more characters. (?=...)
is a positive lookahead, meaning we match the subsequent two characters but don't "consume" them as part of the match. Inside the curly braces, $&
is the matched text—the first character of the three—and $1
and $2
are the captured characters inside the lookahead. In other words, if the string is "BUMPY"
, it will first match "B"
(and put it in $&
) and capture "U"
and "M"
(and put them in $1
and $2
). Next it will match "U"
and capture "M"
and "P"
, and so on.
Inside the block we check if the first pair of characters ($&
and $1
) is a rise and the second ($1
and $2
) is a fall or vice versa, much like most of the other answers. This ^
expression returns true
or false
, which gets converted to a string and inserted in place of the match. As a result, our example "BUMPY"
becomes this:
`"truetruefalsePY"`"truetruefalsePY"
Since we know the input is all uppercase, we know "f"
will only occur as part of "false"
and !result[?f]
gives us our answer.