# 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.

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 , 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? – isaacg Jun 30 '17 at 2:46
• Is your [10] monolith not [11] ? – TessellatingHeckler Jun 30 '17 at 6:47
• Wouldn't the undefined one just be an empty array? – Solomon Ucko Jul 1 '17 at 2:03
• @isaacg yes, that would be okay – Graviton Jul 1 '17 at 3:01
• @SolomonUcko technically yes, though to make it simpler for all languages I decided to not have them deal with it. – Graviton Jul 1 '17 at 3:02

# 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 Jun 30 '17 at 7:16
• @V.Courtois I don't see why not, since we'll probably never get such input. – Erik the Outgolfer Jun 30 '17 at 7:44
• Okay, it's because I saw that some other answers take it in count – V. Courtois Jun 30 '17 at 8:51
• @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. – Jonathan Allan Jun 30 '17 at 11:15
• Down-voter - would you care to explain your reasons? – Jonathan Allan Jun 30 '17 at 11:24

# Jelly, 11 bytes

ỴṚZi€”_ỊÐḟ’


Try it online!

• Wow, you answered that fast. – Graviton Jun 29 '17 at 22:28
• @Graviton Hehe one should always have this page open somewhere. ;) – Erik the Outgolfer Jun 29 '17 at 22:29
• Explanation, please! – Shaggy Jun 29 '17 at 22:51

# JavaScript (ES6), 79 78 bytes

-1 byte thanks to @Shaggy

a=>a.map((b,i)=>b.replace(/_/g,(_,j)=>o[j]=a.length-i-1),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-1),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 Jun 30 '17 at 13:37 • @Shaggy Nice, I totally didn't think of using replace. Thanks! – Justin Mariner Jun 30 '17 at 20:45 # 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. – aschepler Jul 2 '17 at 12:22 # 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. # 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 # Python 2, 75 bytes lambda s:[x.index('_')for x in map(None,*s.split('\n')[::-1])if'_'in x[1:]]  Try it online! ## 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.

$s1 = @' _ | | _ | | _ | | | | | | | | _ _| |_| |___| |____| |_ '@-split"r?n"$s2 = @'
_
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
'@-split"r?n"

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

$s5 = @' _ _ _ _ _ _ | | _ | | _ | | _ | | _ | | | |_| |_| |_| |_| |_| |_| |_| |_| |_| | '@-split"r?n"  # 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  # 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 Jun 30 '17 at 1:48 • @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! – Neil Jun 30 '17 at 7:39 • @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. – Martin Ender Jun 30 '17 at 7:50
• @FryAmTheEggman And here is a fix to your approach, but it ends up at 46 bytes. – Martin Ender Jun 30 '17 at 7:56
• @MartinEnder 45 perhaps? Try it online! – Neil Jun 30 '17 at 8:01

# Java 8, 133117116 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 Jun 30 '17 at 8:09
• @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. :) – Kevin Cruijssen Jun 30 '17 at 8:23
• I only managed to get it down to 150 using Linq but there should be room for golfing it still. – TheLethalCoder Jun 30 '17 at 9:39
• 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 Jun 30 '17 at 13:19
• 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). – Olivier Grégoire Jul 1 '17 at 13:26

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 Jun 30 '17 at 10:45
• @Jules: Yeah, I usually do – siracusa Jun 30 '17 at 11:19

# 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!

# APL (Dyalog), 14 bytes

0~⍨⍳∘≢+.×'_'=⊖


with ⎕IO←0

Try it online!

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

# MATL, 12 bytes

&nxG2\&fx-Xz


Input is a char matrix, with ; as row separator.

# C#, 150144 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(),
})));

}
}


# 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. – Olivier Grégoire Jul 1 '17 at 13:21
• 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! :) – Kevin Cruijssen Jul 1 '17 at 16:17
• @KevinCruijssen Thanks! Converting the contents of that first for loop to a bodyless for loop was inspiring! Super clever. – Michael Jul 1 '17 at 17:27
• @Michael You're welcome. :) Oh, and if you haven't seen it yet: Tips for golfing in Java and Tips for golfing in <all languages> might be interesting to read through. Helped me a lot when I first started (and still does sometimes). – Kevin Cruijssen Jul 1 '17 at 18:43

# MATL, 10 bytes

ooYssqtO>)


Input is a padded character matrix.

Try it online!

# Mathematica, 4847 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.

# 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 (ES6), 108104 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 – Justin Mariner Jun 30 '17 at 0:58
• Thanks @JustinMariner! I'm stoked about the variable initialization as unused parameters given to Array.map, that's a cool trick. – alexanderbird Jun 30 '17 at 16:58
• Do you really need to assign the RegEx to a variable? You could use it directly in the exec and save a few bytes. – Shaggy Jun 30 '17 at 21:26
• 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? – alexanderbird Jun 30 '17 at 21:51
• @shaggy I forgot to tag you in my last comment – alexanderbird Jul 1 '17 at 4:14

## 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. – Business Cat Jun 30 '17 at 13:30

# 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)


# Pyth, 1915 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


# 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)


Takes in a multiline string. Credit for the setup (header and footer) goes to @GarethPW

# Python 2, 29 bytes

lambda s:len(s.split('\n'))-1
`

Try it online!

This will simply split the array by newline and return length-1.

• This doesn't fulfill the entire challenge. You must return an array or list with all the heights, not just the tallest. – Scott Milner Jun 30 '17 at 22:00