text:
How tall are the monoliths?
Here is an example of an input of monoliths. There are 4 in this example.
  _
 | |        _
 | |  _    | |
 | | | |   | |     _
_| |_| |___| |____| |_

The first monolith is 4 units high, the second is 2, the third is 3, and the last is 1.
The task
Your program should output the heights of the monoliths in order from left to right. The output format can be in any sort of list or array.
Notes

The input can be taken as any dimensional string, list of strings, or list of characters.
This is code-golf, so lowest bytes wins.
You are to assume that monoliths always have the same width, and are always at least 1 _ away from another.
They can come in any height, and in any quantity.

I/O
  _
 | |        _
 | |  _    | |
 | | | |   | |     _
_| |_| |___| |____| |_   >> [4,2,3,1]

           _
          | |
  _       | |
 | |  _   | |  _
_| |_| |__| |_| |_   >> [2,1,4,1]

 _   _   _
| |_| |_| |_____   >> [1,1,1]

____________________   >> undefined behavior

 _
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |   >> [11]

     _       _       _       _       _
 _  | |  _  | |  _  | |  _  | |  _  | |
| |_| |_| |_| |_| |_| |_| |_| |_| |_| |  >> [1,2,1,2,1,2,1,2,1,2]

May I assume the input is right padded with spaces?

Is your [10] monolith not [11] ?

Wouldn't the undefined one just be an empty array?

@isaacg yes, that would be okay

@SolomonUcko technically yes, though to make it simpler for all languages I decided to not have them deal with it.

Ok. So basically, you can implement it like that, but don't have to?

@SolomonUcko Yes, exactly. Primarily because some algorithms might fail at that test, and have to create more code just for that exception. Which drives the average byte count up (which is no fun).

I see, that makes sense.

Bit late to ask, but does the spec guarantee that all monoliths have a single _ on top as in the test cases, or merely that they always have the same width per input?

Jelly, (8?) 9 bytes
Ỵ=”|Sḟ0m2

A monadic link accepting a list of characters as specified and returning a list of integers.
Note: 8 bytes if a list of strings, one per line, was really intended to be an allowed input format - just remove the Ỵ.
Try it online!
How?
Ỵ=”|Sḟ0m2 - Link: list of characters, s
Ỵ         - split at newlines
  ”|      - literal '|'
 =        - equals (vectorises)
    S     - sum (vectorises, hence counts the number of '|' in every column)
     ḟ0   - filter out zeros (only keep the results from the sides of the towers)
       m2 - modulo index with 2 (keep only the left side measurements)

I don't know, but is this okay?

@V.Courtois I don't see why not, since we'll probably never get such input.

Okay, it's because I saw that some other answers take it in count

@V.Courtois the input you suggested does not fit the specification, similarly adding underscores in the sky, part-way up monoliths, or underground would probably break many other submissions.

Down-voter - would you care to explain your reasons?

@JonathanAllan just noticed ^^

Jelly, 11 bytes
ỴṚZi€”_ỊÐḟ’

Try it online!

Wow, you answered that fast.

@Graviton Hehe one should always have this page open somewhere. ;)

Explanation, please!

JavaScript (ES6), 79 78 77 bytes
-1 byte thanks to @Shaggy
-1 byte thanks to @l4m2
a=>a.map((b,i)=>b.replace(/_/g,(_,j)=>o[j]=a.length+~i),o=[])&&o.filter(x=>x)

Takes input as an array of strings.
Test Snippet

f=
a=>a.map((b,i)=>b.replace(/_/g,(_,j)=>o[j]=a.length+~i),o=[])&&o.filter(x=>x)
I.value="           _\n          | |\n  _       | |\n | |  _   | |  _\n_| |_| |__| |_| |_"
<textarea id=I rows=7 cols=30></textarea><br><button onclick="O.value=`[${f(I.value.split`\n`).join`, `}]`">Run</button> <input id=O disabled>

78 bytes: a=>a.map((x,y)=>x.replace(/_/g,(_,z)=>c[z]=a.length-y-1),c=[])&&c.filter(n=>n)

@Shaggy Nice, I totally didn't think of using replace. Thanks!

-i-1 => +~i

@l4m2 Updated, thanks!

C++, 171 169 bytes
#import<vector>
#import<iostream>
int f(std::vector<std::string>s){for(int a,j,i=0,k=s.size()-1;a=s[k][i];++i)if(a==32){for(j=0;(a=s[k-++j][i])-95;);std::cout<<j<<" ";}}

Try it online!
C++ (GCC), 150 bytes
Thanks to @aschepler!
#import<vector>
#import<iostream>
int f(auto s){for(int a,j,i=0,k=s.size()-1;a=s[k][i];++i)if(a==32){for(j=0;(a=s[k-++j][i])-95;);std::cout<<j<<" ";}}

Try it online!

If using g++, you can use the non-standard f(auto s) and specify it takes any random-access container of random-access containers of char.

Dyalog APL, 29 bytes
{0~⍨↑+/(⌈/⍴¨⍵)↑¨(⍳≢⍵)×⌽⍵='_'}

Run with ⎕IO←0.
Try it online!
How?
⌽⍵='_' - where ⍵ is '_', top lines first
×- multiply by ...
(⍳≢⍵) - the range of ⍵ (zero indexed)
↑¨ - for each line, pad with zeros by ...
(⌈/⍴¨⍵) - the maximal length
↑+/ - sum the rows zipped and flatten
0~⍨ - removes zeros

05AB1E, 11 bytes
|Rζ'_δkJ®0‚K

Try it online!
ζ has been replaced by .Bø on TIO since it hasn't been pulled there yet.

Java 8 - 229 Bytes 213 Bytes
s->{Map<Integer,Integer> m=new TreeMap();String[] l=s.split("\n");for(int i=0,j=-1;i<l.length-1;++i){s=l[i];while((j=s.indexOf("_",j+1))>=0){m.put(j,i);}}for(int i:m.values()){System.out.print(l.length-i-1+",");}}

Try it online!
Ungolfed:
public static void foo(String input)
{
    Map<Integer, Integer> map = new TreeMap(); // Raw types!!
    String[] lines = input.split("\n");

    for (int i = 0, j = -1; i < lines.length - 1; ++i)
    {
        input = lines[i];

        while ((j = input.indexOf("_", j + 1)) >= 0)
        {
            map.put(j, i);
        }
    }

    for(int i:map.values())
    {
        System.out.print(lines.length - i - 1 + ",");
    }
}

Woo, first post. Any help improving it would be great. I know I can get rid of that indexOf written twice. Knew it! I toyed with the idea of changing the types in the map from Integer to Long but I think that's a dead end.

I know there is a much, much better Java 8 solution already, but that takes char[][] as input which I think is easier to work with in this case than String.

You haven't included the imports (they're required for Java answers). Don't use a Map but an int[] (maybe initialized to new int[99]?).  No need for a space after String[] l: String[]l works the same and is shorter. Use println(l.length-i-1) instead of println(l.length-i-1+","). Don't initialize j: just write: ,j;. If you use a int[] as suggested earlier, declare like this: int m[]=new int[99],i=0,j; and remove the declaration from the for-loop.

OlivierGrégoire is indeed right about the required import for Map. As for some golfing of your current code with Map, you can change it to this: import java.util.*;s->{Map m=new TreeMap();String[]a=s.split("\n");int l=a.length-1,j=-1,i=j;for(;++i<l;)for(s=a[i];(j=s.indexOf("_",j+1))>=0;m.put(j,i));for(Object o:m.values())System.out.println(l-(int)o);}. No need for the <Integer,Integer> of the map when you can cast to int; a.length-1 is used twice, so you can use a variable for it; by putting everything inside for-loops you can get rid of all brackets. Oh, and welcome to PPCG! :)

@KevinCruijssen Thanks! Converting the contents of that first for loop to a bodyless for loop was inspiring! Super clever.

@Michael You're welcome. :) Oh, and if you haven't seen it yet: Tips for golfing in Java and Tips for golfing in  might be interesting to read through. Helped me a lot when I first started (and still does sometimes).

Uiua, 11 bytes
⊢⇌⍉⊚⍉⇌⌕"_ "

Try it!
Explanation:
      ⌕"_ " # Mark the locations of the tower tops
    ⍉⇌      # Rotate the array 90° clockwise
   ⊚        # Get the coordinates of the marked (non-zero) elements, going top to bottom
⊢⇌⍉         # Take the second column of the coordinates

