I'm Lazy*: Top-left align my text

* and don't have a word processor with top-left align support :D

Take several lines of input, with at least four unique characters of your choice including newline and space. The input can also be taken as a space-padded matrix of characters. Squash it upwards, then squash it left. Output this, with any amount of trailing newlines and spaces.

To squash upwards

For any non-space character "below" a space, swap their places, until there are no more non-space characters below spaces.

To squash left

For each line, remove all spaces.

Example (with abcdefghjkl \n):

With the input (STDIN, function arguments, etc.):

a b c d  e
ff ggg h i
jj kk lll


Squash upwards:

afbgcgdhle
fjj gk l i
k    l


Squash left:

afbgcgdhle
fjjgkli
kl


Output this text. (STDOUT, function return value, etc.)

More examples

input
=>
output
-------
a b c
=>
abc
-------
a

c
=>
a
c
-------

=>
------- ^ note that trailing spaces are allowed so a single line with a space is valid here
a
=>
a
-------

a
=>
a
-------
ab
c
=>
ab
c
-------
abc
d e
f g
=>
abc
de
fg
-------
abc
d
f g
=>
abc
dg
f

This is , shortest answer in bytes per language wins.

Finding out which academic journal requires submissions to be top-left aligned is left as an excercise for the reader.

• Some more test cases would be useful. Also, what corner cases do we have to consider: cna the input consist of a single line? Can a line contain a single character? Can that single character be a space? Jun 2, 2021 at 14:44
• I'll save my upvote for when you have added the cases, and removed that link Jun 2, 2021 at 14:55
• I forgot to say in my sandbox comments to remove the irrelevant link.
– qwr
Jun 2, 2021 at 15:01
• @Wzl I can only guarantee one upvote. But quite a few people seem to agree with my comment... Jun 2, 2021 at 15:03
• An interesting superset of this challenge might be to add a second input which would be 1 of 4 distinct values and "aligning" the matrix to the corresponding corner. Jun 2, 2021 at 21:26

APL (Dyalog Unicode), 11 bytes

~∘' '⍤1∘⍉⍣2


Try it online!

A train taking and returning a character matrix.

         ⍣2  ⍝ repeat 2 times:
⍉    ⍝ transpose the character matrix
~∘' '        ⍝ remove spaces
⍤1      ⍝ in each row
⍝ each row is padded with spaces to keep the matrix shape


APL (Dyalog Extended), 8 bytes

-2 bytes thanks to Bubbler!

In the extended variant ⌂ provides easy access to the dfns namespace, which has a function to drop all blanks.

⌂dab∘⍉⍣2


Try it online!

• With dab, you can remove ⍤1 too (it works fine with matrices): Try it online! Jun 2, 2021 at 23:31

Jelly, 5 bytes

Zḟ€⁶Z


Try it online!

Zḟ€⁶Z  Main Link
Z      Transpose the matrix
ḟ     Filter out
€    From each row
⁶   Spaces
Z  Transpose the matrix

• I don't know any Jelly so am curious how the spaces get filtered out after the 2nd transpose? In J, you have to run the entire sequence "transpose, remove spaces" twice. Jun 3, 2021 at 5:30
• @Jonah The first "remove spaces" removes all of the spaces so there couldn't possibly be any spaces left to remove the second time. Note that zipping ragged arrays in Jelly will just collapse all of the rows left-ward, so [[1, 2], [3], [4, 5]] gets zipped to [[1, 3, 4], [2, 5]]. Jun 3, 2021 at 5:54

J, 14 bytes

-.&' '"1@|:^:2


Try it online!

Not surprising, but what I came up with is almost identical to ovs's APL approach.

how

Transpose |: and remove spaces -.&' ' on each line "1 two times ^:2.

Python 3, 68 bytes

lambda x,g=lambda x:[sorted(r,key=' '.find)for r in zip(*x)]:g(g(x))


Try it online!

-15 bytes thanks to dingledooper

• 68 bytes Jun 2, 2021 at 22:41
• @dingledooper Oh yeah idk why i was doing the joins myself lol, using a matrix is totally acceptable. Thanks. (Also nice golf using sort by key) Jun 2, 2021 at 23:26
• 64 bytes using eval
– xnor
Jun 3, 2021 at 23:58

Red, 108 bytes

func[x][loop 2[x: collect[while[x/1/1][keep pad trim/all form collect[forall x[keep take x/1]]length? x]]]x]


Try it online!

Takes input and returns output as a series of strings space-padded to equal length.

MATL, 7 bytes

