[Question]
  [
(*Inspired by [this challenge](https://codegolf.stackexchange.com/q/93005/31957)*.)
Let's say we have a string `ABBCBA`. We can say that there is a rise between `A` and `B`, for `B` follows `A`; we can say that there is a run between `B` and `B`, for nothing changes; and finally we can say there is a fall between `C` and `B`. We can draw a graph like this:
```
             A   B   B   C   B   A
Rising:        o       o
Continuing:        o
Falling:                   o   o
```
Without the labels, and minimizing whitespace:
```
o o
 o
   oo
```
This is the expected output for input `ABBCBA`.
You may use any non-whitespace character to replace `o` in the output. Further, each column may optionally have an extra space between them, like so:
```
o   o
  o 
      o o
```
The input will consist of at least three characters. The string will consist entirely of uppercase letters, but you may instead use lowercase letters.
## Test cases
```
TEST CASE
LINE 1
LINE 2
LINE 3
HELLOWORLD
 o oo o
  o
o    o oo
TESTCASE
 oo  o
o  oo o
EXAMINATION
o o o o o
 o o o o o
ZSILENTYOUTH
  o ooo o
oo o   o oo
ABC
oo
ABCBA
oo
  oo
```
  
[Answer]
# Mathematica, ~~93~~ ~~83~~ ~~68~~ 64 bytes
(uses `0`, not `O`)
```
Row[Column@Insert[{,},0,2-#]&/@Sign@Differences@LetterNumber@#]&
```
# Explanation
```
LetterNumber@#
```
Gets the position in the alphabet of each characters of the input.
```
Sign@Differences@
```
Takes the difference between each consecutive elements, and takes the sign (`-1` for negative/falling, `0` for 0/continuing, `1` for positive/rising)
```
Insert[{,},0,2-#]&
```
Inserts a `0` in a list of two `Null`s, in the first position if rising, middle if continuing, and third position if falling.
```
Row[Column@ ... ]
```
Formats the output.
---
If the output could look different from the one in the question, the above code could be shortened to 41 bytes:
```
ListPlot@*Sign@*Differences@*LetterNumber
```
... which creates something like this (for "ABBCBA"):
[![enter image description here](https://i.stack.imgur.com/kkMOs.png)](https://i.stack.imgur.com/kkMOs.png)
[Answer]
# [MATL](http://github.com/lmendo/MATL), ~~15~~, 14 bytes
```
dZSqtQtQv~79*c
```
[Try it online!](http://matl.tryitonline.net/#code=ZFpTcXRRdFF2fjc5KmM&input=J0hFTExPV09STEQn)
Explanation:
They say a picture is worth a thousand words, so [here is a beta online interpreter](https://matl.suever.net/?code=dtD1Y.XxZStD1Y.XxqtD1Y.XxttD1Y.XxQtD1Y.XxttD1Y.XxQtD1Y.Xxv~79%2atD1Y.Xxc&inputs=%27HELLOWORLD%27&version=19.2.0) that shows you the value on top of the stack live as it updates. Note that it's still in beta, so you might need to hit run several times.
So first, we call `dZS`. `d` gives us the difference between each consecutive element, and `ZS` gives us the sign (-1, 0, or 1) of each element. So with 'HELLOWORLD' as input, after the first step we'll have:
```
-1  1  0  1  1 -1  1 -1 -1
```
Now, we just use `q` to decrement this and get:
```
-2  0 -1  0  0 -2  0 -2 -2
```
And then two times we duplicate the top of the stack and increment the array (`tQ`) After this we'll have
```
-2  0 -1  0  0 -2  0 -2 -2
-1  1  0  1  1 -1  1 -1 -1
0   2  1  2  2  0  2  0  0
```
Now all of the '0's are where we want to output a character. So, we join these three arrays into a matrix (`v`), and logically negate it (`~`). Then we multiply every value in the matrix by the ASCII value of 'O', (`79*`) and display it as a string with `c`.
[Answer]
# Haskell, 63 bytes
```
f w=[do(e,y)<-zip w$tail w;max" "['o'|b e y]|b<-[(<),(==),(>)]]
```
Returns a list of three strings, representing the lines of output. Contains no subliminal messages.
dianne saved three bytes by using `do` notation and `max` instead of a list comprehension and `last`.
[Answer]
## [CJam](http://sourceforge.net/projects/cjam/), 19 bytes
```
l2ew{:-g)S3*0t}%zN*
```
Uses `0` instead of `o`.
[Try it online!](http://cjam.tryitonline.net/#code=bDJld3s6LWcpUzMqMHR9JXpOKg&input=SEVMTE9XT1JMRA)
### Explanation
```
l      e# Read input.
2ew    e# Get all pairs of consecutive letters.
{      e# Map this block over the pairs...
  :-   e#   Compute the difference between the two letters.
  g    e#   Signum. Gives -1 for rises, 1 for falls, 0 otherwise.
  )    e#   Increment. Gives 0 for rises, 2 for falls, 1 otherwise. Call this i.
  S3*  e#   Push a string with three spaces.
  0t   e#   Replace the i'th space (zero-based) with a zero.
}%
z      e# Transpose.
N*     e# Join with linefeeds.
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 11 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
OIṠ“ o ”ṙZY
```
[Try it online!](http://jelly.tryitonline.net/#code=T0nhuaDigJwgbyDigJ3huZlaWQ&input=&args=QUJCQ0JB) or [verify all test cases](http://jelly.tryitonline.net/#code=T0nhuaDigJwgbyDigJ3huZlaWQrhuLLCtcW8w4figqxZ4oKsauKAnMK2wrY&input=&args=SEVMTE9XT1JMRCBURVNUQ0FTRSBFWEFNSU5BVElPTiBaU0lMRU5UWU9VVEggQUJDIEFCQ0JB).
### How it works
```
OIṠ“ o ”ṙZY  Main link. Argument: s (string)
O            Ordinal; replace all characters with their code points.
 I           Increments; compute the differences of consecutive code points.
  Ṡ          Sign function.
   “ o ”ṙ    Rotate that string -1, 0, or 1 unit(s) to the left.
         Z   Zip; transpose rows and columns.
          Y  Join, separating by linefeeds.
```
[Answer]
# Python 2, ~~76~~ 71 bytes
```
lambda s:[''.join(' o'[cmp(*x)==n]for x in zip(s,s[1:]))for n in-1,0,1]
```
*Thanks to @xnor for notifying me that returning a list of strings is allowed.*
Test it on [Ideone](http://ideone.com/DqNwZ0).
[Answer]
## JavaScript (ES6), ~~96~~ ~~95~~ ~~89~~ ~~87~~ 82 bytes
*2 bytes saved by using `0` instead of `o`, as suggested by Conor O'Brien*  
*~~2~~ 6 bytes saved thanks to ETHproductions*
```
let f =
s=>[1,0,-1].map(k=>s.replace(/./g,(c,i)=>i--?(c>s[i])-(c<s[i])-k&&' ':'')).join`
`
console.log(f("HELLOWORLD"));
console.log(f("EXAMINATION"));
```
[Answer]
# Perl, 47 bytes
Includes +1 for `-p`
Give input on STDIN:
```
bumpy.pl <<< ABBCBA
```
`bumpy.pl`:
```
#!/usr/bin/perl -p
$_ x=3;s%.%/\G(.)(.)/?$2cmp$1^$.&&$":--$.>0%eg
```
[Answer]
# MATL, ~~16~~ 14 Bytes
```
dZSqq_tn:79Z?c
```
[Try it online!](http://matl.tryitonline.net/#code=ZFpTcXFfdG46NzlaP2M&input=J0hFTExPV09STEQn)
This grew out of a discussion of [DJMCMahem's answer](https://codegolf.stackexchange.com/a/94440/42247). Even though this answer is ~~2 characters longer~~ the same length, the method is somewhat different so it may be of independent interest.
*Thanks to Luis Mendo for a suggestion saving 2 bytes (see comments)*
**Explanation:**
'dZS' gets a vector where each entry is the sign of the differences between sucessive characters, then 'qq\_' decrements each entry by two and flips the sign, so now if the character increases it is 1, if it stays the same 2, and if it decreases 3. For example,
```
dZSqq_ applied to 'HELLOWORLD' creates the vector [3 1 2 1 1 3 1 3 3]
```
Next, 't' makes a copy of the previous vector on the stack, then 'n:' places the vector [1,2,3,4,...] on the stack as well. Then '79' places the value 79 on the stack. The value 79 is chosen because it is the number for the unicode character 'o', which will be our output later. (Thanks to Luis Mendo for the idea to put the value 79 here rather than later)
```
tn:79 applied to [3 1 2 1 1 3 1 3 3] creates the following items:
[3 1 2 1 1 3 1 3 3]   <-- first item on the stack
[1 2 3 4 5 6 7 8 9]   <-- second item on the stack
79                    <-- third item on the stack
```
At this point we have precisely the row indices, column indices, and nonzero value of a sparse matrix that has the value 79 wherever we want the output character, and 0 wherever we want to output whitespace. We take these three items off the stack and create this sparse matrix with MATL's sparse matrix command 'Z?'. That is,
```
dZSqq_tn:79 Z? applied to 'HELLOWORLD' outputs the following:
[0  79 0  79 79 0  79 0  0 ]
[0  0  79 0  0  0  0  0  0 ]   <-- 3-by-n sparse matrix
[79 0  0  0  0  79 0  79 79]
```
All that is left is to convert the matrix from numbers to unicode characters, which is done by the command 'c'. The 79's become 'o', and the 0's become spaces:
```
dZSqq_tn:79Z?c applied to 'HELLOWORLD' outputs:
[  o   o o   o    ]
[    o            ]   <-- 3-by-n sparse matrix of characters.
[o         o   o o]
```
The resulting matrix of chars is then implicitly displayed.
[Answer]
# PHP, 95 Bytes
```
for($b[1]=$b[0]=$b[-1]=" ";($s=$argv[1])[++$i];)$b[$s[$i-1]<=>$s[$i]][$i]=8;echo join("\n",$b);
```
1.Create an array of strings with the index -1 to 1 alternative `$b=array_fill(-1,3," ");`
2.Fill the strings dependent by the spaceship operator and position of the input
3.Output join the array with a new line
First Way 111 Bytes
```
for($o=" ";$i<$l=strlen($s=$argv[1])-1;)$o[$l*(1+($s[$i]<=>$s[$i+1]))+$i++]=8;echo join("\n",str_split($o,$l));
```
Use the spaceship operator `<=>` [spaceship operator](http://php.net/manual/en/language.operators.comparison.php)
[Answer]
# JavaScript (ES6), 81 bytes
```
s=>[s,s,s].map(f=([c,...s],n)=>(p=s[0])?((c<p)-(c>p)+n-1&&" ")+f(s,n):"").join`
`
```
Written from scratch, though it was heavily inspired by [@Arnauld's answer](https://codegolf.stackexchange.com/a/94438/42545). Uses recursion to calculate the contents of each row.
[Answer]
# Ruby, ~~66~~ 64 bytes
```
->s{(-1..1).map{|n|s.gsub(/.(?=(.))/){"o  "[n+($1<=>$&)]}.chop}}
```
See it on eval.in: <https://eval.in/649503>
[Answer]
# Java 7, ~~158~~ 156 bytes
```
String c(char[]z){String a,b,c=a=b="";for(char i=1,q=z[0],o=79,s=32,x;i<z.length;a+=(x=z[i])>q?o:s,b+=x==q?o:s,c+=x<q?o:s,q=z[i++]);return a+"\n"+b+"\n"+c;}
```
2 bytes saved thanks to *@Frozn*.
**Ungolfed & test cases:**
[Try it here.](https://ideone.com/2ksqN9)
```
class M{
  static String c(char[] z){
    String a,
           b,
           c = a = b = "";
    for(char i = 1,
             q = z[0],
             o = 79,
             s = 32,
             x; i < z.length; a += (x = z[i]) > q
                                     ? o
                                     : s,
                              b += x == q
                                     ? o
                                     : s,
                              c += x < q
                                     ? o
                                     : s,
                              q = z[i++]);
    return a + "\n" + b + "\n" + c;
  }
  public static void main(String[] a){
    print("HELLOWORLD");
    print("TESTCASE");
    print("EXAMINATION");
    print("ZSILENTYOUTH");
    print("ABC");
    print("ABCBA");
    print("ABBCBA");
    print("UVVWVVUVVWVVUVVW");
  }
  static void print(String s){
    System.out.println(c(s.toCharArray()));
    System.out.println("-------------------------");
  }
}
```
**Output:**
```
 O OO O  
  O      
O    O OO
-------------------------
 OO  O 
       
O  OO O
-------------------------
O O O O O 
          
 O O O O O
-------------------------
  O OOO O  
           
OO O   O OO
-------------------------
OO
  
  
-------------------------
OO  
    
  OO
-------------------------
O O  
 O   
   OO
-------------------------
O O   O O   O O
 O  O  O  O  O 
   O O   O O   
-------------------------
```
[Answer]
# [Clora](https://github.com/opsxcq/cloralang) (20 bytes)
`<IN?o ;=IN?o ;>IN?o`
Explanation:
There are 3 Clora programs, one for each output line.
### First program, `<IN?o`
Check if current input char `I` is smaller `<` than the next char `N`. Save the result in a global flag. Check the flag result `?` and if is true, output `o`, else a blank space (yes, there is a blank space there.
All other programs, follow the same rule and are separated by `;`, every program is executed and receives the input as argument.
You can test it by yourself including clora.js and executing it with
```
(function() {
  var x = new Clora('<IN?o ;=IN?o ;>IN?o ');
  x.execute('EXAMINATION', function(r) {
    console.log(r)
  })
})();
```
[Answer]
# Pyth, 21 bytes
```
jCmX*3\ h._d0-M.:CMz2
```
A program that takes input of an unquoted string on STDIN and prints the result.
This uses a similar idea to @MartinEnder's [CJam answer](https://codegolf.stackexchange.com/a/94439/55526).
[Try it online](https://pyth.herokuapp.com/?code=jCmX%2a3%5C+h._d0-M.%3ACMz2&debug=0) or [Verify all test cases](https://pyth.herokuapp.com/?code=zjCmX%2a3%5C+h._d0-M.%3ACMz2&test_suite=1&test_suite_input=HELLOWORLD%0ATESTCASE%0AEXAMINATION%0AZSILENTYOUTH%0AABC%0AABCBA&debug=0).
**How it works**
```
jCmX*3\ h._d0-M.:CMz2  Program. Input: z
                 CMz   Map ordinal over z, yielding the code-points of the characters
               .:   2  Yield all length-2 sublists of that
             -M        Map subtraction over that
  m                    Map the following over that with variable d:
         ._d            Yield the sign of d
        h               Increment that (i)
    *3\                 Yield string literal of 3 spaces, "   "
   X        0           Replace the space at index i with 0
 C                     Transpose that
j                      Join that on newlines
                       Implicitly print
```
[Answer]
# PHP 7, ~~81~~ ~~80~~ 77 bytes
Note: uses Windows-1252 encoding
```
for($x=2;~$x--;print~õ)for($a=$argn;$c=$a[$$x+1];)echo$c<=>$a[$$x++]^$x?~ß:o;
```
Run like this:
```
echo HELLOWORLD | php -nR 'for($x=2;~$x--;print"\n")for($a=$argn;$c=$a[$$x+1];)echo$c<=>$a[$$x++]^$x?" ":o;';echo
```
# Explanation
Iterates over lines (numbered `1`, `0`, `-1`). Then iterates over the input string for every line. When the result of spaceship comparison equals the line number, output an `o`, otherwise, output a space. After every line, print a newline.
# Tweaks
* Stop iterating when `$x` is `-1`, which we can find by binary negation (result `0`). Saves a byte compared to adding `1` (or 2 with pre-increment).
* Saved 3 bytes by using `$argn`
[Answer]
**Lua** 326 303 bytes
 tl=0 s=io.read() o1,o2,o3="","","" t={} for i=1,#s do t[i]=s:sub(i,i) tl=tl+1 end for v=1,tl-1 do if t[v]t[v+1] then o1=o1.." " o2=o2.." " o3=o3.."o" end end print(o1.."\n"..o2.."\n"..o3)
An ungolfed version
```
tl = 0 --set the tables length to 0
s = io.read() --Get the string from input
o1,o2,o3="","","" --Set the 3 output rows to empty strings
t = {} --Make a table for the string to be sent into
for i = 1, #s do --Loop from 1 to the length of the string
    t[i] = s:sub(i, i) --Set the I-th term in the table to the I-th character in the string
    tl = tl+1 --Add 1 to the table length
end --End the loop
for v=1,tl-1, 1 do --Loop from 1 to the tables length - 1, incrementing by 1
    if t[v] < t[v+1] then --Lua supports greater than less than and equals to with charactes, so this if statement detects if the string is rising
        o1=o1.."o" --Adds an o to the end of the first line of output
        o2=o2.." " --Adds a space to the second line
        o3=o3.." " --Adds a space to the third line
    elseif t[v] == t[v+1] then --Detects if the string is continuing
        o1=o1.." " --Adds a space to the first line
        o2=o2.."o" --Adds an o to the second line
        o3=o3.." " --Adds a space to the third line
    elseif t[v] > t[v+1] then --Detects if string is falling
        o1=o1.." " --Adds a space to the first line
        o2=o2.." " --Adds a space to the second line
        o3=o3.."o" --Adds an o to the third line
    end --Ends the if statement
end --Ends the loop
print(o1.."\n"..o2.."\n"..o3) --Prints the output
```
[Answer]
## R, 114 bytes
A non-competing R answer.
```
v=y=z=rep(" ",length(x<-diff(utf8ToInt(scan(,"")))));v[x>0]="#";y[x==0]="#";z[x<0]="#";cat(v,"\n",y,"\n",z,sep="")
```
### Explanation
1. Read input from command line and convert into ascii decimal vector
2. Take 1st difference and create an 3x vectors of the same length with white spaces
3. Then replace the white space vectors with `#` if the differences are `>0`, `==0` or `<0`.
4. Coerce the vectors and print them separated by newlines
[Answer]
# [Japt](https://github.com/ETHproductions/japt) [`-R`](https://codegolf.meta.stackexchange.com/a/14339/), 13 [bytes](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)
Takes input as a character array. The first 3 bytes could be removed by taking input as an array of codepoints. Uses `"` instead of `o`.
```
mc äÎm!éQû3)Õ
```
[Try it](https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&flags=LVI&header=cQ&code=bWMg5M5tIelR%2bzMp1Q&input=IkFCQkNCQSI)
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 8 bytes
```
C¯±››×↲§
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCJDwq/CseKAuuKAusOX4oaywqciLCIiLCJaU0lMRU5UWU9VVEgiXQ==)
The power of that one built-in I added 3 years ago because I thought it was a good idea to have something to vertically join a list of lists. Can be 7 bytes with the L flag.
## Explained
```
C¯±››×↲§
C¯        # Convert each character to ascii value and get pairwise differences
  ±       # Sign of each
   ››     # + 2 (the ⇧ element doesn't vectorise it's numeric overload)
     ×↲   # left adjust the string "*" by each number in ^
       §  # "vertical join" - Transpose (filling with spaces) and then join on newlines
```
]