(here's how the array looks before and after ⌕"_ ")
["  _                      "
 " | |        _            "
 " | |  _    | |           "
 " | | | |   | |     _   _ "
 "_| |_| |___| |____| |_| |"]

[[0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Welcome to code golf SE teeth eator

Retina, 48 38 bytes
^
¶
{`(¶.*)*¶_(.*¶)+
$#2 $&
}`¶.
¶
G`.

Try it online! Link includes first example. Explanation: A line is prefixed which will collect the results. As each column is repeatedly deleted in turn, those that contains a _ above ground level have the the number of remaining lines in the column counted. Finally the now blank lines are deleted. Edit: Saved 10 bytes thanks to inspriation from @FryAmTheEggman.

Nice, I had a slightly shorter solution, but it wouldn't work on large inputs since it would mess up my ability to sort them. Going column by column is a nice way to avoid that!

@FryAmTheEggman I switched to your method of counting the lines using the _s which makes much more sense than trying to use the |s, thanks!

@FryAmTheEggman Doesn't fix the problem, but your sorting stage can be simplified by dropping the lookbehind and sorting by $.%\``, and the final stage can be !`\d+`. And if you change the first stage to a lookahead, you don't need to loop.

@FryAmTheEggman And here is a fix to your approach, but it ends up at 46 bytes.

@MartinEnder 45 perhaps? Try it online!

Ah yeah, nice idea. Still too long unfortunately :)

If we can assume that the input is padded to a rectangle, here is yet another approach that transposes the input (41 bytes): https://tio.run/##K0otycxL/P9fhevQNhU91QQVLVsuf2WV4gQ9LhCXKzgh3t6WKx7EUedSTIhJ0f7/X0EhXgEL4FKoAUIIiMcUBwnBGQhxsBCcAZLkigcywRiVAQA

@MartinEnder I shall have to remember that transposition trick!

@Neil it's much easier for square inputs, because the linefeeds can remain in the correct position, so you only need that sorting stage and you can drop the s from it.

Python 2, 75 bytes
lambda s:[x.index('_')for x in map(None,*s.split('\n')[::-1])if'_'in x[1:]]

Try it online!

Japt, 11 bytes
z ·mb'_ fw0

Test it online!
Explanation
z ·mb'_ fw0   : Implicit input
z             : Rotate the input clockwise. This puts the "floor" against the left side.
  ·           : Split the 2D string into lines.
   m          : Replace each column (now row) X with
    b'_       :   the index of '_' in X (0-indexed). This gives us the output list, with
              :   0's and -1's mixed in representing the columns that are not monoliths.
        f     : Take only the items X where
         w0   :   max(X, 0) is truthy. Since 0 is falsy, this removes anything <= 0.
              : Implicit: output result of last expression

APL (Dyalog), 14 bytes
0~⍨⍳∘≢+.×'_'=⊖

with ⎕IO←0
Try it online!

This function train equivalent to {((⍳≢⍵)+.×('_'=⊖⍵))~0}

PowerShell, 133 bytes
param($s)$r=,0*($l=($s=$s-replace'\| \|',' 1 ')[0].Length);1..$s.Count|%{$z=$_-1;0..($l-1)|%{$r[$_]+=(''+$s[$z][$_]-as[int])}};$r-ne0

Looks like it's not very competitive; it does a regex replace to turn the towers into columns of 1, makes an array of 0 the length of the input string, then steps through the lines adding up the 1s.
Tests ready to run:
$s1 = @'
  _
 | |        _
 | |  _    | |
 | | | |   | |     _
_| |_| |___| |____| |_
'@-split"`r?`n"

$s2 = @'
 _
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
'@-split"`r?`n"

$s3 = @'
           _
          | |
  _       | |
 | |  _   | |  _
_| |_| |__| |_| |_
'@-split"`r?`n"

$s4 = @'
 _   _   _
| |_| |_| |_____
'@-split"`r?`n"

$s5 = @'
     _       _       _       _       _
 _  | |  _  | |  _  | |  _  | |  _  | |
| |_| |_| |_| |_| |_| |_| |_| |_| |_| |
'@-split"`r?`n"

Java 8, 133 117 116 114 bytes
a->{for(int l=a.length-1,i=0,j;i<a[0].length;i++)if(a[l][i]<33){for(j=0;a[j][i]<33;j++);System.out.print(l-j+",");}}

Takes the input as a String[] char[][] (← saves 16 bytes).
-2 bytes  in exchange for less readable output thanks to @OlivierGrégoire by changing print(l-j+",") to println(l-j).
Explanation:
Try it here.
a->{                         // Method with character 2D-array parameter and no return-type
  for(int l=a.length-1,      //  Length of the 2D char-array - 1
      i=0,j;                 //  Index-integers
    i<a[0].length;i++)       //  Loop (1) over the 2D char-array
    if(a[l][i]<33){          //   If the base of the current column is a space
      for(j=0;a[j][i]<33;    //    Loop (2) over the cells in this column as long as
                             //    we encounter spaces (from top to bottom)
        j++                  //     And increase `j` every time, to go down the column
      );                     //    End of loop (2)
      System.out.println(l-j);
                             //    Print the amount of rows - `j`
    }                        //   End of if-block
                             //  End of loop (1) (implicit / single-line body)
}                            // End of method

I haven't tried it yet but my idea for this challenge was to go top to bottom and look for _ if found store it's location then order on that, ignoring the bottom row of course. Might help to save bytes...

@TheLethalCoder That was my initial thought as well, but where do you want to store it in / order it? I originally thought a Map, but those are unsorted so you'll need a LinkedMap. In my head it all sounded a bit too much bytes, but if you can find a way to accomplish it shorter than this feel free to post an answer and I'll +1 it. :)

I only managed to get it down to 150 using Linq but there should be room for golfing it still.

In C# we have multidimensional arrays like: new[,] instead of the jagged array you are using as new[][]. If you have that in Java it could save you some bytes.

@TheLethalCoder That's the way Java uses multidimensional arrays I'm afraid. char[] = char-array; char[][] = 2D char-array; char[][][] = 3D char-array; etc.

That's unfortunate we have both in C# so it comes in handy sometimes.

System.out.println(l-j); looks listy enough for me to spare 2 bytes. Also, in the explanation, you forgot to change length() into length (no incidence on the byte-count as it's correct in the submission).

Haskell, 75 74 bytes
import Data.List;f=filter(>0).map(length.fst.span(<'!').reverse).transpose

The input is expected as a list of strings (rowwise).

Why use a semicolon after the import, when a newline is the same length and more idiomatic?

@Jules: Yeah, I usually do

MATL, 12 bytes
&nxG2\&fx-Xz

Input is a char matrix, with ; as row separator.
Try it online! Or verify all test cases.

C#, 150 144 137 bytes
using System.Linq;a=>a.SelectMany((i,h)=>i.Select((c,w)=>new{c,w,d=a.Length-1-h}).Where(o=>o.c==95&o.d>0)).OrderBy(o=>o.w).Select(o=>o.d)

Full/Formatted version:
using System;
using System.Collections.Generic;
using System.Linq;

class P
{
    static void Main()
    {
        Func<char[][], IEnumerable<int>> f = a =>
            a.SelectMany((i, h) => i.Select((c, w) => new { c, w, d = a.Length - 1 - h })
                                    .Where(o => o.c == 95 & o.d > 0))
             .OrderBy(o => o.w)
             .Select(o => o.d);

        Console.WriteLine(string.Concat(f(new char[][]
        {
            "  _                 ".ToArray(),
            " | |       _        ".ToArray(),
            " | |  _   | |       ".ToArray(),
            " | | | |  | |    _  ".ToArray(),
            "_| |_| |__| |___| |_".ToArray(),
        })));

        Console.ReadLine();
    }
}

MATL, 10 bytes
ooYssqtO>)

Input is a padded character matrix.
Try it online!

Python 2, 58 bytes
lambda l:[s.index('_')+1for s in zip(*l[-2::-1])if'_'in s]

Try it online!
Taking input as list of strings.

Uiua, 11 12 bytes
▽↧\≠±../+=@|

Try it
Annoyingly my original solution didn’t work, but I have a new one which is much cooler for just a byte longer.
Consider this input:
["  _   _                  "
 " | | | |    _            "
 " | | | |   | |         _ "
 " | | | |   | |     _  | |"
 "_| |_| |___| |____| |_| |"]

First, =@| makes a boolean matrix of where pipes are in the input.
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0]
 [0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1]
 [0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1]]

Then sum /+ the columns:
[0 4 0 4 0 4 0 4 0 0 0 3 0 3 0 0 0 0 1 0 1 0 2 0 2]

Jonathan Allan's Jelly solution uses the same idea of summing the mask of pipes, but in Jelly the shortest way to then get just the relevant numbers is to remove zeros and keep the items at even indices. In Uiua, that comes out to 14 bytes.
Instead, my idea was to first take the signs ± of the sums:
[0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1]

and to scan \ by not equal to ≠:
[0 1 1 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 1 1 0]

Then, we take the minimums ↧ of this and the original sums:
[0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0]

Using this as a filter ▽ for the sums yields the final result:
[4 4 3]

This returns the wrong answer when there are adjacent monoliths of the same height (for example it returns [1] instead of [1,1,1] for the third test case).

@Lynn Aw man. Well now I have a more interesting solution at the cost of two bytes. Time to remove my gloating remark :P

Now it’s just a byte longer than before :)

Here's another 12 char Uiua solution I came up with: ▽\≠±.⊜⧻.⍉=@|