,c!Z{Xz


Input is a char matrix (rectangular char array).

Explanation

,      % Do twice
c    %   Convert to char. The first time this takes the input (implicit),
%   and does nothing because the input is already a char matrix. The second
%   time this transforms the cell array of char vectors at the top of the
%   stack into a char matrix, right-padding each line with space
!    %   Transpose
Z{   %   Convert char matrix into cell array of its rows
Xz   %   Remove space from each char vector contained in that cell array
% End (implicit)
% Display (implicit)

• I'm not quite sure how Z{Xz works here, but would a translation of HN's Jelly answer (transpose, remove spaces from each row, transpose) work as a shorter solution? Jun 3, 2021 at 3:52
• @cairdcoinheringaahing Thanks for the idea. However, it doesn't work because MATL has no concept of zipping arrays of unequal lengths like Jelly has Jun 3, 2021 at 9:55

K (ngn/k), 14 bytes

2{{x@<^x}'+x}/


Try it online!

• 2{...}/ set up a do-reduce, running the code in {...} twice
• {...}'+x call the nested {...} with each item of the transposed input
• {x@<^x} shuffle spaces to the end

Japt, 6 bytes

Õ¸¬Õ¸¬


Try it

Õ¸¬Õ¸¬     :Implicit input of string
Õ          :Transpose
¸         :Split on spaces
¬        :Join
Õ¸¬     :Repeat


Japt-h, 6 bytes

2Æ=Õ¸¬


Try it

2Æ=Õ¸¬     :Implicit input of string U
2Æ         :Map the range [0,2)
=        :  Reassign to U
Õ       :  Transpose
¸      :  Split U on spaces
¬     :  Join
:Implicit output of last element


05AB1E, 6 bytes

Input and output is a list of lists of characters.

2FζðδK


2F iterate two times:
ζ tranpose the list of lists, padding shorter lists with spaces
ðδK remove all spaces

Vyxalaj, 7 bytes

2(ÞTȧvṅ

2(ÞTȧvṅ
2(         Repeat twice:
ÞT        Transpose
ȧ       Remove whitespace
vṅ     Join sublists on empty string


C (gcc), 197 $$\\cdots\$$ 181 180 bytes

Saved a byte thanks to a stone arachnid!!!
Saved 4 bytes thanks to ceilingcat!!!

#define F for(i=0;i<l;)for(j=0,p=t[i++];*p;++p,++j)if(*p<33)for(k
i;j;k;f(t,l,p,q)char**t,*p,*q;{F=i;q=t[k]+j,k<l;)k+=*q-32?*p=*q,*q=32,l:1;F=0,q=p;!k**++q;)*q-32?*p=*q,k=*q=32:0;}


Try it online!

Factor + combinators.extras, 62 bytes

[ [ flip [ [ 32 = ] partition prepend ] map ] twice "\n"join ]


Try it online!

It's a quotation that accepts a matrix of characters/list of strings from the data stack as input and leaves a string on the data stack as output.

• [ ... ] twice Call a quotation twice.
• flip Transpose a matrix.
• [ ... ] map Do something to every row in the matrix.
• [ 32 = ] partition prepend Separate the spaces from the other characters, then stick 'em on one end.
• "\n"join Convert a matrix of code points (e.g. { { 91 91 32 } { 91 32 32 } { 32 32 32 } }) to a string.

Vim, 55 bytes

YP:s/./\\_./g
Dddqq:%s/\v (<C-r>-)(\S)/\2\1
@qq@q:%s/ //g



Requires input to be padded to a rectangle. Try it online!

Strategy

We're going to handle the vertical swaps by constructing a regex that will match any $$\n\$$ characters--including newline--where $$\n\$$ is the length of each line. Then we look for a space followed by $$\n\$$ characters followed by a non-space and swap the space for the non-space. Since the potential matches of this regex are overlapping, we'll use a macro to keep on doing the replacement until there are no more matches. Then the horizontal squashing is easy: just remove all spaces.

Explanation

YP


Copy the top line upward. We're going to turn this copy into the regex we need.

:s/./\\_./g<cr>


Replace each character on the line with \_.. In Vim regex, this is a construct that matches any single character including newline (TIL). Line 1 now contains a regex that matches $$\n\$$ characters.

Ddd


Delete to the end of the line (putting the regex in register -) and then delete the now-blank line (doesn't overwrite - because it's a multiline deletion).

qq


Begin recording macro q:

:%s/\v (<C-r>-)(\S)/\2\1 <cr>


Do a substitution on all lines: space, followed by the regex we stored in register - (group 1), followed by a non-space character (group 2) => group 2, followed by group 1, followed by space. (The \v sequence means we don't have to backslash the parentheses, saving a net 2 bytes.)

@qq


After the substitution, call the macro recursively. Stop recording...

@q


... and call the macro. This recursive macro will run until no more substitutions can be made.

:%s/ //g<cr>


Replace all spaces on all lines with empty string.

Scala 2.12, 71 bytes

Fixed a mistake thanks to @ophact

1.to(2)./:(_){_.transpose.map{r=>val(x,s)=r.partition(32<);x++s}->_ _1}


Try it in Scastie!

Takes a matrix of characters as input. The non-space characters have to be greater than 32 (ASCII).

1.to(2)  //Make the range[1..2]. This is just to repeat the function twice
./:(_){  //Fold over it with the input as the initial value for the accumulator
_.transpose  //Transpose the matrix first so we can work on the columns
.map{r=>    //For every row,
val(x,s)=r.partition(32<); //x is non-space characters, s is spaces
x++s       //Join those together, with all the spaces at the end
}->_   //Make a 2-tuple with the current number (either 1 or 2)
_1}    //Get the first element of that tuple (the matrix), discarding the number

• Your answer seems to return the string unchanged? Or maybe I don't know how to use Scastie properly.
– user100690
Jun 2, 2021 at 15:22
• @ophact Whoops, you're right, that should be 32<, not 32>.
– user
Jun 2, 2021 at 16:00

Pip-rl, 11 9 bytes

ZD J*||Zg


Takes input as lines of stdin, padded to a full rectangle. Try it online!

Explanation

           g is list of lines of stdin (-r flag)
Zg  Zip g (transposing into a list of lists of characters)
||    Strip whitespace from each character (replacing spaces with empty string)
J*      Join each sublist into a single string
ZD         Zip again, padding shorter sublists with nil
Autoprint with each sublist on a separate line (-l flag)


Changing the flags to -rP shows the actual structure of the list that gets output (() is nil):

["a";"f";"b";"g";"c";"g";"d";"h";"l";"e"]
["f";"j";"j";();"g";"k";();"l";();"i"]
[();();();();"k";();();();();"l"]


Since the -l flag joins each sublist together without a separator, and since nil normally produces no output, -rl gives us exactly the output we want:

afbgcgdhle
fjjgkli
kl


JavaScript (ES10), 82 bytes

Expects a space-padded matrix of characters. Returns a list of lists of characters.

m=>m.map(r=>r.flatMap((_,x)=>m.some((r,y)=>1/(c=r[x])||m[y+=[,x]]?0:m[y]=1)?c:[]))


Try it online!

Retina 0.8.2, 46 bytes

+(?<=(.)*) (.*¶(?<-1>.)*(?(1)$))(\S)$3$2  Try it online! Takes space-padded input. Note: Lines 2 and 3 end in a space. Explanation: (?<=(.)*) (.*¶(?<-1>.)*(?(1)$))(\S)
$3$2


Find a space above non-whitespace and exchange the two.

+


Repeat until no more exchanges can be made.





Delete the remaining spaces.

• I was wanting to make a regex (sed) solution, but I couldn't figure out the "find a space above non-whitespace part" (posix regexes are weaker). How did you do it? Jun 2, 2021 at 18:53
• @Wzl .NET's groups actually keep a history of all of their captures, not just the last one as in regular regexes. Here the (?<-1>.)* construct removes the characters captured individually by the (.)* until there are none left, enforced by the (?(1)$) conditional construct. (There are other uses, for instance Retina will substitute $#1 with the number of (remaining) captures in the group.)
– Neil
Jun 2, 2021 at 20:20

Charcoal, 26 bytes

ＷＳ⊞υιＦ²≔Ｅ§υ⁰◨Φ⭆υ§μλ›μ Ｌυυυ


Try it online! Link is to verbose version of code. Takes input as newline-terminated space-padded list of strings. Explanation:

ＷＳ⊞υι


Input the strings.

Ｆ²


Repeat twice.

≔Ｅ§υ⁰◨Φ⭆υ§μλ›μ Ｌυυ


Transpose the array, filter out the spaces, then right-pad back to the original length.

υ


Output the final result.

JavaScript (ES10note), 76 bytes

a=>(g=a=>a[0].map((c,i)=>a.map(l=>l[i]).sort((x,y)=>(y>' ')-(x>' '))))(g(a))


Try it online!

Just noticed that this Python answer by hyper-neutrino used the same algorithm. You may upvote that one.

Husk, 5 bytes

TmfIT


Try it online!

same as jelly

Wolfram Language (Mathematica), 47 bytes

a=PadRight[#/." "->Nothing]/. 0->" "&;a@a@#&


Try it online! Pure function. Takes a space-padded matrix of characters and returns the squashed matrix. This function uses the relatively straightforward algorithm: transpose, remove spaces, pad with spaces, and repeat once more. The Unicode character is U+F3C7 for \[Transpose]. Note that without the space, the ReplaceAll expression would be parsed as / .0 -> " ".