[Question]
  [
We don't have enough (semi-)easy challenges for beginners. More and more of the easy ones are already taken. So I tried to come up with something that might be achievable by beginners, but that isn't a duplicate.
### Input:
A single string separated with your OS new-line (i.e. `\r\n`),  
or an array with multiple strings.
### Output - *The Stairs*:
Remove all non-alphabetic and non-numeric symbols. So all that's left is `[A-Za-z0-9]`. And then 'build a stairs'; basically ordering them on length with the smallest at top and widest at the bottom.
### Challenge rules:
1. When two strings are of equal length, we merge them with each other as one big string (the order doesn't matter, so it could be from first to last or last to first, whichever of the two you prefer).
2. The rule above can stack when the merged strings are of equal length again (see test case 2).
### General rules:
* The input is STDIN and contains only ASCII characters. And the output is STDOUT.
* The case of the output must be the same as the input.
* ~~Each submission must be a full program able to compile and run, so not just a method/function.~~ EDIT: I'm rather new, so perhaps it's indeed better to use the [default](http://meta.codegolf.stackexchange.com/a/2422/34531) from now on, even though I prefer a full program myself. Sorry for everyone that has already posted a full program. Feel free to edit, and I'll try to not change the post mid-challenge next time.
* This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest answer in bytes wins. I probably accept the shortest answer in a year from now.  
Don't let code-golf answers discourage you from posting golfed non-codegolf languages like C# and alike! Try to come up with the shortest answer for any programming language.
* Feel free to use newer languages than this question.
---
### Test cases:
***Input 1:***
```
This is a sample text,
that you will have to use to build stairs.
The wood may be of excellent quality,
or pretty crappy almost falling apart and filled with termites.
Bla bla bla - some more text
Ok, that will do
```
***Output 1:***
```
Okthatwilldo
Thisisasampletext
Blablablasomemoretext
Thewoodmaybeofexcellentquality
thatyouwillhavetousetobuildstairs
orprettycrappyalmostfallingapartandfilledwithtermites
```
---
***Input 2:***
```
A
small
one
that
contains
equal
length
strings
for
the
special
rule
```
***Output 2:***
```
A                   Or alternatively:       A
length                                      length
oneforthe                                   theforone
smallequal                                  equalsmall
stringsspecial                              specialstrings
thatrulecontains                            containsrulethat
```
***Steps explained of 2:***
*First order on length:*
```
A
one
for
the
that
rule
small
equal
length
strings
special
contains
```
*First merge:*
```
A
oneforthe
thatrule
smallequal
length
stringsspecial
contains
```
*Second order on length:*
```
A
length
thatrule
contains
oneforthe
smallequal
stringsspecial
```
*Second merge:*
```
A
length
thatrulecontains
oneforthe
smallequal
stringsspecial
```
*Third order on length:*
```
A
length
oneforthe
smallequal
stringsspecial
thatrulecontains
```
---
***Input 3:***
```
Test,
test.
This
is
a
test.
```
***Output 3:***
```
a                   Or alternatively:       a
is                                          is
TesttestThistest                            testThistestTest
```
---
***Input 4:***
```
a
bc
d!
123
```
***Output 4:***
```
123     Or alternatively:    123
adbc                         dabc
```
  
[Answer]
## [Husk](https://github.com/barbuz/Husk), 11 bytes
```
ωȯmΣġLÖLmf□
```
[Try it online!](https://tio.run/##yygtzv7//3znifW55xYfWehzeJpPbtqjaQv///8freSopKNUnJuYkwOk8/NSgWRJRmIJkErOzytJzMwrBjJTC0sTQfI5qXnpJRkgDSVFmXnpIKm0/CKwFpDG4oLU5EywwqLSnFSlWAA "Husk – Try It Online")
Husk is younger than this challenge (which makes no difference officially, but still).
## Explanation
```
ωȯmΣġLÖLmf□  Implicit input (list of strings), say ["a","bc","d!","123"]
        mf□  Keep only alphanumeric chars of each: ["a","bc","d","123"]
ωȯ           Repeat until fixed point is reached:
      ÖL       Sort by length: ["a","d","bc","123"]
    ġL         Group by length: [["a","d"],["bc"],["123"]]
  mΣ           Concatenate each group: ["ad","bc","123"]
             Final result ["123","adbc"], print implicitly separated by newlines.
```
[Answer]
# Python 3, 264 Bytes
I'm not good at code golf so I'm confident this won't be the best Python 3 answer. This uses recursion and an ordered dict with all the words for each length.
```
from collections import*
def f(i):
 d = defaultdict(list)
 for l in i: x = "".join(c for c in l if c.isalnum());d[len(x)].append(x)
 n = (sorted(["".join(d[z]) for z in d.keys()], key=len))
 if n == i:return "\n".join(n)
 return f(n)
print(f(eval(input())))
```
Takes input from stdin as a list, for example, test it with this list:
```
['A', 'small', 'one', 'that', 'contains', 'equal', 'length', 'strings', 'for', 'the', 'special', 'rule']
```
Will output:
```
A
length
oneforthe
smallequal
stringsspecial
thatrulecontains
```
[Answer]
# Retina, ~~69~~ 63 bytes
```
[^\w¶]|_
{`\b((.)+)¶((?.)+)\b(?(2)(?!))
$1$3
O$`(.)+
$#1$*
```
[Try it online!](http://retina.tryitonline.net/#code=W15cd8K2XXxfCgp7YFxiKCguKSspwrYoKD88LTI-LikrKVxiKD8oMikoPyEpKQokMSQzCk8kYCguKSsKJCMxJCo&input=QQpvbmUKZm9yCnRoZQp0aGF0CnJ1bGUKc21hbGwKZXF1YWwKbGVuZ3RoCnN0cmluZ3MKc3BlY2lhbApjb250YWlucw)
[Answer]
# Oracle SQL 11.2, 346 bytes
The lines in the input string are separated by '¤'. 
That way it is not necessary to create a table to use as the input.
```
This is a sample text,¤that you will have to use to build stairs.¤The wood may be of excellent quality,¤or pretty crappy almost falling apart and filled with termites.¤Bla bla bla - some more text¤Ok, that will do
A¤small¤one¤that¤contains¤equal¤length¤strings¤for¤the¤special¤rule
Test,¤test.¤This¤is¤a¤test.¤         
```
Query :
```
WITH v AS(SELECT REGEXP_REPLACE(COLUMN_VALUE,'[^a-zA-Z0-9]')s FROM XMLTABLE(('"'||REPLACE(:1,'¤','","')||'"'))),r(s,i,l)AS(SELECT s,1,1 FROM v UNION ALL SELECT LISTAGG(s)WITHIN GROUP(ORDER BY s)OVER(PARTITION BY LENGTH(s)),ROW_NUMBER()OVER(PARTITION BY LENGTH(s)ORDER BY s),l+1 FROM r WHERE l<LENGTH(:1)AND i=1)SELECT s FROM r WHERE l=LENGTH(:1);  
```
Un-golfed 
```
WITH v AS
( 
  -- Splits on ¤ and keeps only alphanum characters 
  SELECT REGEXP_REPLACE(COLUMN_VALUE,'[^a-zA-Z0-9]')s FROM XMLTABLE(('"'||REPLACE(:1,'¤','","')||'"'))
)
-- Recursive view 
-- s : string
-- i : index of the string in case of duplicates
-- l : exit condition
,r(s,i,l)AS
(
  -- Start with every element of the input
  SELECT s,1,1 FROM v
  UNION ALL
  SELECT -- Concatenate elements of the same lengths
         LISTAGG(s)WITHIN GROUP(ORDER BY s)OVER(PARTITION BY LENGTH(s))
         -- Index of elements of the same length (listagg with over generates duplicates)
        ,ROW_NUMBER()OVER(PARTITION BY LENGTH(s) ORDER BY s)
        -- exit condition
        ,l+1 FROM r WHERE l<LENGTH(:1) AND i=1
)
-- Keep only the elements from the last iteration (automaticaly sorted on my system)
SELECT s FROM r WHERE l=LENGTH(:1)  
```
[Answer]
# [J](http://jsoftware.com/), 48 bytes
```
[:(/:#&>)[:(#&>,&.>//.])^:_(#~e.&AlphaNum_j_)&.>
```
[Try it online!](https://tio.run/##JYzBCoMwEETv@xVLBTVgY@kxrYIUeio99FpaCbIaJSbWxGt/PQ30MMzAG94UdjzrsRKYYYEHFDF7jpfH7RqeIi9FktYsjlhFyuuy5C/2Fm2efImnjV6UvG9zO7UswsAAHFYc8/OJt0f210EDbpZagzUEXkkPnTVejsYBfTapQZMZvALn19EMDnq7xhuBW6gbI143TRDN1CmLPbrwAw "J – Try It Online")
## ungolfed
```
[: (/: #&>) [: (#&> ,&.>//. ])^:_ (#~e.&AlphaNum_j_)&.>
```
## explanation
* `(#~e.&AlphaNum_j_)&.>` remove non alphanum
* `(#&> ,&.>//. ])` combine same length items
* `^:_` keep combining until it stops changing
* `(/: #&>)` sort by length
[Answer]
## Haskell, 129 bytes
```
import Data.List
import Data.Char
l=length
print.(foldl(const.map concat.groupBy((.l).(==).l).sortOn l)=<<(filter isAlphaNum<$>))
```
Accepts and prints an array of strings. If the result can be returned from the function (in contrast to printed to stdout), you can omit the `print.` and save 6 bytes.
How it works (note, I use `x` for the input parameter which of course does not appear in the pointfree version above):
```
 (    )=<<(     )          -- (f =<< g) x is f (g x) x, so we fold over x with a
                           -- starting value of:
     filter isAlphaNum<$>x -- keep only alphanumeric chars in every line of x
                           -- during folding, I ignore the the elements of x.
                           -- However folding stops the repeatedly applied function
                           -- after (length x) steps, which is enough for combining
                           -- lines of equal length
 const                     -- ignore elements from x, deal only with start value
                sortOn l   -- sort lines from shortest to longest
      groupBy((.l).(==).l) -- group lines of equal length
    map concat             -- concatenate each group      
print                      -- print result after (length x) iterations
```
[Answer]
# Python 3, ~~184~~ 180 bytes
```
def f(x):l=len;m=filter;y=sorted([''.join(m(str.isalnum,i))for i in x],key=l);*z,=m(l,[''.join(i for i in y if-~j==l(i))for j in range(l(y[-1]))]);y==z and+print(*z,sep='\n')or f(z)
```
A function that takes input, by argument, as a list of strings and prints the result to STDOUT. Execution raises an error (due to the use of the + operator before the print statement), but not before the output has been printed.
**How it works**
```
def f(x):                              Function with input of list of strings
l=len;m=filter                         Redefine much-used functions: len gives the length
                                       of an object and filter chooses those items from an
                                       iterable for which a function is true
[''.join(m(str.isalnum,i))for i in x]  Strip to leave only alphanumeric characters...
y=sorted(...,key=l)                    ...and sort by length, into y
''.join(i for i in y if-~j==l(i))      Concatenate equal length strings...
[...for j in range(l(y[-1]))]          ...for all possible string lengths...
*z,=(m(l,...))                         ...and remove empty strings by filtering by length
                                       (the empty string has length 0, and is thus false),
                                       into z
y==z and+print(*z,sep='\n')...         If no change after concatenation, no more equal
                                       length strings exist, so print result to STDOUT...
...or f(z)                             ...else pass new list to function
```
[Try it on Ideone](https://ideone.com/vD0bGs)
[Answer]
# [jq](https://stedolan.github.io/jq/), 78 bytes
Expects "an array with multiple strings."
```
def g:group_by(length);map(scan("\\w+"))|g|until(all(length<2);map(add)|g)[][]
```
[Try it online!](https://tio.run/##NYzBDsIgDEDv@4qFE0S9eFQvfse2mLoxhmGFQYkx2beLM7BTX9PX91pSGuRYq4vyNrrH88ONREWTuM7geOgBOWvb94EJsao1ImnDwZhi3c7Zg2HYzqLpmi6lpqprdmfH/wjzJme0KDPQBJSpt0igMeRNLhGKm@slQV6jKs5o/R4pteBkr/c/H41kVVd9rSNtMaST/wE "jq – Try It Online")
[Answer]
# Javascript ~~198~~ ~~188~~ ~~186~~ 179 bytes
This is my second longest golfed javascript program
```
s=>s.replace(/[^\w]|_/g,``,l=0).split(/\s/g).sort(g=(a,b)=>a[m=`length`]-b[m]).reduce((a,b,c)=>a+(a.split(/\s/g)[c-1][m]<b[m]?`
`:` `)+b).replace(/ /g,``).split`
`.sort(g).join`
`
```
Probably can be golfed further
[Answer]
# [Perl 5](https://www.perl.org/), 112 bytes
```
@F=<>;while($n-@F){$n=@F;%k=();s/[^a-z0-9]//gi,$k{y///c}.=$_ for@F;@F=values%k}say $k{$_}for sort{$a<=>$b}keys%k
```
[Try it online!](https://tio.run/##JYyxCoMwFEV3v8LhCQrG2MGhaMTJrZtbaSUtqYaIEV/aYiW/3jRQuFy4nMNdxDoVzjUtq@ryPcpJxDCTpk12mFnTlpFicVIiPV85@eTkeKF0kCmofaOU3m3GoA8fevWmv3jx6SkwUhb5FnoHeutZiHo1O/CK1XCzSmzecK4TaNLA@M6CbpQY@PD//urFSD2jI6ciyw/5Dw "Perl 5 – Try It Online")
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 17 bytes
```
f€ØWṖ¤L€Ġị⁸Ẏ€µÐLY
```
[Try it online!](https://tio.run/##y0rNyan8/z/tUdOawzPCH@6cdmiJD5B9ZMHD3d2PGnc83NUH5B3aeniCT@T///@j1R3VdRTUi3MTc3JAjPy8VBBVkpFYAqKT8/NKEjPzikHs1MLSRLCanNS89JIMsLaSosy8dLBsWn4RRCNYf3FBanImRHVRaU6qeiwA "Jelly – Try It Online")
Not sure why `Ẏf¥€ØWṖ¤L€ĠịµÐLY` doesn't work...
Explanation:
```
f€ØWṖ¤L€Ġị⁸Ẏ€µÐLY Full program
             µÐL  Execute the following until we get a result a second time
     ¤              The following as a nilad
  ØW                  [A-Za-z0-9_]
    Ṗ                 Remove last element (_)
f€                  Filter the left argument (current result) with the above nilad
       €            Left map
      L               Length
        Ġ           Group indices of same values, sort values
          ⁸         Left argument
         ị          Index on ^^ and ^
            €       Left map
           Ẏ          Concatenate elements
                Y Join on newlines (full program will display correctly)
```
[Answer]
# Pyth, 22 bytes
```
jlDusM.glkG@Ls++GrG1UT
```
[Try it here.](http://pyth.herokuapp.com/?code=jlDusM.glkG%40Ls%2B%2BGrG1UT&input=%5B%27A%27%2C+%27small%27%2C+%27one%27%2C+%27that%27%2C+%27contains%27%2C+%27equal%27%2C+%27length%27%2C+%27strings%27%2C+%27for%27%2C+%27the%27%2C+%27special%27%2C+%27rule%27%5D&debug=0)
Explanation:
```
jlDusM.glkG@Ls++GrG1UT
j                      join on newlines
 lD                     sort by length
   u                     run until duplicate result, return result (argument G, iteration number H)
    sM                    map concatenate elements
      .g                   group elements by function (argument k)
        l                   length
         k                   k
          G                 G
           @L             left map filter on presence (extra argument first)
             s             concatenate elements
              +             concatenate two items
               +             concatenate two items
                G             G (default = lowercase alphabet)
                 r 1          to uppercase
                  G            G
                    U        unary range [0..n)
                     T        T (default = 10)
```
[Answer]
# Pyth, 39 bytes
Back to golfing !
There is the program :
~~```
=Qm:d"[\W_]"kQKYLmsd.glkolNb;WnKQ=KQ=yQ;jQ
```~~
```
=Qm:d"[\W_]"kQLmsd.glkolNb;WnYQ=YQ=yQ;j
```
[Test it here !](https://pyth.herokuapp.com/?code=%3DQm%3Ad%22%5B%5CW_%5D%22kQLmsd.glkolNb%3BWnYQ%3DYQ%3DyQ%3Bj&input=%5B%27A%27%2C+%27small%27%2C+%27one%27%2C+%27that%27%2C+%27contains%27%2C+%27equal%27%2C+%27length%27%2C+%27strings%27%2C+%27for%27%2C+%27the%27%2C+%27special%27%2C+%27rule%27%5D%0A&debug=0)
# Explanations
```
=Qm:d"[\W_]"kQLmsd.glkolNb;WnYQ=YQ=yQ;j       (Implicit) Assign evaluated imput to Q (In this case, an array)
=Q                                            Reassign a value to Q
  m          Q                                map a function over Q
   :d"[\W_]"k                                 Replace any special character with an empty string
              L           ;                   Declare a function y(b)
                      olNb                      Sort b by length
                  .glk                          Group strings of same length in arrays
               msd                              Concat each inner array
                           WnYQ      ;        While Y != Q (previous array is not equal to current array)
                               =YQ              Assign the current array to Y (Y=Q)
                                  =yQ           Assign y(Q) to Q (Q=yQ). Here, the assigned variable name is implicit
                                      j       Display the resulting array
```
[Answer]
# Java 8, 268 bytes
A void lambda accepting a mutable `List<String>` (i.e. implements `add` and `remove`; e.g. `ArrayList`). Output is printed to standard out, delimited by newline, with a trailing newline. Cast to `Consumer<List<String>>`.
```
l->{int i=0,z;while(i<l.size())l.set(i,l.get(i++).replaceAll("\\W| ",""));while(l.size()>0){l.sort((s,t)->s.length()-t.length());String s=l.remove(0);for(i=0,z=s.length();l.size()>0&&l.get(0).length()==z;i++)s+=l.remove(0);if(i<1)System.out.println(s);else l.add(s);}}
```
[Try It Online](https://tio.run/##hVRNb9swDD0nv4LwoZBRW8iucxKg23XDDg2ww7qDYjOxWlnyJDqpm@W3Z7SdJW3XZoYNfVCPenwkfa82KnU12vvi4VA3S6NzyI0KAb4qbWE3HtVebxQhBFLExnsGyIa0kavG5qSdlZ@dDU2Ffnq2fdGBprfktV3P58AuLN2S0j5XAWF2MOl8x1ugZ5PkKduW2qDQUyODfkIRxzxBEjoxct2N19ex9FgbleONMSK6u/v@G6IkiuL4iP2LnE/iHc@dJyFCQnE6D9KgXVMp4pRO0zgbqEGYGfZcuQ2KSZytnBc9o9kZlZ1dX10NfCbxyTqbPWUdvXD9wpFecTQf4ts2EFbSNSR7BYwVIc7QsARGqqLoVvv9YZSN/1F5upg/U/rGe9X2kvI2udNSLH78BM13hLjL1MgjNd6@BgYZyKOqxHBS5s4YzEmcjw12zmNvcD5IcscF51e8QeTjR4tb1nE82nfkh7o5ct84XUDF1SMGlZmj8usjxZelIFWeY03ieUzsGE7A3RjeeaJFqQPwqyCoqjYIhI@URMn7CCoVQesa2GpjoFQbxjhoQj8sG22KLgTN4V/ysigRts51IbawRHArwMccWS0u6F@NMpraizSc54ZAohZyr@q6BWUqFwhWypiuKFWtPIGyBayYJxZMl0qOzlecwMvcPhkFy@OXQnAVQuX8IM0l3LeHBHp1emUK98bZfZ/t0Rs1HaVpGrHxNeL/qY5uIFQcNTiLw/25swywAbBTEoY@46x05RCAG5SPcZPUmGs2@8ZgJEPNkosI@HcwFOT@8Ac)
This ended up being much longer than I expected. As Kevin observed, it's more complicated than it seems at first glance.
## Ungolfed lambda
```
l -> {
    int i = 0, z;
    while (i < l.size())
        l.set(i, l.get(i++).replaceAll("\\W| ", ""));
    while (l.size() > 0) {
        l.sort((s, t) -> s.length() - t.length());
        String s = l.remove(0);
        for (
            i = 0, z = s.length();
            l.size() > 0 && l.get(0).length() == z;
            i++
        )
            s += l.remove(0);
        if (i < 1)
            System.out.println(s);
        else
            l.add(s);
    }
}
```
First, I reduce the input in place to letters and numbers. I then process the inputs in groups by length. I append items to the first in the list until the next length is reached, removing them as I go. If only the first element was used, that will be the only string of that length, so it's printed. Otherwise, the joined string is added to the list for another iteration. I sort the list by length each iteration before use.
I started off with a lovely solution that used a priority queue to keep track of the intermediate strings. Unfortunately, `java.util.PriorityQueue<String>` is quite long (and using the raw type was longer), so it had to go.
[Answer]
# [Japt](https://github.com/ETHproductions/japt) v2.0a1 [`-h`](https://codegolf.meta.stackexchange.com/a/14339/58974), 11 bytes
Input & output as arrays of strings.
```
£=mk\W üÊmq
```
[Try it](https://ethproductions.github.io/japt/?v=2.0a1&code=oz1ta1xXIPzKbXE=&input=WyJhIgoiYmMiCiJkISIKIjEyMyJdCi1oUg==)
```
£=mk\L üÊmq
                :Implicit input of string array U
£               :Map
  m             :  Map U
   k            :    Remove
    \W          :    /[^A-Z0-9]/gi
       ü        :  Sort & partition by
        Ê       :    Length
         m      :  Map
          q     :    Join
 =              :  Reassign to U for next iteration
                :Implicit output of last element
```
[Answer]
# JavaScript, 119 bytes
I feel like this should be much shorter ...
Includes 2 leading newlines in the output.
```
f=s=>s==(s.replace(/[^\w\n]|_/g,t=``).split`
`.sort((x,y)=>x[l=`length`]-y[l]).map(x=>t+=s==(s=x[l])?x:`
`+x),t)?t:f(t)
```
[Try it online](https://tio.run/##PVHNjtsgEL7PU0xvRut41fa2Elm1L9BLbklaiD2O2WKgzHhjS333FDtt0QAaBr6f4c2@W26zS7ILsaP7vdes96x1xU2m5G1L1fPx@@l2CuffP56vtWhjVMPJOzFgGo5ZqmquF6X389Fr4ylcZTDn3XL0Z9WMNlWz3suT3jD1vJ6@zi/l7dOsalGv8tJXou5tDBw9NT5eqyOAOQyOsYRFtmPyhEKz1CCDFVzihDfnPQ72vRQiTrxtl8n5Dlmsy9zAYSC8xdjhaBe8EMYeaW7JF4WCvyZbHCw1xIwpk8iCbbYpLWj9GFmwt967cEWbbBa0ocO@MFJXiGUoYvLohArLV2/x8nfukONIOMb8kAvffta4Kd7UdtHUxdkX4LGAQwy02YFivUgODLSqgkcHgSUXfoY@5nKNgBO1rpTz5GnDORCvDSnr6tUxlLCPfKtbuLTQfYCPnz6DATj/@4u@mlVTwMdKqeYtumBO4RR2/8eaGXX/Aw)
[Answer]
# [Perl 6](https://github.com/nxadm/rakudo-pkg), 85 bytes
```
{.&([o] {my@a;@a[+.comb]~=$_ for $_;@a.grep(~*)}xx$_).sort(+*.comb)}o*.map:{S:g/\W//}
```
[Try it online!](https://tio.run/##HY1LCoMwFAD37xRZiPiBuOtCsdgzdNGFFUnlGQP5NYmgiF7dSrczA2PRydupVhKPpCbnRuOkNR3Z1NqwqmFtTgejPt1RRz0ZjSNRf1HKHdrkyNJ9WaI@pd64kOTZP013k1HFbLk9S168X0WxnxWMiRQafXq/U8/W8wFeMSnBaIQwsQCD0YEJ7QG/M5MgUfMwgQ9OaO7hGl8Zgrc4iEu7WeIP "Perl 6 – Try It Online")
Input and outputs as lists of strings.
[Answer]
# Pyth, 21 bytes
```
jusM.glkG:R"[^\w\d]"k
```
Input is a list of strings. Try it online [here](https://pyth.herokuapp.com/?code=jusM.glkG%3AR%22%5B%5E%5Cw%5Cd%5D%22k&input=%5B%22A%22%2C%22small%22%2C%22one%22%2C%22that%22%2C%22contains%22%2C%22equal%22%2C%22length%22%2C%22strings%22%2C%22for%22%2C%22the%22%2C%22special%22%2C%22rule%22%5D&debug=0), or verify all the test cases [here](https://pyth.herokuapp.com/?code=jusM.glkG%3AR%22%5B%5E%5Cw%5Cd%5D%22k&test_suite=1&test_suite_input=%5B%22This%20is%20a%20sample%20text%2C%22%2C%22that%20you%20will%20have%20to%20use%20to%20build%20stairs.%22%2C%22The%20wood%20may%20be%20of%20excellent%20quality%2C%22%2C%22or%20pretty%20crappy%20almost%20falling%20apart%20and%20filled%20with%20termites.%22%2C%22Bla%20bla%20bla%20-%20some%20more%20text%22%2C%22Ok%2C%20that%20will%20do%22%5D%0A%5B%22A%22%2C%22small%22%2C%22one%22%2C%22that%22%2C%22contains%22%2C%22equal%22%2C%22length%22%2C%22strings%22%2C%22for%22%2C%22the%22%2C%22special%22%2C%22rule%22%5D%0A%5B%22Test%2C%22%2C%22test.%22%2C%22This%22%2C%22is%22%2C%22a%22%2C%22test.%22%5D%0A%5B%22a%22%2C%22bc%22%2C%22d%21%22%2C%22123%22%5D&debug=0).
```
jusM.glkG:R"[^\w\d]"kQ   Implicit: Q=eval(input()), k=""
                         Trailing Q inferred
          R          Q   For each string in Q...
         : "[^\w\d]"     ... replace non-alphanumerics...
                    k    ... with k (empty string)
 u                       Repeat the following until a fixed point occurs, current as G:
    .g  G                  Group the elements of G...
      lk                   ... by length
                             Groups ordered by the result of the inner function, i.e. length
                             This means that, in the final iteration, this acts as a sort by length
  sM                       Concatenate each group back into a string
j                        Join the resulting list on newlines, implicit print
```
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 12 bytes
```
krv↔⁽LġṠÞṡ)Ẋ
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJhaiIsIiIsImtyduKGlOKBvUzEoeG5oMOe4bmhKeG6iiIsIiIsIkFcbnNtYWxsITBcbm9uZVxudGhhdCxcbmNvbnRhaW5zXG5lcXVhbFxubGVuZ3RoXG5zdHJpbmdzXG5mb3JcbnRoZVxuc3BlY2lhbFxucnVsZSJd)
I/O as lists of lines
```
          )Ẋ # Repeat until no change...
  v          # To each...
   ↔         # Keep only characters from...
kr           # Alphanumeric chars
      ġ      # Group by...
    ⁽L       # Length
       Ṡ     # Concatenate each
        Þṡ   # Sort by length
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~95~~ 93 bytes
```
f=->a{b=a.map{_1.gsub /\W|_/,""}.group_by(&s=:size).map{_2*""}.sort_by &s
b[a.size-1]?a:f[b]}
```
[Attempt This Online!](https://ato.pxeger.com/run?1=NY9BbsIwEEX3c4ooiwhQY0RXKFKKOAWLNArjyE4sObbx2IsUOAkbFvRQvU0TAev3pPf_7eEjH-_33xhkvv2rZZl_4ZmXyAZ052bDOoo8WX8fLs36I02vrPM2uoaPi4zKgtSPWD7Nz9VMyfowwSQj4BWymeebeoeFrHh9fUWOLgZKZJXugQbUGqwREHoM0FoTUBkCcYqoQQvThR4oeGU6Amn9pAkgJ1o1YR-1SJlWRtC8YZEVbW8Ht6yfnfepfw)
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 16 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
εžKÃ}»Δ¶¡é.γg}J»
```
Input as a list of strings.
[Try it online](https://tio.run/##yy9OTMpM/f//3Naj@7wPN9ce2n1uyqFthxYeXql3bnN6rdeh3f//Rys5KukoFecm5uQA6fy8VCBZkpFYAqSS8/NKEjPzioHM1MLSRJB8TmpeekkGSENJUWZeOkgqLb8IrAWksbggNTkTrLCoNCdVTykWAA) or [verify all test cases](https://tio.run/##PVCxTsMwEP2VI3OoBHwAAjHBwNKtynBJLo2FHQf70jZDJn6BH2BkRnSpxJCKtb8Uzk6FZN@z/e7uvbP1mCuaNv1DOp2@f3@ejm/DeDi9j/vx4/i5OH2th8fxMA3puL@dVqtkWSsPshA8mlYTMO04TdKEa2TobQdbpTXUuBHKQucj5J3SJXhG5fxCkpc1wdbaEgz2kBPYCmhXkNbUMLx2qBX3oal10Dpi7qFw2LY9oDbWM1SotWrWgC06BmxKqESVShHnWiw5o5ii0r1GyM/7Erw1BMa62bbQzy8pROfRdWmTLIVVcieMN6IRLDR0nk6gsI3M0Hg5UrApKJbXXIcCdmIpUJV1sSQU@pYKFRNdp2kx91@Sn/9McP4OFepiwP/3mBqueSGhvJBwdX2TZNkf).
Could have been 14 bytes with `εžKÃ}Δé.γg}J}»` if `Δ` would work with a list of strings as well..
**Explanation:**
```
ε   }            # Map the (implicit) input-list of strings:
 žjÃ             #  Leave only the letters and digits of each string
                 #   i.e. ["a","bc","d!","123"] → ["a","bc","d","123"]
     »           # Join the list by newlines to a single string
                 #  i.e. ["a","bc","d","123"] → "a\nbc\nd\n123"
      Δ          # Loop until the string no longer changes:
       ¶¡        #  Split by newlines
                 #   i.e. "a\nbc\nd\n123" → ["a","bc","d","123"]
         .γ }    #  Group the strings by:
           g     #   Their length
                 #    i.e. ["a","bc","d","123"] → [["a,"d"],["bc"],["123"]]
             J   #  Join each group-list to a single string
                 #   i.e. [["a,"d"],["bc"],["123"]] → ["ad","bc","123"]
              »  #  Join this list by newlines again
                 #   i.e. ["ad","bc","123"] → "ad\nbc\n123"
                 # (and the result is output implicitly after the loop)
                 #  i.e. "123\nadbc"
```
[Answer]
## Powershell, Windows 10, 63 bytes
So input...
```
$n = @"
This is a sample text,
that you will have to use to build stairs.
The wood may be of excellent quality,
or pretty crappy almost falling apart and filled with termites.
Bla bla bla - some more text
Ok, that will do
"@
```
and code...
```
((($n -Split '\n').Replace(" ","")) -Replace '[\W]','')|Sort *h
```
That covers input/output 1, working on 2 and 3...
]