Mathematica, 48 47 39 bytes
Last/@(Reverse@Most@#~Position~"_")&

Try it online!
Function which expects a rectangular array of characters. Takes Most of the array (all but the last row), Reverses it, then takes the Transpose*, then finds all Positions at which the _ character appears. The relevant heights are the Last elements of each Position.
*  is the 3 byte private use character U+F3C7 which represents \[Transpose] in Mathematica. Note that this doesn't work in Mathics, so the TIO link just uses Transpose.

JavaScript (ES6), 108 104 88 bytes
Saved 16 bytes thanks to @JustinMariner
i=>i.map((s,h)=>{while(t=r.exec(s))m[t.index]=i.length-h-1},m=[],r=/_/g)&&m.filter(e=>e)

Input taken as an array of strings

let input = [
'  _',
' | |           _',
' | |  _   _   | |',
' | | | | | |  | |     _',
'_| |_| |_| |__| |____| |_'
]

let anonymousFunction =
i=>i.map((s,h)=>{while(t=r.exec(s))m[t.index]=i.length-h-1},m=[],r=/_/g)&&m.filter(e=>e)

console.log(anonymousFunction(input))

88 bytes here

Thanks @JustinMariner! I'm stoked about the variable initialization as unused parameters given to Array.map, that's a cool trick.

Do you really need to assign the RegEx to a variable? You could use it directly in the exec and save a few bytes.

Actually, it is necessary - the while loop iterates over each match on a line, and without the internal state of the regex in the variable it would match the first occurance each time and loop infinitely. Each iteration it would create a new regex so exec would match the first. It actually crashes the stack exchange snippet editor if you inline the regex. Unless I'm missing something?

@shaggy I forgot to tag you in my last comment

Ruby, 82 bytes
Takes in a list of lines.
->l{l.map! &:chars;(l.pop.zip(*l).map{|s|s.join.count ?|}-[i=0]).select{0<1&i+=1}}

Try it online!

CJam, 15 14 bytes
1 byte saved thanks to @BusinessCat
{W%z'_f#{0>},}

This is a block that takes an array of strings on the stack and outputs an array.
Explanation:
W%    e# Reverse
z     e# Zip
'_f#  e# Get the index of '_' in each element (-1 if not found)
{0>}, e# Filter where positive

You can save 1 byte by reversing the whole array before transposing.

SOGL V0.12, 9 bytes
I{ _WH╥?O

Try it Here!
Takes input as an array of arrays of strings (characters).
Explanation:
I          rotate the array clockwise
 {         for each element
   _       push "_"
    W      get its index in the array (0 if not found, 1 if its the ground, >1 if its what we need)
     H     decrease that
      ╥    palindromize (duplicates the number, if it's <0, then errors and pushes 0, if =0, pushes 0, if >0, then pushes the number palindromized (always truthy))
       ?   if that, then
        T  output in a new line the original decreased index

JavaScript (Node.js), 70 bytes
a=>[...a.pop()].flatMap((_,i)=>a.flatMap((s,j)=>s[i]>_?a.length-j:[]))

Try it online!

Uiua SBCS, 13 bytes
+1↘1⍜⍉⊚↘1⇌=@_

Try it!
+1↘1⍜⍉⊚↘1⇌=@_
          =@_  # matrix mask of underscores
         ⇌     # reverse order of rows
       ↘1      # drop the first, removing the "floor"
    ⍜⍉⊚        # coordinates in the mask were it to be transposed
  ↘1           # drop the x coordinates
+1             # increment

Uiua, 12 bytes
+1▽⊃∊⊗@_⍉↘1⇌

See it in action

Ruby, 73 bytes
More boring but shorter than my original solution (below). Takes an array of lines.
->s{s.pop
s.map(&:chars).transpose.filter_map{n=_1.index ?_
n&&s.size-n}}

Attempt This Online!
Ruby, 78 bytes
->s,*a{s.scan(/_/){c=$'.count $/
a<<[$`[/.+\Z/].size,c]if c>0}
a.sort.map{_2}}

Attempt This Online!

Perl 5 -p, 44 bytes
s/_/$r[pos]=$./eg}{$_&&$.-$_&&say$.-$_ for@r

Try it online!

Pip, 18 17 bytes
15 bytes of code, +2 for -rp flags.
_FI_@?'_MRVgZDs

Takes input from stdin. Try it online!
Explanation
                 g is list of lines from stdin (-r flag); s is space
         RVg     Reverse g
            ZDs  Zip (transpose), filling gaps with a default char of space
        M        Map this function:
   _@?'_          Index of _ in each line (or nil if it doesn't appear)
_FI              Filter, keeping only the truthy (nonzero, non-nil) values
                 Autoprint in repr format (-p flag)

Octave, 31 bytes
@(a)(s=sum(a>95))(s>0)(1:2:end)

Takes a 2D array of chars as input.
Verify all test cases!

Perl 6, 65 bytes
{m:ex/^^(\N+)_([\N*\n]+:)/.sort(*[0].chars).map(+*[1].comb("
"))}

Try it online!

m:exhaustive/^^(\N+)_([\N*\n]+:)/ searches the input string for all underscores, and returns a match object for each, where the first capturing parentheses contain the preceding part of the line on which the underscore is found, and the second capturing parentheses contain the entire rest of the string.  The rest of the string must contain at least one newline, so we don't count the underscores at ground level.  The :exhaustive flag allows these matches to overlap.
.sort(*[0].chars) sorts these match objects by the number of characters in the part of the line preceding each underscore.  This orders them left-to-right.
.map(+*[1].comb("\n")) maps each match object to the number of newline characters in the part of the input string trailing each underscore--that is, the height.  The \n is an actual newline character, saving one byte.

PHP, 119 bytes
function($s){$r=array_map(null,...$s);foreach($r as$k=>&$v)if($v=array_count_values($v)['|'])echo($v+$r[$k+2]=0)." ";};

Let's break this down! Our input here is a 2D array of chars.
$r=array_map(null,...$s) // Neat little snippet to transpose the array

foreach($r as$k=>&$v)    // Loop through the array, grabbing each row of our 2D array
(which is now each column of the monolith)

if($v=array_count_values($v)['|']) // Count the number of '|' characters in the column
(which is the height of our monolith), and if it's greater than 0 (truthy in PHP)...

echo($v+$r[$k+2]=0)." "; // Output that number, and simultaneously set the row 2 indices
                            down to null (to remove duplicate values)

Pyth, 19 15 14 bytes
f>T0mx_d\_.tQd

Test it online! The input is a list of lines.
Explanations
          .tQd     # Transpose, pad with spaces
    mx_d\_         # For each line, reverse it, find the position of "_" (-1 if not found)
f>T0               # Filter on positions greater than zero

Japt, 9 bytes
Takes input as an array of lines.
Õ®x2 èSÃf

Try it (header splits input string to array) or run all test cases
Õ®x2 èSÃf     :Implicit input of array
Õ             :Transpose
 ®            :Map
  x2          :  Trim left
     è        :  Count
      S       :    Spaces
       Ã      :End map
        f     :Filter

Jelly, 9 bytes
ṖZ=”_UT€F

Try it online!
Unfortunately, Jonathan Allan's answer is still shorter, as I assume input is a list of lines, so don't count the Ỵ. However, I reckon this is an interesting enough approach to post
How it works
ṖZ=”_UT€F - Main link. Takes a list of lines L on the left
Ṗ         - Remove the last line
 Z        - Transpose
  =”_     - Check each character for equality with "_"
     U    - Reverse each row
       €  - For each row
      T   - Yield the indices of 1
        F - Flatten

R, 114 99 bytes
\(u){`+`=length
for(j in 2:+u-1){F=c(a<-which(u[[j]]=="_"),F)
T=c(rep(+u-j,+a),T)}
T[order(F)][-1]}

Attempt This Online!

The monoliths are looking like barplots, and so, it is natural to use R. Surprisingly though, nobody has yet golfed this in R.

The function takes as an input a list of vectors (1D arrays) of chacters; I have added strsplits to the function call (see the link below) for better readability
f(strsplit(strsplit("____________________","\n")[[1]],"")) throws an error

History:

-14 bytes thanks to pajonk
-1 byte golfed myself

Nice solution! Some golfs for -14 bytes: https://ato.pxeger.com/run?1=lVLBasMwDIUd9RXGJ4s4h-40xvwXubnGLW2yJJS0qAk9ZPmSXbLBPmr7mjl13HVsLamMrCcs6UnCr2_Uv2fqo6mz-OFzPRcNtotooTZp9VznQKrtINuSKFlRsfvHqIln2JJaieVTfMiLVS4arUtjlOKWoySExD1SuhMutJTREmWCHSR6S-uUBKHpPNfXnc7Evqb9blPUPwA4YxbYizujBM8OzoC87yNCnGVgHT6qHe-j4ZLPK45az4yRnCPCJVZ2RngSVwJG6uCdmvHgjDeAyZyWsVEh5I6t31BjSJ2qN2wjzHzRwgDDMq7YX6NdUTatOW7_kT-p_o_1vbff

@pajonk impressive golfing! would you like to write your own answer?

Nah, the core algorithm is yours, from me just some minor improvements.

Haskell + hgl, 20 bytes
fl gt0<fa"_"~<<tx<Rv

Attempt This Online!
Some late night golfing, I'll probably find a way shorter version tomorrow.
Explanation

Rv reverse the rows
tx transpose
fa"_" find the index of _ in the column ignoring columns without a _
fl gt0 remove 0s

Reflection

All of the following presets with _ could have been useful here:

ce '_'
e '_'
fa"_"

Related to that it might be nice to have  a version of ce which takes a list and counts all elements in that list appearing in the input.  This would be generally useful but would also save a byte on using ce to find specific characters.
eq0 is 3 bytes, but seems generally useful. If it were 2 bytes we could do fn q0 here instead of fl gt0 to save a byte.


text:
Scrappers v0.1: Mercenary Programmers
In a desolate, war-torn world, where cities have been overrun by thugs and thieves, civilization has reinvented itself in the form of small, isolated, industrial cooperatives, scattered throughout the previously uninhabited landscape. The existence of these communities is reliant on teams of mercenary workers called "scrappers", who search the untamed territory for valuable materials to sell to the coops. As these materials have grown more scarce, scrapping has become an ever more difficult and dangerous profession. Fragile human workers have mostly been replaced with remote robotic stand-ins, called “bots”, and a typical mercenary is more likely to be a skilled programmer than an armed welder. As the human presence in scrapping has declined, so too has the respect between mercenary groups for one another. Bots are equipped not only to collect scrap, but to defend it, and in some cases take it by force. Bot programmers work tirelessly devising new strategies to outsmart rival scrappers, resulting in increasingly aggressive bots, and yet another danger for humans who venture outside the walls of their communities.

(yeah, the logo gets cropped hilariously)
Welcome to Scrappers!
This is an early version of Scrappers in which scrap collection and factories have not been implemented. It’s basically a “shoot ‘em up”.
You are a mercenary programmer tasked with creating a program to remotely conduct your bots to victory over rival scrapper groups. Your bots are spider-like machines consisting of power and shield generators at their core, surrounded by many appendages equipped with gripping, cutting, and attacking implements. The power generator is capable of producing 12 power units (pu) per tick (a scrapper's unit of time). You are in control of how this power is distributed amongst a bot's three primary needs: movement, shields, and firepower.
Scrapper bots are exceptionally agile machines, and can easily move over, under, and around any obstacles they encounter. Thus, collision is not something that your program needs take into consideration. You are free to allocate all, some, or none of the 12pu available to your bot for movement, as long as you deal in whole numbers. Allocating 0pu to a bot's movement functions would render it immobile. Allocating 2pu would enable a bot to move 2 distance units (du) per tick, 5pu would result in 5du/tick, 11pu would result in 11du/tick, and so on.
Your bots’ shield generators project a bubble of deflective energy around their body. A shield can deflect up to 1 damage before popping, thus leaving your bot exposed until it's shield generator builds enough power to snap the shield back into place. You are free to allocate all, some, or none of the 12pu available to your bot towards it’s shield. Allocating 0pu to a bot's shield means that it will never generate a shield. Allocating 2pu would allow a bot to generate a new shield 2 out of 12 ticks, or once every 6 ticks. 5pu would result in shield regeneration 5 out of every 12 ticks, and so on.
By building up a charge in their welding lasers, your bots can fire damaging beams over short distances with fair accuracy. Like shield generation, your bots’ rate of fire depends on the power allocated to their lasers. Allocating 0pu to a bot's lasers means that it will never fire. Allocating 2pu would allow a bot to fire 2 out of every 12 ticks, and so on. A bot’s laser will travel until it encounters an object or disperses into uselessness, so be mindful of friendly fire. Although your bots are quite accurate, they aren’t perfect. You should expect +/- 2.5 degrees of variance in accuracy. As the laser beam travels, its particles are incrementally deflected by the atmosphere until the beam becomes effectively harmless with enough distance. A laser does 1 damage at point blank range, and 2.5% less damage every bot-length it travels. In other words, the closer  you are to your target, the more likely you are to hit it, and the more damage you will cause.
Scrapper bots are autonomous enough to handle basic functions, but rely on you, their programmer, to make them useful as a group. As a programmer, you may issue the following commands for each individual bot:

MOVE: Specify coordinates towards which a bot will move.
TARGET: Identify a bot to aim at and fire at when power allocation allows.
POWER: Redistribute power between movement, shields, and firepower.

Technical Game Details
There are three programs that you'll need to be familiar with. The Game Engine is the heavy lifter and provides a TCP API that the player programs connect to. The player program is what you'll write, and I've provided some examples with binaries here. Finally, the Renderer processes the output from the Game Engine to produce a GIF of the battle.
The Game Engine
You can download the game engine from here. When the game is launched, it will begin listening on port 50000 (currently not configurable) for player connections. Once it receives two player connections, it sends the READY message to the players and begins the game. Player programs send commands to the game via the TCP API. When the game is over, a JSON file named scrappers.json (also, currently not configurable) is created. This is what the renderer uses to create a GIF of the game.
The TCP API
Player programs and the game engine communicate by passing newline-terminated JSON strings back and fourth over a TCP connection. There are just five different JSON messages that can be sent or received.
Ready Message
The READY message is sent from the game to the player programs and is only sent once. This message tells the player program what its player ID (PID) is and provides a list of all the bots in the game. The PID is the only way to determine which Bots are friendly vs enemy. More info on the bot fields below.
{
    "Type":"READY",  // Message type
    "PID":1,         // Player ID
    "Bots":[         // Array of bots
        {
            "Type":"BOT",
            "PID":1,
            "BID":1,
            "X":-592,
            ...
        },
        ...
    ]
}

Bot Message
The BOT message is sent from the game to the player programs and is sent when a bot's attributes change. For instance, when shields are projected, or health changes, a BOT message is sent. The Bot ID (BID) is only unique within a particular player.
{
    "Type":"BOT",   // Message type
    "PID":1,        // Player ID
    "BID":1,        // Bot ID
    "X":-592,       // Current X position
    "Y":-706,       // Current Y position
    "Health":12,    // Current health out of 12
    "Fired":false,  // If the Bot fired this tick
    "HitX":0,       // X position of where the shot landed
    "HitY":0,       // Y position of where the shot landed
    "Scrap":0,      // Future use. Ignore.
    "Shield":false  // If the Bot is currently shielded.
}

Move Message
The MOVE message is a command from the player program to the game (but think of it as a command to a bot). Simply identify the bot you want to move, and the coordinates. It's assumed that you are commanding your own bot, so no PID is necessary.
{
    "Cmd":"MOVE",
    "BID":1,        // Bot ID
    "X":-592,       // Destination X coordinate
    "Y":-706,       // Destination Y coordinate
}

Target Message
The TARGET message tells one of your bots to target some other bot.
{
    "Cmd":"TARGET",
    "BID":1,        // Bot ID
    "TPID":0,       // The PID of the bot being targeted
    "TBID":0,       // The BID of the bot being targeted
}

Power Message
The POWER message reallocates the 12pu available to your bot between movement, firepower, and shields.
{
    "Cmd":"POWER",
    "BID":1,        // Bot ID
    "FPow":4,       // Set fire power
    "MPow":4,       // Set move power
    "SPow":4,       // Set shield power
}

The Competition
If you're brave enough to explore the untamed lands, you'll be entered into a double-elimination tournament against your mercenary peers. Please create an answer for your submission and either paste your code or provide a link to a git repo, gist, etc. Any language is acceptable, but you should assume I know nothing about the language and include instructions for running your program. Create as many submissions as you like, and be sure to give them names!
The sample player programs will be included in the tournament, so I highly recommend testing your bot against them. The tournament will commence roughly two weeks after we get four unique program submissions. Good luck!
--- Winner's Bracket ---

** Contestants will be randomly seeded **
__________________
                  |___________
__________________|           |
                              |___________
__________________            |           |
                  |___________|           |
__________________|                       |
                                          |________________
__________________                        |                |
                  |___________            |                |
__________________|           |           |                |
                              |___________|                |
__________________            |                            |
                  |___________|                            |
__________________|                                        |
                                                           |
--- Loser's Bracket ---                                    |___________
                                                           |
___________                                                |
           |___________                                    |
___________|           |___________                        |
                       |           |                       |
            ___________|           |                       |
                                   |___________            |
___________                        |           |           |
           |___________            |           |___________|
___________|           |___________|           |
                       |                       |
            ___________|            ___________|

Other Important Info

The game runs at 12 ticks/second, so you will not receive messages more frequently than every 83 milliseconds or so.
Each bot is 60du in diameter. The shield takes up no additional space. With the +/- 2.5% accuracy, the odds of hitting a bot at a certain distance are represented by this graph:

The decay of laser damage over distance is represented by this graph:

A bot's accuracy and laser decay combine to calculate its average damage per shot. That is, the average damage a bot will cause when it fires from a certain distance. Damage per shot is represented by this graph:

A bot's laser originates half way between the bot's center and its edge. Thus, stacking your bots will result in friendly fire.
Enemy bots spawn roughly 1440du apart.
The game ends if 120 ticks (10 seconds) pass without any damage dealt.
The winner is the player with the most bots, then the most health when the game ends.

Understanding the Rendered Image

Player 1 is represented by circles and player 2 by hexagons.
The color of a bot represents its power allocation. More red means more power has been allocated to firing. More blue means more shield. More green means more movement.
The "hole" in a bot's body represents damage. The larger the hole, the more damage has been taken.
The white circles surrounding a bot are it's shield. If a bot has a shield at the end of the turn, it is shown. If the shield was popped by taking damage, it is not shown.
The red lines between bots represent shots taken.
When a bot is killed, a large red "explosion" is shown.

Comments are not for extended discussion; this conversation has been moved to chat.

Extremist (Python 3)
This bot will always devote all of its power to one thing: shielding if it isn't shielded, moving if it is out of position, and firing otherwise. Beats all of the sample bots except death-dish.
import socket, sys, json
from types import SimpleNamespace
s=socket.socket()
s.connect(("localhost",50000))
f=s.makefile()
bots={1:{},2:{}}
def hook(obj):
    if "BID" in obj:
        try:
            bot = bots[obj["PID"]][obj["BID"]]
        except KeyError:
            bot = SimpleNamespace(**obj)
            bots[bot.PID][bot.BID] = bot
        else:
            bot.__dict__.update(obj)
        return bot
    return SimpleNamespace(**obj)
decoder = json.JSONDecoder(object_hook=hook)
PID = decoder.decode(f.readline()).PID
#side effect: .decode fills bots dictionary
def turtle(bot):
    send({"Cmd":"POWER","BID":bot.BID,"FPow":0,"MPow":0,"SPow":12})
    bot.firing = bot.moving = False
def send(msg):
    s.send(json.dumps(msg).encode("ascii")+b"\n")
for bot in bots[PID].values():
    turtle(bot)
target_bot = None
def calc_target_bot():
    ok_bots = []
    for bot2 in bots[(2-PID)+1].values():
        if bot2.Health < 12:
            ok_bots.append(bot2)
    best_bot = (None,2147483647)
    for bot2 in (ok_bots or bots[(2-PID)+1].values()):
        dist = bot_dist(bot, bot2)
        if dist < best_bot[1]:
            best_bot = bot2, dist
    return best_bot[0]
def bot_dist(bot, bot2):
    if isinstance(bot, tuple):
        bot=SimpleNamespace(X=bot[0],Y=bot[1])
    if isinstance(bot2, tuple):
        bot=SimpleNamespace(X=bot[0],Y=bot[1])
    distx = bot2.X - bot.X
    disty = bot2.Y - bot.Y
    return (distx**2+disty**2)**.5
LENGTH_Y = -80
LENGTH_X = 80
line = None
def move(bot, pos):
    bot.firing = False
    bot.moving = True
    send({"Cmd":"POWER","BID":bot.BID,"FPow":0,"MPow":12,"SPow":0})
    send({"Cmd":"MOVE","BID": bot.BID,"X":pos[0],"Y":pos[1]})
def go(bot, line):
    if line != None:
        position = (line[0]+LENGTH_X*(bot.BID-6),line[1]+LENGTH_Y*(bot.BID-6))
        if not close_pos(bot, position, 1.5):
            return True, position
    return False, None
def close_pos(bot, pos, f):
    if abs(bot.X - pos[0]) <= abs(LENGTH_X*f) or \
        abs(bot.Y - pos[1]) <= abs(LENGTH_Y*f):
        return True
def set_line(bot):
    global line
    newline = bot.X - LENGTH_X*(bot.BID - 6), bot.Y - LENGTH_Y*(bot.BID - 6)
    if line == None or bot_dist(line, target_bot) < (bot_dist(newline, target_bot) - 100):
        line = newline
def move_or_fire(bot):
    global target_bot, line
    if not target_bot:
        target_bot = calc_target_bot()
    followline, place = go(bot, line)
    if not target_bot:
        #Game should be over, but just in case ...
        return turtle(bot)
    elif bot_dist(bot, target_bot) > 2000:
        line = None
        position = (target_bot.X, target_bot.Y)
        position = (position[0]+LENGTH_X*(bot.BID-6),position[1]+LENGTH_Y*(bot.BID-6))
        move(bot, position)
    elif followline:
        set_line(bot)
        move(bot, place)
    elif any(close_pos(bot, (bot2.X, bot2.Y), .6) for bot2 in bots[PID].values() if bot != bot2):
        try:
            move(bot, place)
        except TypeError:
            turtle(bot)
        set_line(bot)
        #Let the conflicting bots resolve
    else:
        set_line(bot)
        bot.firing = True
        bot.moving = False
        send({"Cmd":"POWER","BID":bot.BID,"FPow":12,"MPow":0,"SPow":0})
        send({"Cmd":"TARGET","BID": bot.BID,
              "TPID":target_bot.PID,"TBID":target_bot.BID})
def dead(bot):
    del bots[bot.PID][bot.BID]
def parse_message():
    global target_bot
    line = f.readline()
    if not line:
        return False
    bot = decoder.decode(line)
    assert bot.Type == "BOT"
    del bot.Type
    if bot.PID == PID:
        if bot.Health <= 0:
            dead(bot)
        elif not bot.Shield:
            turtle(bot)
        else:
            move_or_fire(bot)
    elif target_bot and (bot.BID == target_bot.BID):
        target_bot = bot
        if target_bot.Health <= 0:
            target_bot = None
            dead(bot)
            for bot in bots[PID].values():
                if bot.firing or bot.moving:
                    move_or_fire(bot)
    elif bot.Health <= 0:
        dead(bot)
    assert bot.Health > 0 or bot.BID not in bots[bot.PID]
    return True
while parse_message():
    pass

I am unfamiliar with python, but there seems to be multiple issues with your submission: 1) lines 212 120 are not indented correctly and 2) target_hp is not defined. I could fix (1) but (2) is stopping me from running your submission. But it could be my lack of experience with python.

That entire if statement was leftover from some debugging and isn't necessary at all

Less Reckless (Go)
go run main.go

Originally, I planned to slightly modify the Reckless Abandon sample program so that bots would not fire if a friendly bot was in the way. I ended up with bots that pick new targets when a friend is in the way, which I guess is better. It'll beat the first two programs.
The code isn't perfect. The logic to determine if a shot is clear uses some pretty random guesswork.
There doesn't seem to be a mechanism to target "nobody". That might be a good feature to add.
The TCP API is nice in that any language can play, but it also means a lot of boilerplate code. If I wasn't familiar with the language the sample bots were written in, I probably wouldn't have been motivated to play around with this. A collection of boilerplate samples in various languages would be a great addition to your other git repos.
( most of the following code is copy/paste from one of the sample bots )
package main

import (
    "bufio"
    "encoding/json"
    "flag"
    "io"
    "log"
    "math"
    "math/rand"
    "net"
    "time"
)

const (
    MaxHealth int = 12
    BotSize float64 = 60
)

var (
    // TCP connection to game.
    gameConn net.Conn
    // Queue of incoming messages
    msgQueue chan MsgQueueItem
)

// MsgQueueItem is a simple vehicle for TCP
// data on the incoming message queue.
type MsgQueueItem struct {
    Msg string
    Err error
}

// Command contains all the fields that a player might
// pass as part of a command. Fill in the fields that
// matter, then marshal into JSON and send.
type Command struct {
    Cmd  string
    BID  int
    X    int
    Y    int
    TPID int
    TBID int
    FPow int
    MPow int
    SPow int
}

// Msg is used to unmarshal every message in order
// to check what type of message it is.
type Msg struct {
    Type string
}

// BotMsg is used to unmarshal a BOT representation
// sent from the game.
type BotMsg struct {
    PID, BID   int
    X, Y       int
    Health     int
    Fired      bool
    HitX, HitY int
    Scrap      int
    Shield     bool
}

// ReadyMsg is used to unmarshal the READY
// message sent from the game.
type ReadyMsg struct {
    PID  int
    Bots []BotMsg
}

// Create our game data storage location
var gdb GameDatabase

func main() {

    var err error
    gdb = GameDatabase{}
    msgQueue = make(chan MsgQueueItem, 1200)

    // What port should we connect to?
    var port string
    flag.StringVar(&port, "port", "50000", "Port that Scrappers game is listening on.")
    flag.Parse()

    // Connect to the game
    gameConn, err = net.Dial("tcp", ":"+port)
    if err != nil {
        log.Fatalf("Failed to connect to game: %v\n", err)
    }
    defer gameConn.Close()

    // Process messages off the incoming message queue
    go processMsgs()

    // Listen for message from the game, exit if connection
    // closes, add message to message queue.
    reader := bufio.NewReader(gameConn)
    for {
        msg, err := reader.ReadString('\n')
        if err == io.EOF {
            log.Println("Game over (connection closed).")
            return
        }
        msgQueue <- MsgQueueItem{msg, err}
    }
}

func runStrategy() {

    // LESS RECKLESS ABANDON
    // - For three seconds, all bots move as fast as possible in a random direction.
    // - After three seconds, split power between speed and firepower.
    // - Loop...
    //     - Identify the enemy bot with the lowest health.
    //     - If a friendly bot is in the way, pick someone else.
    //     - If there's a tie, pick the one closest to the group.
    //     - Everybody moves towards and targets the bot.

    var myBots []*GDBBot

    // Move quickly in random direction.
    // Also, might as well get a shield.
    myBots = gdb.MyBots()
    for _, bot := range myBots {
        send(bot.Power(0, 11, 1))
        radians := 2.0 * math.Pi * rand.Float64()
        x := bot.X + int(math.Cos(radians)*999)
        y := bot.Y + int(math.Sin(radians)*999)
        send(bot.Move(x, y))
    }

    // Wait three seconds
    time.Sleep(3 * time.Second)

    // Split power between speed and fire
    for _, bot := range myBots {
        send(bot.Power(6, 6, 0))
    }

    for { // Loop indefinitely

        // Find a target

        candidates := gdb.TheirBots()

        // Order by health
        reordered := true
        for reordered {
            reordered = false
            for n:=1; n<len(candidates); n++ {
                if candidates[n].Health < candidates[n-1].Health {
                    temp := candidates[n-1]
                    candidates[n-1] = candidates[n]
                    candidates[n] = temp
                    reordered = true
                }
            }
        }

        // Order by closeness

        // My swarm position is...
        ttlX, ttlY := 0, 0
        myBots = gdb.MyBots() // Refresh friendly bot list
        for _, bot := range myBots {
            ttlX += bot.X
            ttlY += bot.Y
        }
        avgX := ttlX / len(myBots)
        avgY := ttlY / len(myBots)

        // Sort
        reordered = true
        for reordered {
            reordered = false
            for n:=1; n<len(candidates); n++ {
                thisDist := distance(avgX, avgY, candidates[n].X, candidates[n].Y)
                lastDist := distance(avgX, avgY, candidates[n-1].X, candidates[n-1].Y)
                if thisDist < lastDist {
                    temp := candidates[n-1]
                    candidates[n-1] = candidates[n]
                    candidates[n] = temp
                    reordered = true
                }
            }
        }

        // For all my bots, try to find the weakest enemy that my bot has a clear shot at
        myBots = gdb.MyBots()
        for _, bot := range myBots {
            for _, enemy := range candidates {

                clear := clearShot(bot, enemy)
                if clear {

                    // Target and move towards
                    send(bot.Target(enemy))
                    send(bot.Follow(enemy))
                    break
                }
                log.Println("NO CLEAR SHOT")
            }
        }

        time.Sleep(time.Second / 24)
    }
}

func clearShot(bot, enemy *GDBBot) bool {

    deg45rad := math.Pi*45/180
    deg30rad := math.Pi*30/180
    deg15rad := math.Pi*15/180
    deg5rad := math.Pi*5/180

    myBots := gdb.MyBots()
    enmyAngle := math.Atan2(float64(enemy.Y-bot.Y), float64(enemy.X-bot.X))

    for _, friend := range myBots {

        dist := distance(bot.X, bot.Y, friend.X, friend.Y)
        angle := math.Atan2(float64(friend.Y-bot.Y), float64(friend.X-bot.X))
        safeAngle := angle

        if dist < BotSize*3 {
            safeAngle = deg45rad/2
        } else if dist < BotSize*6 {
            safeAngle = deg30rad/2
        } else if dist < BotSize*9 {
            safeAngle = deg15rad/2
        } else {
            safeAngle = deg5rad/2
        }

        if angle <= enmyAngle+safeAngle &&  angle >= enmyAngle-safeAngle {
            return false
        }
    }

    return true
}

func processMsgs() {

    for {
        queueItem := <-msgQueue
        jsonmsg := queueItem.Msg
        err := queueItem.Err

        if err != nil {
            log.Printf("Unknown error reading from connection: %v", err)
            continue
        }

        // Determine the type of message first
        var msg Msg
        err = json.Unmarshal([]byte(jsonmsg), &msg)
        if err != nil {
            log.Printf("Failed to marshal json message %v: %v\n", jsonmsg, err)
            return
        }

        // Handle the message type

        // The READY message should be the first we get. We
        // process all the data, then kick off our strategy.
        if msg.Type == "READY" {

            // Unmarshal the data
            var ready ReadyMsg
            err = json.Unmarshal([]byte(jsonmsg), &ready)
            if err != nil {
                log.Printf("Failed to marshal json message %v: %v\n", jsonmsg, err)
            }

            // Save our player ID
            gdb.PID = ready.PID
            log.Printf("My player ID is %v.\n", gdb.PID)

            // Save the bots
            for _, bot := range ready.Bots {
                gdb.InsertUpdateBot(bot)
            }

            // Kick off our strategy
            go runStrategy()

            continue
        }

        // The BOT message is sent when something about a bot changes.
        if msg.Type == "BOT" {

            // Unmarshal the data
            var bot BotMsg
            err = json.Unmarshal([]byte(jsonmsg), &bot)
            if err != nil {
                log.Printf("Failed to marshal json message %v: %v\n", jsonmsg, err)
            }

            // Update or add the bot
            gdb.InsertUpdateBot(bot)

            continue
        }

        // If we've gotten to this point, then we
        // were sent a message we don't understand.
        log.Printf("Recieved unknown message type \"%v\".", msg.Type)
    }
}

///////////////////
// GAME DATABASE //
///////////////////

// GameDatabase stores all the data
// sent to us by the game.
type GameDatabase struct {
    Bots []GDBBot
    PID  int
}

// GDBBot is the Bot struct for the Game Database.
type GDBBot struct {
    BID, PID int
    X, Y     int
    Health   int
}

// InserUpdateBot either updates a bot's info,
// deletes a dead bot, or adds a new bot.
func (gdb *GameDatabase) InsertUpdateBot(b BotMsg) {

    // If this is a dead bot, remove and ignore
    if b.Health <= 0 {

        for i := 0; i < len(gdb.Bots); i++ {
            if gdb.Bots[i].BID == b.BID && gdb.Bots[i].PID == b.PID {
                gdb.Bots = append(gdb.Bots[:i], gdb.Bots[i+1:]...)
                return
            }
        }
        return
    }

    // Otherwise, update...
    for i, bot := range gdb.Bots {
        if b.BID == bot.BID && b.PID == bot.PID {
            gdb.Bots[i].X = b.X
            gdb.Bots[i].Y = b.Y
            gdb.Bots[i].Health = b.Health
            return
        }
    }

    // ... or Add
    bot := GDBBot{}
    bot.PID = b.PID
    bot.BID = b.BID
    bot.X = b.X
    bot.Y = b.Y
    bot.Health = b.Health
    gdb.Bots = append(gdb.Bots, bot)
}

// MyBots returns a pointer array of GDBBots owned by us.
func (gdb *GameDatabase) MyBots() []*GDBBot {
    bots := make([]*GDBBot, 0)
    for i, bot := range gdb.Bots {
        if bot.PID == gdb.PID {
            bots = append(bots, &gdb.Bots[i])
        }
    }
    return bots
}

// TheirBots returns a pointer array of GDBBots NOT owned by us.
func (gdb *GameDatabase) TheirBots() []*GDBBot {
    bots := make([]*GDBBot, 0)
    for i, bot := range gdb.Bots {
        if bot.PID != gdb.PID {
            bots = append(bots, &gdb.Bots[i])
        }
    }
    return bots
}

// Move returns a command struct for movement.
func (b *GDBBot) Move(x, y int) Command {
    cmd := Command{}
    cmd.Cmd = "MOVE"
    cmd.BID = b.BID
    cmd.X = x
    cmd.Y = y
    return cmd
}

// Follow is a convenience function which returns a
// command stuct for movement using a bot as a destination.
func (b *GDBBot) Follow(bot *GDBBot) Command {
    cmd := Command{}
    cmd.Cmd = "MOVE"
    cmd.BID = b.BID
    cmd.X = bot.X
    cmd.Y = bot.Y
    return cmd
}

// Target returns a command struct for targeting a bot.
func (b *GDBBot) Target(bot *GDBBot) Command {
    cmd := Command{}
    cmd.Cmd = "TARGET"
    cmd.BID = b.BID
    cmd.TPID = bot.PID
    cmd.TBID = bot.BID
    return cmd
}

// Power returns a command struct for seting the power of a bot.
func (b *GDBBot) Power(fire, move, shield int) Command {
    cmd := Command{}
    cmd.Cmd = "POWER"
    cmd.BID = b.BID
    cmd.FPow = fire
    cmd.MPow = move
    cmd.SPow = shield
    return cmd
}

////////////////////
// MISC FUNCTIONS //
////////////////////

// Send marshals a command to JSON and sends to the game.
func send(cmd Command) {
    bytes, err := json.Marshal(cmd)
    if err != nil {
        log.Fatalf("Failed to mashal command into JSON: %v\n", err)
    }
    bytes = append(bytes, []byte("\n")...)
    gameConn.Write(bytes)
}

// Distance calculates the distance between two points.
func distance(xa, ya, xb, yb int) float64 {
    xdist := float64(xb - xa)
    ydist := float64(yb - ya)
    return math.Sqrt(math.Pow(xdist, 2) + math.Pow(ydist, 2))
}

Does this program beat my extremist submission?

No @ppperry, it doesn't. It's cannon fodder, but I'm working on a second bot.

Trigger Happy - Java 8
Trigger Happy is a simple evolution of my original, but no longer viable, Bombard bot. It is a very simple bot that will simply fire on the currently targeted enemy if there is a clear shot, otherwise performs a random walk to try to get into a better position. All the time attempting to have a shield.
However, for all its simplicity it is very effective. And will readily destroy the sample bots.
Note, there are multiple bugs with the bot such as will sometimes fire even when not a clear shot and may not maintain a shield... but it is still effective so will just submit this entry as-is

Death-dish vs Trigger Happy
Code as follows:
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

//import visual.Viewer;

public class TriggerHappy {

  static final int BOT_RADIUS = 30;
private static final double WALK_MAX_DIRECTION_CHANGE = Math.PI/3;
  static Bot targetedBot;

  enum BotState
  {
    INIT,
    RANDOM_WALK,
    FIRING,
    SHIELDING,
    DEAD,
    END
  }

  enum Power
  {
    MOVE,
    FIRE,
    SHIELD
  }

  private static PrintStream out;
private static List<Bot> enemyBots;
private static List<Bot> myBots;
//private static Viewer viewer;

  public static void main(String[] args) throws Exception
  {
    InetAddress localhost = Inet4Address.getLocalHost();
    Socket socket = new Socket(localhost, 50000);
    InputStream is = socket.getInputStream();
    out = new PrintStream(socket.getOutputStream());

    // read in the game configuration
    String line = readLine(is);
    Configuration config = new Configuration(line);
  //  viewer = new Viewer(line);

    myBots = config.bots.values().stream().filter(b->b.playerId==config.playerId).collect(Collectors.toList());
    enemyBots = config.bots.values().stream().filter(b->b.playerId!=config.playerId).collect(Collectors.toList());

    // set initial target
    targetedBot = enemyBots.get(enemyBots.size()/2);
    myBots.forEach(bot->target(bot,targetedBot));

    for (line = readLine(is);line!=null;line = readLine(is))
    {
//      viewer.update(line);
      // read in next bot update message from server
      Bot updatedBot = new Bot(line);
      Bot currentBot = config.bots.get(updatedBot.uniqueId);
      currentBot.update(updatedBot);

      // check for bot health
      if (currentBot.health<1)
      {
        // remove dead bots from lists
        currentBot.state=BotState.DEAD;
        if (currentBot.playerId == config.playerId)
        {
          myBots.remove(currentBot);
        }
        else
        {
          enemyBots.remove(currentBot);

          // change target if the targetted bot is dead
          if (currentBot == targetedBot)
          {
            if (enemyBots.size()>0)
            {
              targetedBot = enemyBots.get(enemyBots.size()/2);
              myBots.forEach(bot->target(bot,targetedBot));
            }
            // no more enemies... set bots to end state
            else
            {
              myBots.forEach(bot->bot.state = BotState.END);
            }
          }
        }
      }
      else
      {
          // ensure our first priority is shielding
          if (!currentBot.shield && currentBot.state!=BotState.SHIELDING)
          {
              currentBot.state=BotState.SHIELDING;
              shield(currentBot);
          }
          else
          {
              // not game end...
              if (currentBot.state != BotState.END)
              {
                // command to fire if we have a clear shot
                if (clearShot(currentBot))
                {
                    currentBot.state=BotState.FIRING;
                    fire(currentBot);
                }
                // randomly walk to try and get into a better position to fire
                else
                {
                    currentBot.state=BotState.RANDOM_WALK;
                    currentBot.dir+=Math.random()*WALK_MAX_DIRECTION_CHANGE - WALK_MAX_DIRECTION_CHANGE/2;
                    move(currentBot, (int)(currentBot.x+Math.cos(currentBot.dir)*100), (int) (currentBot.y+Math.sin(currentBot.dir)*100));
                }

              }
          }
      }
    }
    is.close();
    socket.close();
  }

// returns true if there are no friendly bots in firing line... mostly
private static boolean clearShot(Bot originBot)
{

    double originToTargetDistance = originBot.distanceFrom(targetedBot);
    for (Bot bot : myBots)
    {
        if (bot != originBot)
        {
            double x1 = originBot.x - bot.x;
            double x2 = targetedBot.x - bot.x;
            double y1 = originBot.y - bot.y;
            double y2 = targetedBot.y - bot.y;
            double dx = x2-x1;
            double dy = y2-y1;
            double dsquared = dx*dx + dy*dy;
            double D = x1*y2 - x2*y1;
            if (1.5*BOT_RADIUS * 1.5*BOT_RADIUS * dsquared > D * D && bot.distanceFrom(targetedBot) < originToTargetDistance)
            {
                return false;
            }
        }
    }

    return true;

}

  static class Bot
  {
    int playerId;
    int botId;
    int x;
    int y;
    int health;
    boolean fired;
    int hitX;
    int hitY;
    double dir = Math.PI*2*Math.random();
    boolean shield;
    int uniqueId;
    BotState state = BotState.INIT;
    Power power = Power.SHIELD;

    Bot(String line)
    {
      String[] tokens = line.split(",");
      playerId = extractInt(tokens[1]);
      botId = extractInt(tokens[2]);
      x = extractInt(tokens[3]);
      y = extractInt(tokens[4]);
      health = extractInt(tokens[5]);
      fired = extractBoolean(tokens[6]);
      hitX = extractInt(tokens[7]);
      hitY = extractInt(tokens[8]);
      shield = extractBoolean(tokens[10]);
      uniqueId = playerId*10000+botId;
    }

    Bot()
    {
    }

    double distanceFrom(Bot other)
    {
        return distanceFrom(new Point(other.x,other.y));
    }

    double distanceFrom(Point other)
    {
        double deltaX = x - other.x;
        double deltaY = y - other.y;
        return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    }

    void update(Bot other)
    {
      x = other.x;
      y = other.y;
      health = other.health;
      fired = other.fired;
      hitX = other.hitX;
      hitY = other.hitY;
      shield = other.shield;
    }
  }

  static class Configuration
  {
    BotState groupState = BotState.INIT;
    HashMap<Integer,Bot> bots = new HashMap<>();
    boolean isOpponentInitiated;
    int playerId;

    Configuration(String line) throws Exception
    {
      String[] tokens = line.split("\\[");
      playerId = extractInt(tokens[0].split(",")[1]);

      for (String token : tokens[1].split("\\|"))
      {
        Bot bot = new Bot(token);
        bots.put(bot.uniqueId,bot);
      }
    }
  }

  /**
   * Reads a line of text from the input stream. Blocks until a new line character is read.
   * NOTE: This method should be used in favor of BufferedReader.readLine(...) as BufferedReader buffers data before performing
   * text line tokenization. This means that BufferedReader.readLine() will block until many game frames have been received.
   * @param in a InputStream, nominally System.in
   * @return a line of text or null if end of stream.
   * @throws IOException
   */
  static String readLine(InputStream in) throws IOException
  {
     StringBuilder sb = new StringBuilder();
     int readByte = in.read();
     while (readByte>-1 && readByte!= '\n')
     {
        sb.append((char) readByte);
        readByte = in.read();
     }
     return readByte==-1?null:sb.toString().replace(",{", "|").replaceAll("}", "");

  }

  final static class Point
  {
    public Point(int x2, int y2) {
        x=x2;
        y=y2;
    }
    int x;
    int y;
  }

  public static int extractInt(String token)
  {
    return Integer.parseInt(token.split(":")[1]);
  }

  public static boolean extractBoolean(String token)
  {
    return Boolean.parseBoolean(token.split(":")[1]);
  }

  static void distributePower(Bot bot, int fire, int move, int shield)
  {
    out.println("{\"Cmd\":\"POWER\",\"BID\":"+bot.botId+",\"FPow\":"+fire+",\"MPow\":"+move+",\"SPow\":"+shield+"}");
//  viewer.distributePower(bot.botId, fire, move, shield);
  }

  static void shield(Bot bot)
  {
    distributePower(bot,0,0,12);
    bot.power=Power.SHIELD;
  }

  static void move(Bot bot, int x, int y)
  {
    distributePower(bot,0,12,0);
    out.println("{\"Cmd\":\"MOVE\",\"BID\":"+bot.botId+",\"X\":"+x+",\"Y\":"+y+"}");
  }
  static void target(Bot bot, Bot target)
  {
    out.println("{\"Cmd\":\"TARGET\",\"BID\":"+bot.botId+",\"TPID\":"+target.playerId+",\"TBID\":"+target.botId+"}");
  }

  static void fire(Bot bot)
  {
    distributePower(bot,12,0,0);
    bot.power=Power.FIRE;
  }
}

To compile:
javac TriggerHappy.java
To run:
java TriggerHappy

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Simplify matrix input!
I have written a few challenges related to matrices, and common for all are that I use a format like the one below when representing the matrices, both in examples and in test cases:
16    2    3   13
 5   11   10    8
 9    7    6   12
 4   14   15    1

This is likely a cumbersome format in many languages.

Challenge:
Write a program/function that can take a matrix on the form given in the top as input (directly copy/pasted from this post), and output the same matrix on all of the three other conventional formats shown below.
The input format:
Numbers separated by a varying number of spaces, and newlines to represent rows (see test cases).

The number of spaces between numbers are not guaranteed to be consistent. You may however assume that the last digit in each column align (if that helps any).
There can be both integers and floats, and they can be positive, negative or zero. A matrix will not contain integers and floats at the same time.
You may assume that no number is longer than 10 characters, including the minus and decimal point for negative floats.
You may assume that there are the same number of entries in each row and in each column.
There won't be any empty input matrices, but there can be single numbers, or matrices with only one row or column.

You may in these cases choose between the output formats shown in the test cases

Your program/function must handle the input if it's directly copied from this post and pasted into the interpreter (STDIN or as function argument or something equivalent). You may have whatever you like (brackets, quotation marks, parentheses) in front of, and/or after the matrix, but you must consider the matrix a sequence of characters that can't be altered (that includes the newlines).
To clarify: Assume your function/program is called f and the matrix is:
1 -2
3  5
6  7

then you may give the matrix as function arguments like this (and infinitely many other options):
f(1 -2
3  5
6  7)

f([1 -2
3  5
6  7])

f("""1 -2
3  5
6  7""")

If your language can't, in any way, take the copy/pasted matrix as input then I'm afraid you have to pick another language.

The output format:
You should output the matrix on the following three formats (order doesn't matter):
[[16, 2, 3, 13], [5, 11, 10, 8], [9, 7, 6, 12], [4, 14, 15, 1]]
{{16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}}
[16, 2, 3, 13; 5, 11, 10, 8; 9, 7, 6, 12; 4, 14, 15, 1]

You may separate the three outputs however you want (e.g. a newline)
You must output the numbers using the same precision as the input (for instance, you must not trim the number of decimals, nor output integers as floats).
The spaces are mandatory
You must use - for negative numbers, not _ or similar.

Test cases:
16    2    3   13
 5   11   10    8
 9    7    6   12
 4   14   15    1
----
[[16, 2, 3, 13], [5, 11, 10, 8], [9, 7, 6, 12], [4, 14, 15, 1]]
{{16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}}
[16, 2, 3, 13; 5, 11, 10, 8; 9, 7, 6, 12; 4, 14, 15, 1]

0.14778   0.27114   0.24415
0.45997   0.12287   0.67470
0.28945   0.37928   0.51887
----
[[0.14778, 0.27114, 0.24415], [0.45997, 0.12287, 0.6747], [0.28945, 0.37928, 0.51887]]
{{0.14778, 0.27114, 0.24415}, {0.45997, 0.12287, 0.6747}, {0.28945, 0.37928, 0.51887}}
[0.14778, 0.27114, 0.24415; 0.45997, 0.12287, 0.6747; 0.28945, 0.37928, 0.51887]

-0.0398301   0.2403455  -0.2253368   0.3565870   0.0605803   0.0830780
-0.3254422  -0.1185191  -0.2989537   0.1647319   0.3621135   0.2018815
-0.0022281  -0.3362287  -0.3568447   0.4419063   0.3801872  -0.2847033
---
[[-0.0398301, 0.2403455, -0.2253368, 0.3565870, 0.0605803, 0.0830780], [-0.3254422, -0.1185191, -0.2989537, 0.1647319, 0.3621135, 0.2018815], [-0.0022281, -0.3362287, -0.3568447, 0.4419063, 0.3801872, -0.2847033],]
{{-0.0398301, 0.2403455, -0.2253368, 0.3565870, 0.0605803, 0.0830780}, {-0.3254422, -0.1185191, -0.2989537, 0.1647319, 0.3621135, 0.2018815}, {-0.0022281, -0.3362287, -0.3568447, 0.4419063, 0.3801872, -0.2847033},}
[-0.0398301, 0.2403455, -0.2253368, 0.3565870, 0.0605803, 0.0830780; -0.3254422, -0.1185191, -0.2989537, 0.1647319, 0.3621135, 0.2018815; -0.0022281, -0.3362287, -0.3568447, 0.4419063, 0.3801872, -0.2847033]

0       4       1       0
0       0      -6       0
0       1       4      -3
2       0       0       8
0       0       0       0
----
[[0, 4, 1, 0], [0, 0, -6, 0], [0, 1, 4, -3], [2, 0, 0, 8], [0, 0, 0, 0]]
{{0, 4, 1, 0}, {0, 0, -6, 0}, {0, 1, 4, -3}, {2, 0, 0, 8}, {0, 0, 0, 0}}
[0, 4, 1, 0; 0, 0, -6, 0; 0, 1, 4, -3; 2, 0, 0, 8; 0, 0, 0, 0]

1
----
[1]     (or [[1]])
{1}     (or {{1}})
[1]     (or 1)

1 2
----
[1, 2]  (or [[1, 2]])
{1, 2}  (or {{1, 2}})
[1, 2]

4
5
----
[[4], [5]]
{{4}, {5}}
[4; 5]

I'm fully aware of this, but in this challenge, the cumbersome I/O format is the whole point. The challenge will be all about formatting the output in some languages, while reading the input will be the hardest part in other languages.
Please do not be discouraged if reading the input is hard, those submissions might be the most interesting ones. Short isn't necessarily the same as impressive. And as always, explanations are encouraged!

Retina, 52 bytes
This answer is based on my Perl answer, with the help of Martin Ender for the golfing with Retina.
^ *
[
$
]
\s+
,
m):`.+
[$&]
*T`[]`{}
], .
;
^.|]$

Try it online!
The explanations can be found on my Perl answer. The differences are:
*
[
$
]

Instead of s/^ *(.+)/[$1]/gm to both remove the leading spaces and add brackets around the lines.
^.|]$

To remove the leading and trailing brackets for the third output.

Retina, 57 54 bytes
Byte count assumes ISO 8859-1 encoding.
m`^ +

¶
] [
 +
,
:`.+
[[$&]]
*T`[]`{}
], .
;
^.|]$

Try it online!
The TIO link currently prints no linefeeds between the three formats but that's because it uses an unstable commit. The program does print the intermediate linefeeds in Retina 0.8.2.
Explanation
m`^ +

Get rid of leading spaces on each line.
¶
] [

Replace linefeeds with ] [.
 +
,

Replace all runs of spaces with a comma and a space.
:`.+
[[$&]]

Wrap the entire thing in [[...]] which completes the first format. Print the result.
*T`[]`{}

Replace brackets with braces and print the result without actually changing the working string (i.e. the first format is restored after this is printed).
], .
;

Replace ], [ with a semicolon and a linefeed.
^.|]$

Remove the first [ and the last ]. This completes the third format.

Scala, 183 181 149 bytes
Try it online!
New version, using String replacements and regexes:
(x:String)=>{val d=x.replaceAll("\n *","; ").replaceAll("(?<!;) +",", ");(s"[[${d.replace("; ","], [")}]]",s"{{${d.replace("; ","}, {")}}}",s"[$d]")}

The new version has the same semantics and usage as the old version using split, map and mkString.
Old version, using split, map and mkString:
Edit: Redundant character class for space removed
(x:String)=>{val d=x.split("\n").map(_.trim.split(" +").mkString(", "));(d.map(x=>s"[$x]").mkString("[",", ","]"),d.map(x=>s"{$x}").mkString("{",", ","}"),d.mkString("[","; ","]"))}

Lambda. Execute in REPL. Accepts input as triple-quoted String parameter, returns output as a 3-tuple of the required outputs. The REPL renders tuples separated by commas, bordered by parentheses.
Explanation:
New version:
Mostly the same logic as the other regex-based answers, except for the tricky lookbehind to handle leading spaces on lines.
Old version:
We split the input matrix representation into a 2D String array, then map it to a 1D array by collapsing the inner arrays by separating the elements with , . Finally, we just create the different outputs by collapsing the 1D arrays by using the required newline separators and boundary markers (prefixes and suffixes). It's all implemented via split (reading), map (transforming) and mkString (collapsing).
Example REPL session:
scala> val r=(x:String)=>{val d=x.split("\n").map(_.trim.split(" +").mkString(", "));(d.map(x=>s"[$x]").mkString("[",", ","]"),d.map(x=>s"{$x}").mkString("{",", ","}"),d.mkString("[","; ","]"))}

scala> r("""16    2    3   13
     |  5   11   10    8
     |  9    7    6   12
     |  4   14   15    1""")
res12: (String, String, String) = ([[16, 2, 3, 13], [5, 11, 10, 8], [9, 7, 6, 12], [4, 14, 15, 1]],{{16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}},[16, 2, 3, 13; 5, 11, 10, 8; 9, 7, 6, 12; 4, 14, 15, 1])

For the few-element edge cases, this provides the desired output.

Far better than the other Scala answer, well done!

Japt, 63 53 bytes
This was coming in at 44 bytes before I noticed that the spacing in the output was mandatory.
·®¸f
"[[{q"],["}]]
\{\{{q"},\{"}}}
[{q';}]"r",|;"_+S

Test it

Explanation
          :Implicit input of string U
·         :Split to an array on newlines.
®         :Map over the array.
¸         :Split each element to an array on spaces.
f         :Filter to remove empty elements from the subarrays.
"[[       :Start building the output string. In Japt strings, anything enclosed in {}s will be evaluated before being added to the string.
{q"],["}  :Join the array to a string using ],[ The sub-arrays will be cast to comma separated strings in the process.
]]        :That's the first line done.
\{\{      :The start of the second line. A few bytes have to be sacrificed to esapce the {s
{q"},\{"} :Join the array to a string using },{
}}        :That's the second line done.
[         :And on to the last line.
{q';}     :This time we join the array with a semi-colon.
]"        :And that's the string completed.
r         :Except we still need to replace...
",|;"     :  All occurrences of a comma or a semi-colon with...
_+S       :  Itself and a space.
          :Implicit output of resulting string.

Well done. The best I could do was somewhere around 60 bytes...

Perl 5, 71 bytes
69 bytes of code + -p0 flags.
s/^ *(.+)/[$1]/gm;s/\s+/, /g;$_="[$_]
{".y/[]/{}/r."}
".s/], \[/; /gr

Try it online!
Explanations
s/^ *(.+)/[$1]/gm; adds [] around each line while removing the leading spaces.
s/\s+/, /g; replaces runs of spaces and newlines with a comma and a space.
The first output is then obtained by surrounding with braces: [$_].
The second needs to replace braces with curly bracket (y/[]/{}/r) and surround with curly brackets "{" ... "}".
For the third, ], [ are replaces with a semicolon and a space (s/], \[/; /gr).

After writing this solution, I tried adpating Martin Ender's Retina answer, but it ended up 10 bytes longer (TryItOnline):
s/^ +//gm;s/
/] [/g;s/ +/, /g;$_="[[$_]]
{{".y/[]/{}/r."}}
[".s/], \[/; /gr."]"

For this version, see Martin's answer for the explanations.

Javascript (ES6), 121 110 106 bytes
-15 bytes thanks to @Shaggy and @Justin
m=>`[[${(a=m.split`
`.map(x=>x.match(/\S+/g).join`, `)).join`], [`}]]
{{${a.join`}, {`}}}
[${a.join`; `}]`

Example code snippet:

f=
m=>`[[${(a=m.split`
`.map(x=>x.match(/\S+/g).join`, `)).join`], [`}]]
{{${a.join`}, {`}}}
[${a.join`; `}]`
console.log(f(
`1 -2
 3  5
 6  7`
))

Save 4 bytes by changing map(x=>x.trim().replace(/ +/g,", ")) to map(x=>x.match(/\S+/g).join`, `).

MATL, 60 bytes
`jtU&D32', 'XHYXw]xXhH&Zc91wh93htD[]&D{}&DXED&GxvUH&4$'; 'TD

Try it online!
Thanks a lot to Luis Mendo for shaving off a quarter of my bytecount in a masterclass in chat.
Paste the input, followed by an empty line.
% Act I: Taking input.

`jt             w]    % Take input line by line until an empty line is encountered.
   U                  % Convert string input to numerical row array
    &D                % Convert back to string, adding brackets and single spaces
      32', 'XHYX      % Add commas before the spaces. Store ',  ' in clipboard H.

% Act II: Nested square brackets

x                     % Discard the tab character
 Xh                   % Concatenate all strings as cell array.
   H&Zc               % Join all the strings together, using clipboard H as a separator
       91wh93h        % Wrap in square brackets (ASCII 91 and 93)
              tD      % Display a copy of the result.

% Act III: Nested curly brackets

[]&D{}&D              % Convert empty array and cell array to string.
        XE            % Use to substitute square for curly brackets.

% Act IV: MATLAB-style input.

&Gxv                  % Get all the input again, discard the tab, and concatenate vertically.
    U                 % Convert to numerical
     &4$     TD       % Convert to string, using row- and column separators
        H'; '         % Namely, clipboard H and a semicolon.

05AB1E,  45  44 bytes
|„  ð:ðδÛ˜ð¡„, ý''KD…[ÿ]=„[]„{}‡,"], ["„; :=

Try it online!
First output
|                           # push a list of the inputs
 „  ð:                      # replace any instance of 2 spaces with 1 space
      ðδÛ                   # remove any leading spaces
         ˜                  # flatten to a 1D list
          ð¡                # split on spaces
            „, ý            # merge on ", "
                ''K         # remove all single quotes
                   D        # duplicate for use in output 3
                    …[ÿ]    # interpolate between square brackets
                        =   # print without popping

Second output
„[]„{}‡,                    # translate square brackets to curly brackets and print

Third output
                            # the copy from the first output is used here
 "], ["„; :                 # replace "], [" with "; "
           =                # print

Python 2, 163 152 150 145 bytes
-5 bytes thanks to Felipe Nardi Batista who suggested the use of splats (sorry, I just need an excuse to say that word :P).
import re
a=str.replace
def f(s):r=a(`[re.findall('[\.\d]+',i)for i in s.split('\n')]`,"'",'');print r,a(a(r,*']}'),*'[{'),a(r[1:-1],'], [','; ')

Try it online!

Ah, splats... Thanks!

Python 2, 143 bytes
import re
b=re.sub
def f(s):s='[['+b('\n','], [',b(' +',', ',b('\n +','\n',s)))+']]';print s,b('\[','{',b('\]','}',s)),b('\], \[','; ',s)[1:-1]

Try it online!

Python 3, 184 178 174 173 169 163* 157* 153 bytes
Input/Output Format: Output with a space between the matrices and input with this function call (as shown on TIO):
g("""<paste matrix here>""")

This is the function :
def g(s,r=str.replace):a=str([[[int,float]['.'in y](y)for y in x.split()]for x in s.split('\n')]);print(a,r(r(a,*'[{'),*']}'),'['+r(a,'], [','; ')[2:-1])

Try it online!

*Saved a 6 bytes thanks to @officialaimm (from 169 to 163 bytes).
*Saved 4 bytes thanks to @FelipeNardiBatista.

Explanation to come after further golfing.

V, 41 bytes
òJé;òÓ¨ä©ó«/±,
yss]Y.pkÓ; /], [
Ùòcs]}f[

Try it online!
Explanation
òJé;ò            Join all lines with `; ` (trailing single space)
     Ó¨ä©ó«/±,   :s/\v(\d)\s+/\1, /g
yss]             Surround everything with brackets (completes [x,x;x,x])
Y.pk             (Y)ank, surround with brackets again, (p)aste.  Adds [[x,x;x,x]]
    Ó; /], [     :s/; /[, ]/g (transforms to [[x,x], [x,x]])
Ù                Duplicate this line
 ò               recursively
  cs]}           (c)hange (s)urrounding [] with {}
      f[         go to the next [ until there are none

C, 415 bytes
#import<stdio.h>
#define A(a,c,o)for(l=strlen(a)-o,k=0;c[k];)a[l+k]=c[k++];
j,k,l;main(i){char s[999],a[999]="[",b[999]="{",c[999]="[",t[]=" ";for(;fgets(s,999,stdin);){A(b,"{",0)A(a,"[",0)for(i=0;s[i];++i){j=0;for(;s[i]-32&&s[i]-10&&s[i];++i){j=1;t[0]=s[i];A(c,t,0)A(b,t,0)A(a,t,0)}if(j){A(c,", ",0)A(b,", ",0)A(a,", ",0)}}A(c,"; ",2)A(b,"}, ",2)A(a,"], ",2)}A(c,"]",2)A(b,"}",2)A(a,"]",2)puts(a);puts(b);puts(c);}

It's a monster and waaayyyy too long, but I'm done with it. Should have gone for a different approach probably.
Try it online!
Second test case
|
Third test case
|
Fourth test case
|
Fifth test case
| Sixth test case
| Seventh test case

Pip -r, 48 45 40 bytes
YP(RPg@XN)R';kPTMyR"], [""; "yTR"[]""{}"

Takes input from stdin. Outputs formats in the order 1, 3, 2. Try it online!
Explanation
                 Preset variables used: XN is regex matching numbers, k is ", "
YP(RPg@XN)R';k
     g           With -r flag, g is a list of lines from stdin
      @XN        Find all numbers in (elements of) g
   RP            Apply Pip's built-in repr, which wraps lists in [] and separates items
                   with ; (e.g. [[1;2];[3;4]])
  (      )R';k   Replace the semicolons with ", " to obtain format #1
YP               Print and yank into y variable

PTMyR"], [""; "
 TMy             Trim the first and last characters from y
    R"], [""; "  Replace the delimiters between sublists with "; " to obtain format #3
P                Print

yTR"[]""{}"
yTR              In y, transliterate
   "[]"          [ and ]
       "{}"      into { and } (format #2)
                 Autoprint (implicit)

SCALA, 590 bytes
Was hard, but I think I'm done with it
var o=s.replaceAll("  *"," ").replaceAll("\n ","\n")
var z=o.split("\n")
var h=z.length
var k=new Array[Array[String]](h)
for(i<-0 to h-1)k(i)=z(i).split(" ")
var u=k.length-1
print("{")
for(i<-0 to u){print("{")
for(j<-0 to k(i).length-2)print(k(i)(j)+", ")
print(k(i).last)
print("}")}
print("}[")
for(i<-0 to u){print("[")
for(j<-0 to k(i).length-2)print(k(i)(j)+", ")
print(k(i).last)
print("]")}
print("][")
for(i<-0 to u-1){for(j<-0 to k(i).length-2)print(k(i)(j)+", ")
print(k(i).last)
print("; ")}
for(j<-0 to k(k.length-1).length-2)print(k(u)(j)+", ")
print(k.last.last)
print("]")

Quick explanation : I take input surrounded by triple quotes, then take off unrequired spaces ; split the string two times (once for lines and once for columns) ; and I print with my three routines. It might be possible defining a function to mutualize, but I don't know how.
Try it online!

This is horrible. I now have to post a Scala answer.

Have an upvote for effort, though.

You might want to take a look at https://codegolf.stackexchange.com/a/129356/48620 to see what might be possible with Scala. Using it like one would use pre-1.5 Java is only scratching the tip of the iceberg.

Look into something cool called "string interpolation", and the utility methods on Seq, which Array provides. map and mkString being 2 very relevant ones for the job.

Also, where do you get s (I'm assuming that that is your input String) from? Is this supposed to be an REPL session? Is this defined in a method? A lambda? Please clarify in your answer. You should include the lambda or method header in your code, not leave it in the TIO link, if you do not specify in your answer that you have done so.

Plus, your output is wrong, which makes me want to retract my upvote - there are no commas between the brackets, as dictated by the output format.

Sorry for being away this weekend. I am correcting this comma issue. And about you telling "this is horrible" I'm totally new to this exercise, so I have to practice. I'll look at your link soon though ; thanks for it.

In fact I'm getting it though :/ just correcting this issue make the code faaar too much bigger. I really have to found another algorithm - I think the problem lies here. I mean I'll redo it entirely.

"It's horrible" is actually more of joke than it is serious, but I'd seriously suggest using a language you're more familiar with for code-golf. Optimising program character count is easier when you know all the folds where your language bends.

:'( As I said, I'm a beginner in code-golf. I signed in to PPCG last week, and discovered a new programming world. In fact when I discovered ScaLa like three years ago, I found it superb in its syntax ; I now see (with your solution) that it is even able to do more. So that's my goal, and I won't forgive on coding with ScaLa.

Let us continue this discussion in chat.

Jelly, 37 bytes
j€⁾, j⁾; ⁾[]j
ỴḲLÐf$€VµŒṘṄ“[]“{}”yṄȧÇ

A full program printing the three formats on three lines.
Try it online!
How?
j€⁾, j⁾; ⁾[]j - Link 1, create the 3rd format (semicolon-style): list of lists
  ⁾,          - literal [',', ' ']
j€            - join for €ach (place ", " between the elements of each row)
      ⁾;      - literal [';', ' ']
     j        - join (place "; " between the rows)
         ⁾[]  - literal ['[', ']']
            j - join (surround the whole result with a pair of brackets)

ỴḲLÐf$€VµŒṘṄ“[]“{}”yṄȧÇ - Main link: list of characters
Ỵ                       - split at newlines
     $€                 - last two links as a monad for €ach row:
 Ḳ                      -   split at spaces
   Ðf                   -   filter keep those for which the following is truthy:
  L                     -     length (this removes all the empty lists "between" spaces)
       V                - evaluate as jelly code (yields a list of lists of numbers)
        µ               - monadic chain separation, call that x
         ŒṘ             - get a Python string representation of x
           Ṅ            - print that (the 1st format) plus a newline, and yield it
            “[]“{}”     - literal [['[', ']'],['{', '}']]
                   y    - translate (converts all '[' to '{' and all ']' to '}')
                    Ṅ   - print that (the 2nd format) plus a newline, and yield it
                      Ç - call the last link as a monad with argument x
                     ȧ  - logical and
                        - implicit print of the result (the 3rd format)

R, 132 bytes
function(x,p=paste0,g=gsub)cat(z<-p('[[',g('\n','], [',y<-g('[:blank:]',', ',x)),']]'),chartr('[]','{}',z),p('[',g('
','; ',y),']'))

Try it online!
an anonymous function. Takes input like
f('1 -2
3 5
6 7')

It prints them in the same order as the test cases, but with spaces as the separator.
Explanation:
It first swaps spaces with ,  and saves the result as y. Then it swaps newlines with ], [, puts [[ and ]] on either end, and saves the result of that as z.
Next, chartr switches [ with { and ] with } in z.
Finally, it takes y, swaps newlines with ;  and puts [ and ] on either end.
Then all the results are passed in that order to cat which prints them out, all nicely formatted, and separated by a single space.
Mildly ungolfed:
function(x)
  cat(
    z<-paste0('[[',gsub('\n','], [',y<-gsub('[:blank:]',', ',x)),']]'),
    chartr('[]','{}',z),
    paste0('[',gsub('\n','; ',y),']'))

Java 8 with Netbeans 8+, 209 bytes
Count is 208 from the code, plus 1 bytes to run it by pressing F6.
Cumbersome answer for cumbersome challenge :p
interface M{static void main(String[]a){String s="";s=s.trim().replaceAll(" +",", ").replaceAll("\n(, )?","; ");System.out.println("["+s+"]\n[["+s.replace("; ","], [")+"]]\n{{"+s.replace("; ","}, {")+"}}");}}

How to use?
Within Netbeans, paste this code in a file called M.java. Then copy the matrix you want to use. Then between the two consecutive characters "", press ctrl+v as required by the challenge.
Now press F6! This will compile the code, run it and output the expected matrix representations.

Doesn't this need to be in all three output formats?

There! That's what I missed! :D Fixing that now.

@StewieGriffin This is advantaging languages that use STDIN by default or ones that don't care about newlines, I could also say that "copy/pasting" in any major Java IDE automatically formats changes the copy/pasted newlines into visual \n, making the result what you saw. So I don't quite get it, to be frank :s

@OlivierGrégoire I'm fully aware that this is advantaging some languages, especially those that can handle the format without any special processing. I even mention this explicitly in the challenge text. Remember that you aren't competing against Jelly, Javascript or Python, you're using Java. It has very different functionality, and can't be fairly compared to the others. I always follow the rules about avoiding cumbersome I/O formats that might give some languages an unfair advantage, but in this particular challenge, parsing the input is a large part of it.

Mathematica, 129 bytes
s=StringSplit
r=StringReplace
Print[#,n,#~r~{"{"->"[","}"->"]"},n,#~r~{"{{"->"[","}}"->"]","}, {"->"; "}]&@ToString@s@s[#,n="
"]&

The third and fourth lines together define a pure function taking a string as input; for example, if we set f=Print...&, then the last test case would be called as:
f@"4
5"

The snippet
ToString@s@s[#,n="
"]

parses the input string as a matrix (of strings—we never try to interpret the entries as numerical quantities) and converts the resulting expression back to a string; this automatically generates the output format with curly braces. Then Print[#,n,#~r~{"{"->"[","}"->"]"},n,#~r~{"{{"->"[","}}"->"]","}, {"->"; "}] prints that output format and the two others, separated by newlines, by using straightforward string replacement rules.

05AB1E, 34 bytes
|εð¡õK}€ï"ÿ"Ð„[]„{}‡s¦¨"], ["„; :»

Try it online!
ε...} has been replaced with vy...}) on TIO since it hasn't been pulled there yet.

@JonathanAllan Thanks, has been fixed.

Cool, now it just needs an explanation of how it works :)

@JonathanAllan Sorry don't have time atm...

C# (.NET Core), 214 bytes
(s)=>{var result=Regex.Replace("[["+Regex.Replace(s.Replace("\n","], [")," +(\\d)",", $0")+"]","  +"," ").Replace("[, ","[");return$"{result}]\n{result.Replace('[','{').Replace(']','}')}}}\n[{result.Replace("[","").Replace("],",";")}";};

Try it online!
Takes the Matrix as a string, returns the three formats as a single string separated by newlines.

Since this answer, I've become more certain that the using statement for libraries other than the base System should be included in the bytecount. I'll leave it in its current form for now, but the statement using System.Text.RegularExpressions is required adding (by my count) 37 additional bytes.

Charcoal, 38 bytes
≔Ｅ⪪θ¶⪫Φ⪪ι λ, θＥ⪪[]{}²⪫ι⪫Ｅθ⪫ιλ, ⪫[]⪫θ;

Try it online! Note: Trailing space. Link is to verbose version of code. Charcoal has a multiline input option delimited using [""" and """]. Explanation:
   θ                Input string
  ⪪ ¶               Split on newlines
 Ｅ                  Map over each line
        ι           Current line
       ⪪            Split on spaces
      Φ   λ         Filter out empty strings
     ⪫     ,        Join with `, `
≔            θ      Assign resulting array to variable

This takes the input and prepares it by splitting it into lines and normalising the separators.
 ⪪[]{}²             Split `[]{}` into substrings of length 2
Ｅ                   Map over the substrings
          Ｅθ        Map over array from above
            ⪫ιλ     Wrap each element with the substring
         ⪫     ,    Join elements with `, `
       ⪫ι           Wrap with the substring
                    Implicitly print each result on a separate line

This handles the [[ ... ], [ ... ]] and {{ ... }, { ... }} cases.
    θ               Array from above
   ⪫ ;              Join elements with `; `
⪫[]                 Wrap result with `[]`
                    Implicitly print

This handles the [ ... ; ... ] case.
Before I golfed a byte off the above solution I used to have two 39-byte solutions; this is the other:
⮌Ｅ⪪[]{}[]²⪫ι⪫ＥＥ⪪θ¶⪫Φ⪪λ ν, ⎇κ⪫ιλλ⁺§;,,κ

Try it online! Note: Trailing space. Link is to verbose version of code. Explanation:
  ⪪[]{}[]²                              Split `[]{}[]` into substrings of length 2
 Ｅ                                      Map over the substrings
                θ                       Input string
               ⪪ ¶                      Split on newlines
              Ｅ                         Map over each line
                     λ                  Current line
                    ⪪                   Split on spaces
                   Φ   ν                Filter out empty strings
                  ⪫     ,               Join with `, `
             Ｅ                          Map over each line
                          ⎇κ   λ        If outer index is zero, just use the line
                            ⪫ιλ         Otherwise wrap the line in the substring
            ⪫                   ⁺§;,,κ  Join with `; ` or `, ` per outer index
          ⪫ι                            Wrap in the substring
⮌                                       Reverse the order of the results
                                        Implicitly print each result on a separate line

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/