text:
Scramble words while preserving their outlines
This is much more advanced than How to randomize letters in a word and Cambridge Transposition because of the rule about which letters may be swapped with which. A simple regex will not suffice here.

It is well known that a text can still be read while the innards of its words have been scrambled, as long as their first and last letters plus their overall outlines remain constant. Given a printable Ascii+Newline text, scramble each word according to these rules:

Scrambling must be (pseudo) random.
A word is a sequence of the Latin characters, A through Z.
Only initial letters will ever be uppercase.
The first and last letters must stay untouched.
When scrambling, only letters within one of the following groups may exchange places:

acemnorsuvwxz
bdfhkl
gpqy
it
j (stays in place)

Example

Srcmable wrods while psrrnveieg their oeiltnus
It is well known that a txet can still be read while the inrands of its wrods have been srcambled, as long as their fisrt and last letters plus their ovaerll ontliues raemin canstnot. Given a patnirlbe Acsii+Nwnliee txet, samrclbe ecah word anoccdirg to these relus:

Smncrbliag must be (pusedo) rondam.
A wrod is a seqencue of the Latin chreratacs, A thurogh Z.
Only iniital lrttees will eevr be uppcsaere.
The fisrt and lsat lettres must stay uctoenhud.
When sarnclbimg, only letters wihtin one of the fwllnoiog guorps may ecxhange plaecs:

aneusvrowxmcz
bhkfdl
gqpy
it
j (stays in plcae)

Emxaple

t is supposed to be shorter than h although many people do not write it so.

@LeakyNun I know, but are you suggest removing t from group 2? Or maybe putting t in a group 4 with i?

The latter would be fine.

may the runtime be theoretically unbounded? (like random tries until something is right)

@SargeBorsch Probably ok if done per word (as it is extremely likely to terminate fast), but not if done on the entire text (as that will probably never terminate). However, I'm not entirely sure I should allow this, as I don't want to trivialize the problem. I'd rather see clever solutions than brute ones. It isn't necessary in this case, as I've written a solution that doesn't.

printable/patnirlbe isn't quite readable.  I think the i/t swap is to blame. Hmm... paintrlbe No that didn't help either. It's probably the pr/pa swap, then.  The outline maintains, but I think that I read "pr" and "pa" as being semantically(?) 1 letter.  prtnialbe Ah yes. That did it. Not sure I can offer a fix to the algorithm though.

@Draco18s Well, really there should be more groups, r has a unique lower-right vacuum, and there is also the amount of "ink" per character and its width…

@Adám Too many groups and there wouldn't be valid swaps. :P Character width can be mitigated by only using a monospaced font to read the results in. But yes.

Jelly, 80 74 bytes
-2 bytes by moving from czar + vex + mow + sun to czar + vexes + unmown (the repeated es and ns are not a problem)
-1 byte using Tị rather than ȦÐf
-1 byte using Œle€Øa rather than i@€ØB>⁵
-2 bytes by reconfiguring the layout a little
Tị
TẊị⁹ż@œp
e€ç⁸F
W;“HọƊṘ€.`]HɲøƁḤ0ẉlfrøj⁷»Ḳ¤ç/
Ḣ,ṪjÇḟ0
Œle€Øað¬œpÇ€ÑżœpÑ¥

A full program taking a character list (or Python formatted string), which prints the result of the scrambling.
Try it online!
A huge amount of difficulty for Jelly here it seems (either that or I have missed a trick, which has been known to happen!) This will surely be beaten by languages with better string manipulation like Retina(no random functionality) or 05ab1e.
How?
Tị - Link 1, get truthy items: list a
T  - truthy indexes of a
 ị - index into a

TẊị⁹ż@œp - Link 2, selective shuffle: list a, list b
T        - truthy indexes of a (those indexes that may be shuffled in b)
 Ẋ       - random shuffle
   ⁹     - link's right argument, b
  ị      - index into (gets the shuffled values)
      œp - partition b at truthy indexes of a
    ż@   - zip with reversed @rguments (place shuffled values - yields a list of lists)

e€ç⁸F - Link 3, value selective shuffle: list a, list b
e€    - c exists in b? for €ach c in a (1s where b has shuffle-able characters, else 0s)
   ⁸  - link's left argument, a
  ç   - call the last link (2) as a dyad
    F - flatten the result (from the yielded list of lists to one list)

W;“HọƊṘ€.`]HɲøƁḤ0ẉlfrøj⁷»Ḳ¤ç/ - Link 4, perform all shuffles on a word's innards: list x
W                             - wrap x in a list
                          ¤   - nilad followed by link(s) as a nilad:
  “HọƊṘ€.`]HɲøƁḤ0ẉlfrøj⁷»     -   compression of s(bdfhkl)+d( czar)+d(vexes)+d(unmown)+s( gpqy)+d( ti)
                              -     where d() looks up a word in Jelly's dictionary and s() adds a string to the compressed output.
                         Ḳ    -   split on spaces: ["bdfhkl","czarvexesunmown","gpqy","ti"]
                           ç/ - reduce by last link (3) as a dyad (shuffles by each in turn)

Ḣ,ṪjÇḟ0 - Link 5, shuffle a word: list w
Ḣ       - head w (yields the leftmost character and modifies w)
  Ṫ     - tail w (yields the rightmost character and modifies w)
 ,      - pair
        -   Note: head and tail yield 0 when w is empty, so ['a'] -> ["a",0] and [] -> [0,0]
    Ç   - call the last link (4) as a monad (with the modified w)
   j    - join
     ḟ0 - filter discard zeros (thus single or zero letter words pass through unchanged)

Œle€Øað¬œpÇ€ÑżœpÑ¥ - Main link: list s
Œl                 - convert s to lowercase, say t
    Øa             - lowercase alphabet, say a
  e€               - c exists in a? for €ach c in t
      ð            - dyadic chain separation (call that u)
       ¬           - not (vectorises across u), say v
        œp         - partition s at truthy indexes of v (extract words, plus empty lists from within strings of non-alphabetic characters)
          Ç€       - call the last link (5) as a monad for €ach (shuffle their innards)
            Ñ      - call the next link (1) as a monad (only keep the actual words)
                 ¥ - last two links as a dyad:
              œp   -   partition s at truthy indexes of u (get the non-words, plus empty lists from within strings of alphabetic characters)
                Ñ  -   call the next link (1) as a monad (only keep actual non-words)
             ż     - zip together
                   - implicit print

It's actually harder than I thought.

@LeakyNun welp it took me much longer than 10 minutes to grapple with it.

Wow, congrats on being the first. Longest Jelly program I've ever seen.

You're right, this would probably be a breeze in Retina... if it had any sort of randomness...

@Adám - There is this and the entry it cracked, although that was code-bowling - as for golf I do ... have ... a few ... longer Jelly submissions.

@JonathanAllan Cool. It is way up there though.

@MartinEnder Ah, that's a shame - one for the TODO list.

@JonathanAllan Yeah, it's been on there for ages, and is probably going to be part of the next release, because this has been bugging me many times.

czar + vex + mow + sun‽

@Adám dictionary lookups to form acemnorsuvwxz. I will write up commented code at some point too.

@MartinEnder Random regex... How about ?? which might or might not match that character/group. Would be really fun with backtracking involved. I've always wanted something like that for log parsing.

PHP, 278 Bytes
<?=preg_replace_callback("#\pL\K(\pL+)(?=\pL)#",function($t){preg_match_all("#([^bdf-lpqty])|([bdfhkl])|([gpqy])|([it])|(j)#",$t[0],$p);foreach($p as$v){$k++?$c=array_keys($n=array_filter($v)):$o=[];!$n?:shuffle($n)&&$o+=array_combine($c,$n);}ksort($o);return join($o);},$argn);

Try it online!
Expanded

echo preg_replace_callback("#\pL\K(\pL+)(?=\pL)#" # patter \pL is shorter as [a-z]
,function($t){  # replacement function beginning
  preg_match_all("#([^bdf-lpqty])|([bdfhkl])|([gpqy])|([it])|(j)#",$t[0],$p); # makes groups with the regex. group 0 is the whole substring
  foreach($p as$v){ # loop through groups
    $k++?$c=array_keys($n=array_filter($v)):$o=[]; # group 0 make new empty replacement array in the other case filter the group remove empty values.
    #You gain an array with the keys as position in the substring and the values
    #store the key array and the values array
    !$n?:shuffle($n)&&$o+=array_combine($c,$n);
    #if values shuffle the values and make a new array with the keys and the shuffled values and merge the new array to the replacement array
  }
  ksort($o); # sort the replacement array ascending positions
  return join($o); # return the replacement as string
},$argn);

functions
array_combine
array_filter
array_keys
ksort
preg_replace_callback
shuffle

Tip: You could use the "disable output cache" setting on TIO, rather than running the code a few times. I just ran it with the example - All good!

@JonathanAllan Thank You for the tip with the cache. It was hard enough to find a way to solve this

Pyth, 79 bytes
sm?td++hduuXNhTeTC,f@@GTHUG.S@HGG+-GJ."by❤jã~léÜº"cJ\jPtdedd:jb.z"([A-Za-z]+)"3

where ❤ is U+0018.
Try it online!
Sample
It is well knwon that a text can still be raed while the irnands of its wrods have been seraclbmd, as long as their first and last lettres plus their oaervll ontliues rmeain conntsat. Given a text, sacmrble each wrod acrncdiog to thsee relus:

Scamrlbing must be (puesdo) rnadom.
A word is a suqencee of the Latin chraectars, A thuorgh Z.
Only iaitinl lettres will eevr be uppaersce.
The first and last lettres msut stay uotcnuhed.
When srancblimg, only lettres wiihtn one of the follnwiog guorps may enxhcage plecas:

amsuvrcnoxewz
bhfkdl
gpqy
it
j (stays in place)

Can't you save with \pL instead of [A-Za-z]?

@Adám What is \pL?

Any character with the property of being a Letter.

I don't think it works here...

wouldn't \w be enough?

@SargeBorsch that would match digits also

@LeakyNun I know, I know. I never programmed in Pyth (or Python) so I have no idea which regex syntax it uses.. In java it's (i?)[a-z] which is indeed longer than [A-Za-z]. In Retina it's i`[a-z], which is shorter than [A-Za-z]. If Pyth's syntax is 1 or 2 bytes it's shorter, otherwise it's easier to just keep [A-Za-z]. Ah well, I'll just delete my comments to clean up this comment section.. It was just an idea.. Next time I'll google the regex syntax before making the comment, sorry.

The try it online link says that it's 84 characters.

@isaacg updated.

JavaScript 176 bytes
t.replace(/\B(\w+)\B/g,b=>{return[/[acemnorsuvwxz]/g,/[bdfhkl]/g,/[gpqy]/g,/[it]/g].forEach(d=>{g=b.match(d),b=b.replace(d,c=>{return g.splice(Math.random()*g.length,1)})}),b})

Method:

RegExp iterates over the centre of each word (/\B(\w+)\B/g) using 1st replace fn.

1st replace fn iterates an array of RegExp's for each letter-group  (/[bdfkhl/g, /[gqpy]/g, etc.. ).

Each iteration builds a temp array of word-centre's characters appearing in current letter-group.

Each iteration then uses current letter-group's RegExp to iterate over entire word-centre, using a 2nd replace fn.

2nd replace fn randomly splices the temp array, removing a random character and returning it.

Demo:
Run it in JSFiddle: https://jsfiddle.net/CookieJon/bnpznb7r/

Welcome to PPCG. Amazing first answer. However, I think you need \pL(\pL+)\pL rather than \B(\w+)\B to exclude digits and underscore.

Ah, thanks!  Must admit regex is not my bag (I have to look up the reference EVERY time I use it!)  I can swallow the 3 extra characters... will update my answer shortly thanks again. :-)

Incredible first answer! :) A few, quick improvements for you to get you down to 155 bytes, including @Adáms correction above: t=>t.replace(/\B[a-z]+\B/gi,b=>([/[acemnorsuvwxz]/g,/[bdfhkl]/g,/[gpqy]/g,/[it]/g].map(d=>b=b.replace(d,c=>g.splice(new Date%g.length,1),g=b.match(d))),b))

@Shaggy I think b=>[...].map(...)&&b saves another byte. Also I'm not sure your i is necessary.

If @Adám is going to be strictly picky with his word definition then you'll need to use t.replace(/[A-Za-z]([a-z]+)(?=[a-z])/g,(w,b)=>...w[0]+b...) or some such.

@Neil, yeah there's definitely more room for improvement. Don't know where that i flag snuck in from, though.

I'm about to update my answer with these nifty tricks, but I can't grok one of them...   g.splice(new Date%g.length,1),g=b.match(d)   So I guess the comma there makes this assignment a single expression (hence no return), I guess assigning is RTL (hence g defined after the splice), but why will this only work in the arrow function? I.e. executing the following in console throws 'g undefined' error: g.splice(1,1),g=[1,2,3,4]?  What am I missing?

@Neil Why? Input is printable ASCII+newlines only. What will \pL(\pL+)\pL find which isn't a word? Also remember that 2-letter-words (and 3-letter words) cannot be scrambled (as there are no additional innard-letters to exchange with), so there is no need to match them.

Sorry, what does \pL(\pL+)\pL do?  http://regexr.com/ says it matches the 'p' and 'L' characters...?

@Bumpy What you're actually seeing is b.replace(d,c=>g.splice(...),g=b.match(d)). So we're trying to pass three parameters to replace instead of two. The third is ignored by replace, but it still gets evaluated, which includes the side-effect of setting g.

@Adám This is JavaScript RegExp flavour, so it doesn't have all that fancy PCRE stuff like character properties or lookbehinds.

Thanks Neil, gotcha.  Also while you're here, care to explain .map(...)&&b -- I'm baffled!  Still not sure which regex to use for the main one, either.   After this, I think I'll publish updated version and draw a line under it for now. Thanks... this is quite fun!

Definitely better than mine, hahah. Chapeau! :)

In your version you have b=>{return[...].forEach(...),b}. Let's start with the forEach. It's 7 bytes, but we can use map to achieve the same side-effect, thus saving 4 bytes. Next, the {return...}. We can switch this to (...) to save 6 bytes... but we can go one better; since map always returns a truthy value, we can switch the , to &&, which then makes the ()s unnecessary, ending up with b=>[...].map(...)&&b. We've saved a total of 11 bytes.

Thanks again...  I've been poring over this and believe I understand all the suggestions (apart from the correct regex).  Will update later now, I've started another code golf challenge I have to finish first!! :-) (addictive!)

C, 453, 356 369 bytes
#define F for
#define M rand()%s+1+q
char a[256],*b=" acemnorsuvwxz\1bdfhkl\1gpqy\1it\1j";g(c,t)char*c,*t;{static int i,j,k,w,v,n,q,s,r;r=-1;if(c&&t){strcpy(c,t);if(!k)F(j=i=k=1;b[i];++i)b[i]-1?(a[b[i]]=j):++j;F(r=i=0;c[i];){F(;isspace(c[i]);++i);F(q=i;!isspace(c[i])&&c[i];++i);F(s=v=i-q-2;--v>0;)if(a[c[j=M]]==a[c[w=M]]&&a[c[j]])n=c[j],c[j]=c[w],c[w]=n;}}return r;}

ungolf with comments
// Input in the arg "t" result in the arg "c"
// NB the memory pointed from c has to be >= memory pointed from t
//    the char is 8 bit
#define F for
#define M rand()%s+1+q
char a[256], *b=" acemnorsuvwxz\1bdfhkl\1gpqy\1it\1j";
   g(c,t)char*c,*t;
   {static int i,j,k,w,v,n,q,s,r;
    r=-1;
    if(c&&t)
      {strcpy(c,t);                         // copy the string in the result space
       if(!k)
         F(j=i=k=1;b[i];++i)
             b[i]-1?(a[b[i]]=j):++j;        // ini [possible because at start k=0]
       F(r=i=0;c[i];)
         {F(;isspace(c[i]);++i);            //skip spaces
                                            // the start q the end+1 i
          F(q=i;!isspace(c[i])&&c[i];++i);  //skip word
          F(s=v=i-q-2;--v>0;)               //loop for swap letters of the same set
            if(a[c[j=M]]==a[c[w=M]]&&a[c[j]])
                n=c[j],c[j]=c[w],c[w]=n;
         }
      }
   return r;
  }

#include <stdio.h>
#define G(x,y) if(x)goto y
main()
{char a[256],r[256];
l1:
 gets(a);// i would know the string lenght<256
 g(r,a);
 printf("%s\n",r);
 G(*a,l1);
}

JavaScript (ES6), 380 327 311 294 Bytes
(298 282 265 Bytes excluding the rules)
Thanks to @Shaggy for the useful tips!
((b,d)=>b.replace(/\B[a-z]+\B/gi,f=>(g=>(g.map(j=>(h=d.slice(0,~(rind=d.indexOf(j))?rind:-1),~rind?h.split`,`.length-1:-1)).map((j,k,l,m=[])=>{l.map((n,o)=>n==j?m.push(o):0),sub=m[new Date%(m.length-1)]||k,tmp=g[sub],g[sub]=g[k],g[k]=tmp}),g.join``))([...f])))(s,"aneusvrowxmcz,bhkfdl,gqpy,it");

var f = ((b,d)=>b.replace(/\B[a-z]+\B/gi,f=>(g=>(g.map(j=>(h=d.slice(0,~(rind=d.indexOf(j))?rind:-1),~rind?h.split`,`.length-1:-1)).map((j,k,l,m=[])=>{l.map((n,o)=>n==j?m.push(o):0),sub=m[new Date%(m.length-1)]||k,tmp=g[sub],g[sub]=g[k],g[k]=tmp}),g.join``))([...f])))

var s="Let there be scrambling";
console.log(s);
console.log(f(s,"aneusvrowxmcz,bhkfdl,gqpy,it"))

s="It is well known that a text can still be read while the innards of its words have been scrambled, as long as their first and last letters plus their overall outlines remain constant. Given a printable Ascii+Newline text, scramble each word according to these rules";
console.log(s);
console.log(f(s,"aneusvrowxmcz,bhkfdl,gqpy,it"))

Function f takes in a string of any kind (single word, multiple words, multiple words with signs in it - which it interprets as word-breaking) and an array a string of "rules" of any length separated by commas.
That array of rules, in the case of your question, would be ["aneusvrowxmcz", "bhkfdl", "gqpy", "it"] "aneusvrowxmcz,bhkfdl,gqpy,it"
Some letters don't get mixed even though they could, since you stated in your question that letters "may exchange spaces". If I misinterpreted it, I can change the code to always scramble letters that match the rules.
I know this is an enormous amount of bytes and it won't be able to compete with golfing languages, but I wanted to try anyway, hope you like it :)
Human-readable non-uglified code:
((txt,rules)=>txt.replace(/\B[a-z]+\B/gi,wo=>((w=>(w.map(c=>(h=rules.slice(0, ~(rind=rules.indexOf(c))?rind:-1),~rind?(h.split`,`.length-1):-1)).map((e,i,arr,a=[])=>{
    arr.map((x,i)=>(x==e)?a.push(i):0),
    sub=a[new Date%(a.length-1)]||i,
    tmp=w[sub],
    w[sub]=w[i],
    w[i]=tmp
}),w.join``))([...wo]))))(str, "aneusvrowxmcz,bhkfdl,gqpy,it")

The OP rules have to be included in byte count. By may, I meant have a chance to.

Welcome to PPCG :) You can definitely golf a lot off this.

I was going to try to golf this down for you but, given how much can be done with it, I ran out of time so instead I'll point you here and here to help get you started.

A few quick pointers, though: 01) Get rid of all the vars an lets. 02) Unless it's a recursive function, no need to include the variable declaration (f=) in your byte count. 03) Use currying when a function has 2 parameters (b=>d=> instead of (b,d)=>) and call your function with f(b)(d). 04) You have the i flag so no need to include A-Z in your regex. 05) You can use indexOf or search on a string, without splitting it into an array.

How does suggestion 03 save characters? They look the same to me.

@SteveBennett b=>d=> 6 bytes, (b,d)=> 7 bytes.

@TheLethalCoder Yes, but with b=>d=> you have to use (b)(d), which is 1 character more than (b,d), so isn't it the same thing?

Anyway, I updated the code after shoving off more than 50 bytes. Thanks everyone for the tips!

@Hankrecords Only if you're recursively calling the function, if you don't call it again you don't need to use (b)(d) though I didn't properly look over your code to see if that is the case here.

Hmm, I don't get what you mean. If you have f=b=>d=>..., then f is a function that takes an argument, and returns a function. How could you call f in any way other than f(myb)(myd)? Genuinely curious.

Python 3.6, 349 340 bytes
from itertools import *
from random import *
import re
def S(s):
    C=lambda c:len(list(takewhile(lambda x:c not in x,('j','it','gqpy','bhkfdl'))));L=[];B=[[]for i in range(5)]
    for l in s:c=C(l);L+=[c];B[c]+=[l];shuffle(B[c])
    return''.join(B[n].pop()for n in L)
A=lambda t:re.sub('[A-Za-z]{3,}',lambda x:x[0][0]+S(x[0][1:][:-1])+x[0][-1],t)

Indented with tabs.
The function is named A.
It doesn't use brute force, the runtime is deterministic, as OP asked.

Mathematica 232 Bytes
StringReplace[#,x:Repeated[WordCharacter,{2,∞}]:>""<>(s=StringTake)[x,{i,i}~Table~{i,StringLength@x}/.Flatten[Thread[#->RandomSample@#]&/@(StringPosition[x~s~{2,-2},#]+1&/@Characters@{"acemnorsuvwxz","bdfhkl","gpqy","it","j"})]]]&

The basic idea is to permute the subsets corresponding to the 4 distinct character groups.  Probably room for improvement.

C (clang), 282 263 bytes
-19 bytes thanks to the man (or cat) ceilingcat!!
c,o,d,e,g;l(*f){for(char*s[5]={"aneusvrowxmcz","bhkfdl","gqpy","it"},**h,*i=f,*t;*i;){if(isalpha(*i)){for(t=i;isalpha(*i);)i++;e=i-t-2;for(h=s;*h&&e;*h++)for(c=999;--c;)if(o=1+rand(d=1+rand()%e)%e,index(*h,t[d])&&index(*h,t[o]))g=t[d],t[d]=t[o],t[o]=g;}else++i;}}

Try it online!
Ungolfed:
int func(char*p)
{
    char *groups[] = {"aneusvrowxmcz","bhkfdl","gqpy","it",0}, **g, *s, *t;
    int n,r,i,l,o;

    for (s = p; *s;)
    {
        if (isalpha(*s))
        {
            t = s;
            while (*s && isalpha(*s))
                s++;
            // start scrambling
            l = s - t - 2;
            for(g=groups; *g && l; *g++)
            {
                for(n=999;--n;)
                {
                    i = 1 + rand() % l;
                    r = 1 + rand() % l;
                    if (strchr(*g, t[i]) && strchr(*g, t[r]))
                    {
                        o=t[i];
                        t[i]=t[r];
                        t[r]=o;
                    }
                }
            }
            // end scrambling
        }
        else
            s++;
    }
}

Why would you like to do 999 swap in a word? Do you know that one word of one char has l=-1 and this possibly means that it begin to do 999 possible swap using 1 + rand() % -1 so random write in 2 giga of memory... But possible i see it wrong....

There's unfortunately no magic regarding the use of 999. It's just 1 byte less than 1000 :)

In gcc it seems rand()%(-1) return 0 the first 2 time I tried it. so possible no swap of random 2giga space...% of int is not the % of unsigned...

@RosLup, I'm sorry but I don't follow what you are saying..

239 bytes

Go, 364 357 347 bytes
import(."math/rand";."regexp")
func f(s string)string{return MustCompile(`(\w)(\w+)(\w)`).ReplaceAllStringFunc(s,func(S string)string{k:=S[1:len(S)-1]
for i:=range k{for _,l:=range[]string{"acemnorsuvwxz","bdfhkl","gpqy","it","j"}{if o,_:=MatchString("["+l+"]",k[i:i+1]);o{q:=Intn(len(l));k=k[:i]+l[q:q+1]+k[i+1:]}}}
return S[:1]+k+S[len(S)-1:]})}

Attempt This Online!
Uses an adaptation of my "Cambridge Transposition" solution.

-7 bytes from some reorganization
-10 bytes from using string slices and general cleanup

JavaScript, 151 bytes
Revisiting and expanding on my suggested improvements to Bumpy's solution all these years later.
s=>s.replace(/\B[a-z]+\B/g,m=>[/[^bdf-jklpqty]/g,/[bdfhkl]/g,/[gpqy]/g,/i|t/g].map(r=>m=m.replace(r,c=>d.sort(_=>new Date%3-1).pop(),d=m.match(r)))&&m)

Try it online!

Python 3.8 (pre-release), 241 bytes
Breaks, if words contain numbers (which is quite unlikely..)
import random,re
g=lambda c:sum([(p:="jitgpqybdfhkl".find(c))<0,p<1,p<3,p<7])
def f(m,C=[[],[],[],[],[]]):
 for c in m[0]:l=C[g(c)];l+=[c];random.shuffle(l)
 return''.join(C[g(c)].pop()for c in m[0])
h=lambda s:re.sub('(?<=\w)\w+(?=\w)',f,s)

Try it online!
Python 3.8 (pre-release), 298 281 261 255 249 bytes
import random,re
g=lambda c:sum([(p:="jitgpqybdfhkl".find(c))<0,p<1,p<3,p<7])
def f(m,C=[[],[],[],[],[]]):
 t,*u,v=m[0]
 for c in u:l=C[g(c)];l+=[c];random.shuffle(l)
 return t+''.join(C[g(c)].pop()for c in u)+v
h=lambda s:re.sub('[A-Za-z]{4,}',f,s)

Try it online!

Clojure, 326 322 324 bytes
Update 1: replaced (map(fn[[k v]]...)...) with (for[[k v]...]...)
Update 2: fixed regex, using \pL instead of \w etc.
#(let[G(zipmap"bdfhklgpqyitj""0000001111223")](apply str(flatten(interleave(for[v(re-seq #"\pL+"%)w[(rest(butlast v))]W[(into{}(for[[k v](group-by G w)][k(shuffle v)]))]R[(rest(reductions(fn[r i](merge-with + r{(G i)1})){}w))]][(first v)(map(fn[c r](nth(W(G c))(-(r(G c))1)))w R)(if(second v)(last v))])(re-seq #"\PL+"%)))))

I'm looking forward to seeing something shorter. Earlier ungolfed version with a few example runs:
(def f #(let[G(zipmap"bdfhklgpqyitj""0000001111223")] ; Create groups, the longest "acemnorsuvwxz" goes to an implicit group nil
          (apply str(flatten(interleave
                              (for[v (re-seq #"\w+"%)                                          ; Iterate over words
                                   w [(rest(butlast v))]                                       ; This holds the middle part
                                   W [(into{}(map(fn[[k v]][k(shuffle v)])(group-by G w)))]    ; Create shuffled groups
                                   R [(rest(reductions(fn[r i](merge-with + r{(G i)1})){}w))]] ; Calculate cumulative sum of group items, used to look-up nth value from shuffled values
                               [(first v)                                     ; First character
                                (map(fn[g r](nth(W g)(-(r g)1)))(map G w)R)   ; Shuffled middle part
                                (if(>(count v)1)(last v))])                   ; Last character, unless the word is just a single character
                              (re-seq #"\W+"%)))))) ; Interleave with spaces, commas, newline etc.

(f "It is well known that a text can still be read while the innards of its words have been scrambled, as long as their first and last letters plus their overall outlines remain constant.\n")
;  "It is well known that a txet can sitll be read wlihe the irnands of its wrods hvae been seacmlbrd, as lnog as their fisrt and lsat letters plus their oavrell ontlieus rmaein cnontast.\n"
;  "It is well kwonn that a text can sitll be raed wlihe the innards of its wrods hvae been seramlbcd, as long as their fisrt and lsat lettres plus their oravell ouiltnes rmeain cnsatont.\n"
;  "It is well konwn that a text can still be read while the iarnnds of its words have been sraemlbcd, as lnog as their first and lsat lrttees plus their oaevrll ontlieus remain canntsot.\n"

I think you need \pL+ and \PL+ rather than \w+ and \W+ to exclude digits and underscore.

Perl 6, 241 195 bytes
Includes +1 byte for -p command-line switch.
s:g/(<:L>)(<:L>+)(<:L>)/{$0}{[~]
$1.comb.pairs.classify({first
.value~~*,:k,/<[bdfhkl]>/,/<[gpqy]>/,/<[it]>/,/j/,!0}).values.map({$_».key
»=>«$_».value.pick(*)})».List.flat.sort».value}$2/;

Ungolfed:
s:g/(<:L>)(<:L>+)(<:L>)/{$0}{
    [~]
    $1.comb
    .pairs
    .classify({
        first .value ~~ *, :k,
            /<[bdfhkl]>/,
            /<[gpqy]>/,
            /<[it]>/,
            /j/,
            !0
    })
    .values
    .map({ $_».key »=>« $_».value.pick(*) })
    ».List
    .flat
    .sort
    ».value
}$2/;

I think you need (\pL)(\pL+)(\pL) rather than (\w)(\w+)(\w) to exclude digits and underscore.

Actually \pL includes a lot of characters outside of the allowed range of latin letters A-Z.  I've updated my code to reflect the requirements more accurately.

Which characters? Remember that input is restricted to printable ASCII+Newlines.

Ah, I missed that.  \pL is spelled <:L> in Perl 6 though.

C#, 438 394 380 374 bytes
namespace System.Text.RegularExpressions{using Linq;s=>Regex.Replace(s,@"\p{L}(([gpqy])|(i|t)|(j)|([bdf-l])|([a-z]))*?[a-z]?\b",m=>{var a=m.Value.ToArray();for(int i=1,j;++i<7;){var c=m.Groups[i].Captures;var n=c.Cast<Capture>().Select(p=>p.Index-m.Index).ToList();foreach(Capture p in c){a[j=n[new Random().Next(n.Count)]]=p.Value[0];n.Remove(j);}}return new string(a);});}

Save 10 bytes thanks to @MartinEnder♦.
Annoyingly, CaptureCollection doesn't implement IEnumerable<T> and that's why the .Cast<Capture>() is needed. Hopefully, I can combine the Linq query and the foreach loop though.
I'm sure there's a lot that can be golfed but it took me long enough just to get it working...
Try it online!
Formatted/Full version:
namespace System.Text.RegularExpressions
{
    using Linq;

    class P
    {
        static void Main()
        {
            Func<string, string> f = s =>
                Regex.Replace(s, @"\p{L}(([gpqy])|(i|t)|(j)|([bdf-l])|([a-z]))*?[a-z]?\b", m =>
                {
                    var a = m.Value.ToArray();

                    for (int i = 1, j; ++i < 7;)
                    {
                        var c = m.Groups[i].Captures;

                        var n = c.Cast<Capture>().Select(p => p.Index - m.Index).ToList();

                        foreach(Capture p in c)
                        {
                            a[j = n[new Random().Next(n.Count)]] = p.Value[0];
                            n.Remove(j);
                        }
                    }

                    return new string(a);
                });

            Console.WriteLine(f("Scramble words while preserving their outlines"));
            Console.ReadLine();
        }
    }
}

Perl 5 -p, 104 bytes
s|\w+|$t=$&;map{@a=$t=~/\B[$_]\B/g;$t=~s/\B[$_]\B/splice@a,rand@a,1/ge}'^bdf-lqpty',bdfhkl,gqpy,it;$t|ge

Try it online!


text:
Am I outgolfed by Dennis?
According to legend, almost everyone is outgolfed by Dennis. If not, they will be.
Now I'm curious if I'm one of those 'almost everyone'.
You will be given a link to an answer in the format of https://codegolf.stackexchange.com/questions/[QUESTION ID]/[QUESTION NAME]/#[ANSWER ID].
Find the length of the code, which we will assume as the last number on the first line (markdown wise) of the answer in the link.
Then, search for Dennis' answers, and do the same.
Now compare the input's and Dennis' answers code length, and if it is out-golfed (meaning one or more answer of Dennis' is shorter than that of the input answer), output a truthy value, and if not, a falsy value.
If there is no answer belonging to Dennis on the same question as the answer, output a falsy value.
Examples

Link : true
Link : false (At least for now, tell me when it changes)

Rules

You may use any form of truthy/falsy value.
The question of the answer you're given will always be code-golf.
The question may not have an answer of Dennis', but the inputted answer will never belong to Dennis.
You may assume there is always a number on the first line of the answer.

Can we assume there will always be an answer by Dennis on the given question, and that the given answer will not be Dennis' answer?

@Mayube No, and yes.

Do we need to handle paging or can we assume both answers will be on the same page if there are multiple pages of answers?

@Shaggy former.

@SIGSEGV If there is no answer by Dennis do we output false because Dennis has not outgolfed the answer?

@Mayube Yes....

Python 3.6 + requests + bs4 - 363 358 bytes
import bs4,re,requests
u,n=input().split("/#");i=1;d=y=float("inf")
while i:
 A=bs4.BeautifulSoup(requests.get(u+f"?page={i}").text,"html.parser")(class_="answer")
 for a in A:
  c=int(re.findall("\d+",(a("h1")+a("h2")+a("p"))[0].text)[-1])
  if "Dennis"in a(class_="user-details")[-1].text:d=min(c,d)
  if a["data-answerid"]==n:y=c
 i=A and i+1;
print(d<y)

Prints True or False.
Note: does not currently work on the second link because of invalid HTML produced by this answer (the em and strong tags are terminated in the wrong order at the end of the second line, and causes the parser to miss the username block). Try it on this link instead.
Using the API - 401 380 bytes
import requests,re
q,A=re.findall("\d+",input());i=1;d=y=float("inf")
while i:
 r=requests.get(f"https://api.stackexchange.com/2.2/questions/{q}/answers?site=codegolf&filter=withbody&page={i}").json();i=r["has_more"]and i+1
 for a in r["items"]:
  c=int(re.search("(\d+)\D+$",a["body"]).group(1))
  if a["owner"]["user_id"]==12012:d=min(d,c)
  if a["answer_id"]==A:y=c
print(d<y)

Note that this also fails on the second link, but because one answer started with This may be foul play. instead of the header...

Consider using the Stack Exchange API to get answer data instead via JSON parser, just make sure filter=withbody is in your GET request in order to obtain the answer body to grab the byte count

With the API version, you used a twice (once to set the answer ID, and another when iterating r["items"], which would lead to incorrect behavior. Also, you don't need to set the pagesize (it will default to 30). c=int(re.search(r'(\d+) bytes').group(1)) should give you a more accurate retrieval of bytecount and is shorter, and if it still fails, (\d+)\s*bytes does the trick but is a bit longer. Finally, i=r["has_more"]and i+1 is shorter than your ternary conditional.

Actually, forget about the regex match. I forgot to account for adding the answer body in the function call so that part is longer. The other suggestions are still valid, though.

@ValueInk Thanks, bit shorter now. Looks like we need a golfing language just for the API, its calls are sooo long...

Perhaps. But honestly there's also the fact that you have a nice HTML parser, plus the fact that you're given the question URL by default. If the input were two numbers instead, there would be quite a bit of overhead for getting the page for the codegolf question as well.

True, but it turns into parsing SE's HTML oddities vs long but safe(r) API calls. Its amusing that both fail on the same link though...

Ruby, 314 315 308+20 = 334 335 328 bytes
Uses the flags -n -rjson -ropen-uri. +1 byte from fixing a minor bug.
-7 bytes by discovering the open-uri Ruby default library.
~/(\d+)\D+(\d+)/
u="http://api.stackexchange.com/2.2/questions/#$1/answers?site=codegolf&filter=withbody&page=%s"
n=eval$2
a="answer_id"
j=1
o=[]
(o+=r=JSON.parse(open(u%j).read)["items"]
j=r!=[]&&j+1)while j
p o.select{|e|e["owner"]["user_id"]==12012||e[a]==n}.min_by{|e|e["body"][/\d+\s*bytes/].to_i}[a]!=n

source: Stack Exchange

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

sort: votes


text:
Martin vs Dennis - Round 1: Who has more rep?
I know there have been a lot of challenges about "the two best code-golfers in the world", but this one is a bit more unique, being Round 1 in a series of (future) challenges involving the two of them.

Your task is to write a program or function that returns two different non-whitespace ASCII strings, corresponding to the one who has more reputation at the moment the program is ran, between Dennis ♦ and Martin Ender ♦. The tricky part is that you must output the exact string "tie" in case the reputation is identical (not likely), and the two different non-whitespace ASCII strings mentioned above should be different than "tie" *.
No input can be taken, such as usernames or user ids. As usual, URL shorteners are forbidden, and so are the common loopholes.
Examples:
Let the chosen string for Dennis be "D" and the chosen one for Martin Ender be "M" (should be specified)

If Dennis' rep > Martin Ender's rep => D
If it's the other way around => M
If it's a tie => tie

IMPORTANT! Voting on posts by Dennis & Martin for the  sole purpose of affecting a tie in order to test the solutions below constitutes targeted voting which is forbidden across the Stack Exchange network. If you want to test that a solution properly outputs tie then change the IDs in it to those of 2 users you know to be tied. See this Meta post for more details.

*I think no one would have used that, anyway

"... the two best code-golfers in the world ..." [citation-needed]

Can we assume that they will always be #1 and #2 in this community?

Yes, you can, as long as they are the #1 and #2, then you update the answer :)

A friendly reminder: targeted voting is forbidden on the entire Stack Exchange network. Voting on Martin's and my posts just to test submissions to this challenge is not allowed.

@Dennis we all know that, but thanks for the reminder. It was just a joke, don't take it seriously

The thing is, if you look at Martin's and my own rep history over the last couple of days, it seems like a handful of users did need a reminder.

@Mr.Xcoder, feel free to edit/move that notice I just edited in.

@Shaggy It's great that you have added that note. Hopefully, the users involved will stop doing that

Sorry for my grammar, I meant to say Although one of the answers has been accepted, it would be nice to see some more interesting solutions

What do you exactly mean by "interesting"? :)

Any new smart answer that uses a different approach than the current ones

So ... when's round 2?!

@Shaggy it's coming soon. I have some minor things to change till I post it.

To @MartinEnder at the top, citations are unneeded for facts that are common knowledge.

still waiting for round 2

05AB1E, 65 64 bytes
Code:
•в=6{•5ôvy’ƒËŠˆ.Â‚‹º.ŒŒ/†š/ÿ’.w’„Ö="Âˆ"’¡1èт£þ}})ZQā*O<“D M·‡“#è

Uses the 05AB1E encoding.

Explanation:
•в=6{• converts the number в=6{ from base 255 to base 10, resulting in 1201208478. The first half being the ID of Dennis (12012) and the second half being the ID of Martin (8478). Split into pieces of 5 using 5ô to get the following array:
['12012', '08478']

Luckily, we can leave the leading zero from Martin's ID, since this will still work (check the link before clicking to see the leading zero).
We now loop through this array using vy and construct the following string from this 05AB1E code:
’ƒËŠˆ.Â‚‹º.ŒŒ/†š/ÿ’  -->  codegolf.stackexchange.com/users/ÿ

Whereas ÿ is the current element of the iterator (using string interpolation) Try it online!
After constructing the link, .w reads all data from the link, resulting into a huge amount of text. To scrape the reputation from this, we need to split on the string title="reputation". Or in a more compressed version: ’„Ö="Âˆ"’. Split on this piece of string (with ¡) and get the second element (with 1è) and keep the first 100 characters (with т£).
Now, our scraped text looks a bit like this:
>
        139,883 reputation

<div class="ba

This part is easy, we just remove anything but digits to remain the reputation number, for which we have a builtin (þ). We end the loop and wrap everything into an array }}).
Finally, we can go on to processing the reputation numbers:
ZQā*O<“D M·‡“#è   -   On stack: an array in the format [Dennis rep, Martin rep]

Z                 # Get the maximum of the array
 Q                # Check for equality with the array
  ā*              # Multiply by it's index (1-indexed)
    O<            # Sum and decrement by 1
      “D M·‡“#    # Push the array ['D', 'M', 'tie']
              è   # Get the element on the index of the sum

Which results in either D, M or tie.

I didn't know that 05AB1E can access internet APIs, this answer kind surprises me => +1

I always like how you and others come up with ways to get a certain number. :) +1 Btw, is the part "second element (with 1è) and keep the first **100 characters** (with т£." supposed to be completely in code-blocks, or should it be "second element (with 1è) and keep the first 100 characters (with т£)." instead? I guess a typo, but if it's supposed to be like this I'm confused..

@KevinCruijssen Huh, I have no idea how that happened, but it's fixed now. Thanks for the heads up! :)

it seems incorrect (I don't know how to correct this kind of code, sorry), Dennis: 140,033; Martin: 140,003, but I tried your code here https://tio.run/nexus/05ab1e#@/@oYdGFTbZm1UDa9PCWsspHDTOPTTrcfXTB6Ta9w02PGmY9ath5aJfe0UlHJ@k/alhwdKH@4f1ANXrlQOJRw7zD02yVDjedblMCcg8tNDy84mLTocWH99XWakYFHmnU8rd51DDHRcH30PZHDQuBTOXDK/7/BwA, it yield tie. Shouldn't it ouput D instead?

@Eddie .w requires web access, which is restricted on TIO (it runs 05AB1E in safe mode). In the offline interpreter, it should work.

@Adnan Nitpick: TIO no longer runs 05AB1E is safe mode, but the sandbox that runs all user requests cuts off all internet access.

@Dennis Oh, that's neat! Thanks for letting me know :)

PowerShell v3+, 147 123 119 103 101 96 Bytes
$a,$b=irm api.stackexchange.com/users/12012`;8478?site=codegolf|% I*|% r*n;$a-$b|% T*g "D;M;Tie"

Saved 24 bytes using true/false output instead of the names.
Saved another 4 by restructuring the final checks.
saved 16 by getting only the reputations of the two users from the request, saves having to use the |% r*n more than once, also means we can get rid of like a million brackets, and two useless variables.
-2 thanks to TessellatingHeckler - using an escape char instead of two doublequotes for the url, also removed the @ from the array which was un-needed (oopsie)
used a weird .ToString trick I never knew existed until now reccomended by TessellatingHeckler -5, and finally below 100.

Version which returns names:
$a,$b=irm "api.stackexchange.com/users/12012;8478?site=codegolf"|% I*
if(($c=$a|% r*n)-eq($d=$b|% r*n)){"tie"}else{@(($a|% d*),($b|% d*))[$c-lt$d]}

this looks pretty messy due to the shortening of parameter names.
anywhere |% r*n appears we're getting the ReputatioN, and |% d* is the Display_name
uses Invoke-RestMethod (alias irm) to query the API, stores the result named Items (gotten using |% I*), into the two variables $a & $b, one for each pro golfer's, the ToString (|% T*g) trick results in one of the values D,M or Tie if the number is odd/even/zero.

I did not expect powershell to be the shortest. +1

@Riker Pyth would've presumably been, but it has a horrible bug.

@EriktheOutgolfer it's not a legitimate victory but i'll take it. would be nice to see a non-competing pyth answer after the bug is fixed though.

This wont work in PowerShell 2.0 so i think you need to add a version to your post. Beautiful to look at though.

@Matt I think the irm command was first added in v3 - don't have access to a v3 shell to check sadly, definitely not in v2 though, thanks for that.

Fine, you win; no way I'm going to beat this now!

Got a short domain? Put a reverse proxy rewrite on it to shorten that hostname... Tried making a hosts file entry but the SE servers need the host header..

@ConnorLSW It was that and the Foreach-Object syntax you are using.

So your code is 103! = 9.902900716486180407546715254581773349090165822114492483005280554699... × 10^163 bytes long..? :P

@totallyhuman You beat me to it ;)

@TessellatingHeckler check the answer for the last bit, you got it below 100! - never knew ToString worked like that with +/- numbers, will remember for future.

Python 2, 160 bytes
from requests import*
print cmp(*[get('http://api.stackexchange.com/users/12012;8478?%ssite=codegolf&filter=!9aK21rboZ'%s).text for s in'order=asc&',''])or'tie'

Not the shortest Python answer, but the shortest one so far that doesn't make any assumptions.
Prints 1 if Martin has more rep, -1 if I do.

JavaScript (ES6), 167 156 146 144 141 132 103 bytes
Stupid fetch and its stupid, expensive Promise chaining!
Assumes, as currently allowed, that Dennis & Martin will always be the 2 top ranked users. Needs to be run from the root level of api.stackexchange.com. Returns  a Promise object (as is now permitted by consensus) containing tie or the JSON object for whoever has the most rep at the time. If the JSON object isn't considered valid output then add 5 bytes for .link.
_=>fetch`users/?site=codegolf`.then(r=>r.json()).then(({items:[j,i]})=>j[r="reputation"]==i[r]?"tie":j)

Saved 11 bytes thanks to Kevin suggesting I return the profile link rather than the first letter of the display_name, which also provide better future-proofing against them changing their usernames to start with the same letter!
5 bytes saved adapting a tip from kamoroso94 on a another solution of mine.

Try It

f=
_=>fetch`//api.stackexchange.com/users/?site=codegolf`.then(r=>r.json()).then(({items:[j,i]})=>j[r="reputation"]==i[r]?"tie":j)
f().then(console.log)

Alternative
If a time comes that Dennis & Martin aren't at the top and we still want to know who has the most rep between them then we'd need the following, at a cost of an additional 10 bytes.
_=>fetch`users/12012;8478?site=codegolf`.then(r=>r.json()).then(({items:[j,i]})=>j[r="reputation"]==i[r]?"tie":j)

You can change .display_name[0] to .display_name, or an even shorter alternative that is still unique for both of them: .link. ;) Or just the entire JSON, but I'm not sure if it fits in the alert-popup.

Thanks, @KevinCruijssen; I had to use an extract of the username as Martin's contains a space, which isn't allowed. Good shout on using link, though, I was using a filtered API query to only return the info I needed.

@KevinCruijssen I've dumped whole HTML pages into alert popups when dealing with AJAX returns. It can handle it.

@Draco18s, alerting a JSON object, though, will just display [object Object].

@Shaggy True, true, it would.

Python 3, 160 157 151 bytes
from requests import*
a,b,*c=get('http://api.stackexchange.com/users?site=codegolf').json()['items']
r='reputation'
print(['tie',a['link']][a[r]>b[r]])

-3 bytes thanks to @KevinCruijssen
Prints a link to the user having more reputation
Assumes they are on #1 and #2

Without making any assumptions, Python 2, 157 bytes:
from requests import*
a,b=get('http://api.stackexchange.com/users/8478;12012?site=codegolf').json()['items']
r='reputation'
print['tie',a['link']][a[r]>b[r]]

PHP, 167 Bytes
prints -1 for Dennis , 1 for Martin Ender. tie in case of a tie

<?=($b=($t=json_decode(gzdecode(join(file('http://api.stackexchange.com/users/12012;8478?site=codegolf&order=asc'))))->items)[0]->reputation<=>$t[1]->reputation)?:tie;

Python, 226 225 221 bytes
I feel like this is too long.
import requests as r,re
def f(i):d=re.sub('[, ]','',r.get('http://codegolf.stackexchange.com/users/'+i).text);D=d.index('"reputation">')+14;return int(d[D:d.index('<',D)])
a=f('8478')
b=f('12012')
print([a>b,'tie'][a==b])

Prints "True" if Martin has more rep than Dennis, "False" if Dennis has more rep than Martin, and "tie" if they have the same (theoretically. I can't test this :P).
https -> http for 1 byte thanks to @KevinCruijssen!
re as r, r.sub -> re, re.sub for 4 bytes thanks to @ovs!

I'm not entirely sure, but is it possible to change https to http? I know PPCG is completely https now, but perhaps it auto-directs to HTTPS when you navigate to HTTP in Python, just as it does in a browser?

@KevinCruijssen Ah yes, I don't know what I was thinking there. Thanks!

You don't need re as R. Just use import requests as r,re and re.sub

@ovs Heh, my original approach was different Thanks!

I think you can use the cmp function to save some bytes by replacing the last three lines with something like print['tie',0,1][cmp(f('8478'),f('12012'))]

@Loovjo Thanks, but unfortunately this only works for Python 2, and the requests part seems to fail for py2.

Bash + jq, 140 133 bytes
w3m 'api.stackexchange.com/users/12012;8478?site=codegolf&sort=name'|jq '.items|map(.reputation)|1/(index(min)-index(max))'||echo tie

Formatted and explained
First, we curl w3m the API (and use --compressed, or short --com to un-gzip):
w3m 'api.stackexchange.com/users/12012;8478?site=codegolf&sort=name'

That's some JSON. Notice the order ist stable, not based on reputation. JQ then processes the JSON, which is what it's made for.
.items                          # take the items array
| map(.reputation)              # extract only the reputations
| 1 /
  (index(min)-index(max))       # This checks if the bigger value is first (1) or last (-1) in array

We use 1/x above to generate an division-by-zero error when min==max, so in a tie situation. The ||echo tie in bash catches that.
Note that a warning is printed on stderr by JQ in that case, but we consider only stdout the actual result of the program ;)

You can use w3m instead of curl --com to save a few bytes. Also, I think it's worth mentioning that this requires jq 1.5, as jq 1.4 didn't raise an error for division by zero.

True, thanks for the hint. W3m is exactly what I was looking for.

Python 2, 228 223 204 199 bytes
I did this on a mobile hotspot so... it's not great... Assumes both of them will always be in the same hundred thousand. Doesn't assume anything now. :D
import urllib as l,re
f=lambda i:int(re.search('n">\s*([\d,]+)',l.urlopen('http://codegolf.stackexchange.com/users/%d'%i).read()).group(1).replace(',',''))
d,m=f(12012),f(8478)
print[d>m,'Tie'][d==m]

Prints True if Dennis has more reputation than Martin, False otherwise and Tie if they are... tied.

Stackexchange API Data Explorer, 184 180 bytes
Thanks to @Kevin Cruijssen for -4 bytes
DECLARE @M int,@D int;SELECT @M=reputation from users where id=8478;SELECT @D=reputation from users where id=12012;IF @D=@M PRINT('tie')ELSE BEGIN;IF @D>@M PRINT(1)ELSE PRINT(2)END

Prints 1 for Dennis and 2 for Martin
Since i only yesterday learned about the SEADE this should be very beatable.
Try it here

You can change 'D' and 'M' to 0 and 1.

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


text:
Download a file from the Internet
Introduction
Yes, it's as simple as that. Download any file from the internet!
Rules
You must use your language's API.
You must output the file you downloaded to STDOUT, the console, a file, etc.
Input should be empty, or the URL you wish to download, but the url must count to byte count..
Good luck!

Bash, 21 17 11 9 7 bytes
curl ai

curl is not a tool that already exists? :)

@AbelTom this is "your language's API"

curl ai no need for http://

could you please explain what curl 3.ly does?

@bolov this uses the command line program curl to download the page at http://3.ly

Why not wget ai?

@SIGSEGV: Because that does not output to stdout.

This doesn't work for me?  What's ai supposed to be? Gives curl: (6) Could not resolve host: ai here.

@Riker It's the ccTLD for Anguilla. curl ai gave me http://209.59.119.34

@martin yea, it only works on some machines.  It's confirmed to work on some linux distros, but not mac and not all windows machines.

Röda, 29 bytes
{saveResource"http://ai","a"}

This is an anonymous function that creates a file a containing the HTML code of http://ai.

Now to convince them to run an FTP server...

How is that url valid?

@IulianOnofrei Why wouldn't it be valid? It has a protocol, a hostname, and no port, path or query string but those are all optional. Are you asking why ai is a valid hostname?

@immibis Isn't the TLD required?

@IulianOnofrei ai is a TLD. Usually TLDs don't resolve to addresses that host websites, but this one apparently does.

@immibis, So ai is the hostname and the TLD at the same time? What do you mean by "this one apparently does"? Do you mean that you can access it in a browser?

Let us continue this discussion in chat.

For those who - like me - the URL does not resolve, you can probably view it by using the IP address directly: 209.59.119.34

Apparently this URL requires a specific DNS server. Which one are you using?

Bash, 45 43 bytes
exec 3<>/dev/tcp/ai/80;echo GET />&3;cat<&3

opens a tcp socket with ai site on file descriptor 3, issues a get, and cats the result.
perhaps can be golfed further.

You can remove the double quotes " around GET /.

Amazing! This is very good, even if it is not the shortest.

MATL, 8 bytes
'v.ht'Xi

The URL provided to Xi (urlread) is prepended with http:// if it isn't already. Additionally the output of urlread contains the contents of the response and this is implicitly printed when the program exits.
Unfortunately this does not work for the online compilers since loading data from an arbitrary URL is disallowed in online-mode, so here's a GIF.

PowerShell, 7 Bytes
Since we're all using www.ai...
irm ai.

uses Invoke-RestMethod - prints the result to StdOut
alternate answer, saves to file named 'a' in run directory, using Invoke-WebRequest and -OutFile param.
iwr ai. -OutF a

I'm going to nitpick that irm won't download any file, as requested in the question, because if the server returns json or xml, it will be turned into a PSObject instead. And irm ai. doesn't work for me - it says name cannot be resolved... I get "$(irm g.cn)" as a suggestion.

good point regarding irm - @John Hathwood - does this still fit the challenge or need to be changed? i'm a little unclear on 'any file' - it outputs a 'parsed' copy of any json or xml, all other files are returned raw.

@TessellatingHeckler what version of PS are you using? do you get anything running nslookup ai. or nslookup www.ai 8.8.8.8?

Aye, it works querying against Google DNS, it's a local Windows DNS server that can't resolve it. OK.  PSv4 as well, but that's not involved, same at a cmd prompt.

@TessellatingHeckler always something simple aha, i'll wait for the challenge author to confirm if the above is ok, but most likely the 15-byte iwr answer will be the correct one.

C#, 96 93 bytes
async()=>Console.Write(await new System.Net.Http.HttpClient().GetStringAsync("http://3.ly"));

Welcome to PPCG!

Thanks! I lurk occasionally but I needed some fun today c:

Mathematica 18 Bytes
URLDownload@"v.ht"

I think FetchURL works

Think you mean URLFetch which requires a Mathematica version before 11.

URLFetch still works in the current version but at some point will probably be fully deprecated, and there did use to be a FetchURL in UtilitiesURLTools
https://reference.wolfram.com/language/ref/URLFetch.html

JS (ES6), 38 36 31 29 bytes
fetch`//ai`.then(x=>x.text())

Depending on the promise consensus, (41 bytes)
fetch`//ai`.then(x=>x.text()).then(alert)

Until we reach a consensus on Promises, I'd say you'll need to alert this.

Do 10 votes a consensus make? (Genuine question that; how many votes do we need for it to considered accaptable?)

Does text return a promise or does ...then(x=>alert(x.text())) work?

@immibis, It returns a Promise, unfortunately.

@programmer5000, shouldn't the first version be a function (+3 bytes) in order to return the promise?

@Shaggy it's acceptable now. The consensus is +5 and 2:1 ratio of up to downvotes.

Do you have a source for that, @Riker?

@Shaggy it used to be in the meta itself, it was accidentally edited out. Martin has confirmed in chat a couple times that's what it is. (iirc the loopholes post is the same)

Excellent. Thanks for the info, @Riker.

PHP, 22 bytes
If allow_url_include=1 is in your ini file:
<?=include"http://ai";

C (Clang, ARMv7-a Linux/Android, AT&T Wireless), 162 bytes
Since we're hardcoding URLs, why not hardcode ISPs?
main(s){int b[500]={5<<28|2,**((int***)gethostbyname("ai"))[4]};connect(s=socket(2,1,0),b,16);write(s,"GET / HTTP/1.0\n\n",16);read(s,b,-1);read(s,b,-1);puts(b);}

I can't show a demo because none of the demos have online enabled :(
This abuses two things. One is that I assume http://ai is smaller than 2000 bytes and just casually read a max of 4GB onto the stack (what could possibly go wrong), and two is that I take advantage of how I discovered that AT&T Wireless converts \n to \r\n in HTTP requests for some reason (new data saving hack?).
Termux screenshot, showing how it works on data (AT&T via Cricket) but not on my Wi-Fi (Xfinity).

Ungolfed and commented:
note: I have removed the punning and buffer reusing for this.
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>

int main(void)
{
    // Look up the IP address of http://ai
    // Note that I mess around with type punning and the documented
    // layout of the structure in the golfed version.
    struct hostent *ent = gethostbyname("ai");
    // Extract the first IP address (already in network order)
    uint32_t ip;
    memcpy(&ip, ent->h_addr_list[0], sizeof(uint32_t));
    // Create the sockaddr struct
    struct sockaddr_in header = (struct sockaddr_in) {
        .sin_family = AF_INET,
        .sin_port = htons(80),
        .sin_addr = { ip }
    };
    // Copy over to the pun
    struct sockaddr_storage header_raw;
    memcpy(&header_raw, &header, sizeof(header));

    // Create an IPv4 socket
    int soc = socket(AF_INET, SOCK_STREAM, 0);
    // Connect the socket to the interwebs
    connect(soc, (const struct sockaddr *)&header_raw, sizeof(header_raw));

    // Send an HTTP GET request
    // Note that because It Works™ on AT&T, I use \n instead of the proper \r\n. Two newlines are still required though.
#ifdef ATT
    const char get_request[] = "GET / HTTP/1.0\n\n";
#else
    const char get_request[] = "GET / HTTP/1.0\r\n\r\n";
#endif
    write(soc, get_request, strlen(get_request));

    char buf[2000] = {0};
    // Note: I use -1 to just read the entire thing. Hopefully it is all shorter than
    // 1999 chars :P
#ifdef BUF_HACK
    size_t len = -1;
#else
    size_t len = sizeof(buf) - 1;
#endif
    // Receive the HTTP response header
    read(soc, buf, len);
    // But ignore it because I don't care about parsing HTTP stuff
    // Just read again for the real data
    read(soc, buf, len);
    // Print to stdout (assuming the HTTP header was shorter)
    puts(buf);
    // I don't actually bother closing the socket in the golfed code, sue me.
#ifndef RESOURCE_HOG
    close(soc);
#endif
}

I just decided to see how painful this was, I knew before I started that it didn't have a chance.

Mathematica, 13 bytes
URLFetch@"ai"

Python 2, 55 49 47 bytes
Not shorter but I really thought I could go further.
from urllib import*
urlopen('http://ai').read

I think from urllib import*\nurlopen('http://g.co').read is a valid submission as the second line is an unnamed function (just like an unnamed lambda function)

You need to remove the trailing brackets. It would be a snippet instead oft an function otherwise

IOError: [Errno socket error] [Errno 8] nodename nor servname provided, or not known

@IulianOnofrei Are you using TIO? Code run in TIO doesn't have access to the internet.

I don't know what TIO is.

Can you access http://ai in a regular browser?

@totallyhuman What is http://ai ? Is this a valid address? I cannot open it in the browser.

It works for me. Might be restricted..?

@totallyhuman nvm. Found this: http://stackoverflow.com/questions/26152106/why-do-these-urls-without-a-tld-resolve-to-a-webpage and I could access it from the phone.

May be helpful: https://codegolf.stackexchange.com/questions/54356/golfing-with-user-agents

R, 24 bytes
readLines('http://g.co')

prints the output to console in the usual R format -- vector of strings, one element per line of the site.

nc -v v.ht 80 < file - 31 bytes
Where file contains:
GET / HTTP/1.1\r\n
Host: v.ht\r\n
\r\n

I profess ignorance about how I should score this. The file is 31 bytes and contains the URL I want, the -v flag value decides if I get the file I want or an error response.

nc ai 80<<<GET\ / works for me for 18B

I saw other people using that but it doesn't resolve on my machine. I might be able to find a more permissive server but this one needs the Host value. I can maybe remove the last two \r\n couplets

Odd, my machine wouldn't resolve ai for curl or wget but does for nc. try ai. (trailing dot), or 3.ly. It's an error page, but that's still within the bounds of the challenge.

Hmm, if the error page is acceptable then I could send a body of just \n. I'll try some more stuff when I get home

Kdb+, 34 15 bytes
KDB+ >= 3.4
 q).Q.hg`http://ai

from here.
KDB+ < 3.4
q)`:http://ai"GET / HTTP/1.0",4#"\n"
"HTTP/1.1 200 OK\r\nDate: Thu, 11 May 2017 21:45:01 GMT\r\nServer: Apache/1.3..

Vim Ex command, 14 bytes
e http://3.ly/

Opens the URL as a new buffer. Netrw seriously suffers from a restrictive URL format.

Racket, 71 bytes
(require net/url)(port->string(get-pure-port(string->url"http://ai")))

Don't see too many Racket answers around here.

J, 33 bytes
Sadly, this only works on the J shell.

load 'web/gethttp'
gethttp 'g.co'

AHK, 31 bytes
URLDownloadToFile,http://g.co,g

There's a built-in so it's not very exciting. Try to fashion, though, the function is fairly long.

Bash + wget, 7 bytes
wget ai

Downloads the page at http://ai

I get "Resolving ai... failed: nodename nor servname provided, or not known." with this, though wget ai. (with a trailing dot) works.

@Kevin Works on my system. Sounds like you're on FreeBSD or macOS.

Yes, macOS Sierra

@Kevin I'm on Linux. Try a VM.

Odd that it wouldn't work on macOS, since it should be the same code (modulo some os-specific compiler flags, which I wouldn't expect to change this) and nslookup, dig, and nc all find it fine. Oh well, not the first difference I've seen, and not worth installing a vm for.

@Kevin I think DNS resolution works slightly differently on BSD systems

w3m ai is probably valid too

@DigitalTrauma What is w2m?

@Mendeleev https://en.wikipedia.org/wiki/W3m

Ruby, 27 + 10 = 37 bytes
puts open('http://ai').read

+10 bytes for -ropen-uri flag (to require open-uri library)

Python + requests, 55 53 50 bytes
from requests import*
print(get('http://ai').text)

-2 bytes by switching URLs
-3 bytes thanks to ovs

Aren't shortened URLs usually disallowed?

Really, that's Python + requests, since requests is (sadly) not in the standard library.

from request import* is 2 bytes shorter

@Shaggy Um... Welp... pretty much every other answer used one rip. But I changed my URL to make it even shorter because apparently http://ai is a valid full URL..

Vim, 2 + 12 = 14 bytes
gf

Expects the URL http://3.ly/ as input. gf opens the current file under the cursor. Thanks to netrw, this works fine for URLs. I found this just now while trying to remember the command to open URLs in your browser (found it, it's gx).

HTML, 24 bytes
<iframe src="http://ai">

This technically fails as it renders the result...

Is that not STDOUT for HTML? 15 bytes: <embed src=//ai

PowerShell, 62 bytes
PowerShell 5
-join[char[]][net.webclient]::new().downloaddata('http://ai.')

66 bytes for more older versions of PowerShell
-join[char[]](new-object net.webclient).downloaddata('http://ai.')

Pyth, 4 + 11 = 15 bytes
jk'z

With URL http://v.ht as input. Takes an URL string as input, downloads the file, and prints its content.
Explanation:
jk'z
   z    Get the input string (URL)
  '     Download the file from the URL, return a list of lines
jk      Join the list on k which is the empty string

Note that we cannot use the function s for concatenating the list because of bytes types issues.
Slightly cheating, 2 + 11 = 13 bytes (it displays the list of the lines in the file instead of a single string for the whole file):
'z

You will need to install Pyth on your machine to test it (the online interpreter does not execute unsafe operations).

Welcome to PPCG! Pretty good, but "the url must count to byte count".

C#, 76 bytes
Console.WriteLine(new System.Net.WebClient().DownloadString("http://3.ly"));

MATLAB, 20 bytes
urlread('http://ai')

Nothing fancy here...

05AB1E, 4 bytes
.w

Beats all other answers. Takes ai as input.

Input should be empty, or the URL you wish to download

@emanresuA It is the URL I wish to download. Also, see my post on Tips for golfing in 05AB1E.

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


text:
Whose rep is tied?
Your challenge is to query the SE API and find out whose rep on PPCG is tied, and output it. If these were all the users on PPCG:
Martin Ender: 10000 rep
Dennis: 10000 rep
xnor: 5000 rep
sp3000: 3000 rep

You should output Martin Ender, Dennis. If these were the only users:
Jon Skeet: 1000000 rep
Martin Ender: 10000 rep
Dennis: 10000 rep
xnor: 5000 rep
sp3000: 3000 rep
Digital Trauma: 2000 rep
Luis Mendo: 2000 rep
Helka Homba: 2000 rep

You should output:
Martin Ender, Dennis
Digital Trauma, Luis Mendo, Helka Homba

Note that you can use different output formats, as long as it is clear whose rep is tied and who they are tied with. Users with <200 rep can be ignored.

Please consider using the Sandbox in the future to get feedback on your challenges before posting them to the main site.

Are we only supposed to get users from PPCG?

@HyperNeutrino yes, only PPCG.

"Users with <200 rep can be ignored." Can be ignored or should be ignored?

When you say we can use different output formats, does that include using something other than their name to identify each user?

JavaScript (ES6), 259 257 248 241 bytes
Returns a Promise object containing \n separated groups, in ascending order of reputation, of profile links for users with the same rep, with each link separated by a comma. As the question only states that users with 200 reputation or less can be ignored (rather than should be ignored), this solution includes a couple of users who do have <200 rep.
f=(x=95,s="",c=0)=>fetch(`//api.stackexchange.com/users?page=${x}&site=codegolf`).then(a=>a.json()).then(j=>(i=j.items.reverse()).map(x=>(r=x.reputation)>c?(c=r,t.length-1&&(s+=t+`
`),t=[x.link]):t.push(x.link),t=[i[0].link])&--p?f(p,s,c):s)

Caveat
Between this challenge, "Martin vs. Dennis" and a couple of others, I've managed to get myself (temporarily) booted from the API for a few hours! I was, therefore, unable to run my final tests on this but it should be working (although, I suspect it might not include users from page 1 in the output). There's probably a bit more I can golf off it, so I'll come back to it when my ban is lifted.

Try it
WARNING: The first Snippet below will submit 95(!) requests to the SE API - running it a couple of times may result in you also having your access to the API temporarily revoked. If you'd prefer to test this with a reduced number of API calls and, therefore, a reduced result set, change the value of the first parameter to something much lower than 95. Alternatively, you can test it with no API calls, using the second batch of sample data from the question by using the second Snippet below, which returns usernames instead of profile links (for now).

f=(x=95,s="",c=0)=>fetch(`//api.stackexchange.com/users?page=${x}&site=codegolf`).then(a=>a.json()).then(j=>(i=j.items.reverse()).map(x=>(r=x.reputation)>c?(c=r,t.length-1&&(s+=t+`
`),t=[x.link]):t.push(x.link),t=[i[0].link])&--p?f(p,s,c):s)
f().then(console.log)

f=(x=95,s="",c=0)=>Promise.resolve(JSON.parse(`{"items":[{"display_name":"John Skeet","reputation":1000000},{"display_name":"Martin Ender","reputation":10000},{"display_name":"Dennis","reputation":10000},{"display_name":"xnor","reputation":5000},{"display_name":"sp3000","reputation":3000},{"display_name":"Digital Trauma","reputation":2000},{"display_name":"Luis Mendo","reputation":2000},{"display_name":"Helka Homba","reputation":2000}]}`)).then(j=>(i=j.items.reverse()).map(y=>(r=y.reputation)>c?(c=r,t.length-1&&(s+=t+`
`),t=[y.display_name]):t.push(y.display_name),t=[i[0].display_name])&--x?f(x,s,c):s)
f().then(console.log)

Drop the the parens on fetch to save 2 bytes

@JohanKarlsson, that won't work due to the ${x} being used to construct the URL.


text:
Expand Kirkman's Schoolgirl Problem
For those of you who are unfamiliar, Kirkman's Schoolgirl Problem goes as follows:

Fifteen young ladies in a school walk out three abreast for seven days in succession: it is required to arrange them daily so that no two shall walk twice abreast.

We could look at this like a nested 3 by 5 list (or matrix):
[[a,b,c]
 [d,e,f]
 [g,h,i]
 [j,k,l]
 [m,n,o]]

Essentially, the goal of the original problem is to figure out 7 different ways to arrange the above matrix so that two letters never share a row more than once. From MathWorld (linked above), we find this solution:
[[a,b,c]   [[a,d,h]   [[a,e,m]   [[a,f,i]   [[a,g,l]   [[a,j,n]   [[a,k,o]
 [d,e,f]    [b,e,k]    [b,h,n]    [b,l,o]    [b,d,j]    [b,i,m]    [b,f,g]
 [g,h,i]    [c,i,o]    [c,g,k]    [c,h,j]    [c,f,m]    [c,e,l]    [c,d,n]
 [j,k,l]    [f,l,n]    [d,i,l]    [d,k,m]    [e,h,o]    [d,o,g]    [e,i,j]
 [m,n,o]]   [g,j,m]]   [f,j,o]]   [e,g,n]]   [i,k,n]]   [f,h,k]]   [h,l,m]]

Now, what if there were a different number of schoolgirls? Could there be an eighth day?† This is our challenge.
†In this case no††, but not necessarily for other array dimensions
††We can easily show this, since a appears in a row with every other letter.

The Challenge:
Given an input of dimensions (rows, than columns) of an array of schoolgirls (i.e. 3 x 5, 4 x 4, or [7,6], [10,10], etc.), output the largest possible set of 'days' that fit the requirements specified above.
Input:
The dimensions for the schoolgirl array (any reasonable input form you wish).
Output:
The largest possible series of arrays fitting the above requirements (any reasonable form).
Test Cases:
Input:  [1,1]
Output: [[a]]

Input:  [1,2]
Output: [[a,b]]

Input:* [2,1]
Output: [[a]
         [b]]

Input:  [2,2]
Output: [[a,b]  [[a,c]  [[a,d]
         [c,d]]  [b,d]]  [b,c]]

Input:  [3,3]
Output: [[a,b,c]  [[a,d,g]  [[a,e,i]  [[a,f,h]
         [d,e,f]   [b,e,h]   [b,f,g]   [b,d,i]
         [g,h,i]]  [c,f,i]]  [c,d,h]]  [c,e,g]]

Input:  [5,3]
Output: [[a,b,c]   [[a,d,h]   [[a,e,m]   [[a,f,i]   [[a,g,l]   [[a,j,n]   [[a,k,o]
         [d,e,f]    [b,e,k]    [b,h,n]    [b,l,o]    [b,d,j]    [b,i,m]    [b,f,g]
         [g,h,i]    [c,i,o]    [c,g,k]    [c,h,j]    [c,f,m]    [c,e,l]    [c,d,n]
         [j,k,l]    [f,l,n]    [d,i,l]    [d,k,m]    [e,h,o]    [d,o,g]    [e,i,j]
         [m,n,o]]   [g,j,m]]   [f,j,o]]   [e,g,n]]   [i,k,n]]   [f,h,k]]   [h,l,m]]

There may be more than one correct answer.

*Thanks to @Frozenfrank for correcting test case 3: if there is only one column, there can only be one day, since row order does not matter.
This is code-golf competition - shortest answer wins.

Does this relate to finite projective planes in any way or am I thinking of a different problem?

@Neil I have no clue. I'm afraid I'm not qualified to answer that. ;-)

Is there a time limit?

@Artyer No, but I would like to be able to test the code...

@Neil that was a fun wikipedia read.

As there are multiple correct answers, can we output any of them?

For test case #3 (or any case with a row width of 1), wouldn't the output be infinite, since it is impossible to violate "no two shall walk twice abreast".

Mathematica, 935 bytes
Inp={5,4};L=Length;T=Table;ST[t_,k_,n_]:=Binomial[n-1,t-1]/Binomial[k-1,t-1];H=ToExpression@Alphabet[];Lo=Inp[[1]]*Inp[[2]];H=H[[;;Lo]];Final={};ST[2,3,12]=4;ST[2,4,20]=5;If[Inp[[2]]==1,Column[Partition[H,{1}]],CA=Lo*Floor@ST[2,Inp[[2]],Lo];While[L@Flatten@Final!=CA,Final={};uu=0;S=Normal[Association[T[ToRules[H[[Z]]==Prime[Z]],{Z,L@H}]]];PA=Union[Sort/@Permutations[H,{Inp[[2]]}]];PT=Partition[H,Inp[[2]]];While[L@PA!=0,AppendTo[Final,PT];Test=Flatten@T[Times@@@Subsets[PT[[X]],{2}]/.S,{X, L@PT}];POK=T[Times@@@Subsets[PA[[Y]],{2}]/.S,{Y,L@PA}];Fin=Select[POK,L@Intersection[Test,#]==0&];Facfin=T[FactorInteger[Fin[[V]]],{V,L@Fin}];end=T[Union@Flatten@T[First/@#[[W]],{W,L@#}]&[Facfin[[F]]],{F,L@Facfin}]/.Map[Reverse,S];PA=end;PT=DeleteDuplicates[RandomSample@end,Intersection@##=!={}&];If[L@Flatten@PT<L@H,While[uu<1000,PT=DeleteDuplicates[RandomSample@end,Intersection@##=!={}&];If[L@Flatten@PT==L@H,Break[],uu++]]]]];Grid@Final]

this is for 26 ladies max
EDIT
I made some changes and I think it works!
The code right now is set to solve [5,4] (which is the "social golfers problem") and gets the result in a few seconds.
However [5,3] problem is tougher and you will have to wait 10-20 minutes but you will get a right combination for all days.
For easier cases it is very quick.
anyway you can try it and see the results
Try it online here
copy and paste using ctrl-v
press shift+enter to run the code
you can change the input at the begining of the code -> Inp={5,4}
run the code multiple times to get different permutations

While this is impressive, and makes a lot of progress towards solving the problem, it is still incomplete. While it works for smaller test cases, it couldn't solve any larger ones, including the [5,3] test case this whole problem is based off of. In addition, this can be golfed more; there are several variable names that are larger than they need to be, and some functions can be shortened with @ or infix notation. I hope you'll keep working, though!

thanks for checking it. I'll try to make this work first and then golf it...

@Scott Milner I made some improvements and it works much better.

You should be able to save a lot of bytes by making your variable names single letters, and assigning some functions you use more than once to variables and replacing the functions with those variables :)

The input [2,1] gives a divide by zero error.

@numbermaniac By just replacing variable names, I was able to get it down to 914. It should be golfable down to around 850.

I fixed the test case. First of all I want this to work. Thats why I haven't golfed it yet.Thanks for all your comments. I think now it is ready.

Jelly, 19 bytes
×Œ!s€ɗœcⱮ×ẎẎṢ€QƑƊƇṪ

Try it online!
The Footer simply formats the input and output and demonstrates for various inputs. Assumes that it's ok to return any valid configuration, rather than the one stated in the question.
This is a brute force approach and isn't efficient by any meaning of the word. If we call the dimensions \$n\$ and \$m\$ (\$n\$ being height), this generates
$$f(n, m) = \sum^{nm}_{i=1} \binom {(nm)!} {i}$$
lists to check. For example, for \$n = 3, m = 5\$, we generate
$$42755752626996476442177192901690329126386272975917980316235035492211700060653916251199050827754168292191219682093923414635027126605138973495697914193291687743693535776000$$
lists to check. Unsurprisingly, this times out on TIO for basically all inputs. Those for which it doesn't time out are shown in the TIO link.
How it works
×Œ!s€ɗœcⱮ×ẎẎṢ€QƑƊƇṪ - Main link. Takes n on the left and m on the right
     ɗ              - Group the previous 3 links into a dyad f(n, m):
×                   -   Yield n×m
 Œ!                 -   Promote n×m into a range [1, 2, ..., n×m] and yield
                         all permutations of that range
    €               -   Over each permutation:
   s                -     Split it into an n×m matrix
         ×          - Yield n×m
        Ɱ           - For each integer 1 ≤ i ≤ n×m:
      œc            -   Yield all combinations (without replacement) of the
                         permutations of length i
          Ẏ         - Tighten these into a single list of lists of matrices
                ƊƇ  - Keep those for which the following is true:
              QƑ    -   The matrix has no duplicates when:
           Ẏ        -     Tightened into a list of lists
            Ṣ€      -     And each list is sorted
                  Ṫ - Get the last (i.e. the longest) such list


text:
Calculate gravity on a 1D field
Given a string or list, calculate the effects of gravity on that string/list.
The string will be made of 5 characters:

N has a weight of 2
L has a weight of 1
S has a weight of -2
D has a weight of -1

(the 5th character is whatever you want, it means empty space. I use  (space) in my examples)
Items with negative weight fall upwards (towards the top of the string), and items with positive weight fall downwards (towards the bottom of the string).
When an object collides with something, one of three things happens:

If the object collides with the top or bottom "walls" of the input, then it just stops.
If the object collides with another object, their weight/velocity is summed (i.e. N and D would give 1). If the result is positive, both objects fall downwards. If it's negative, they fall upwards.
If an object  (let's call it A) collides with an object B, and B is already pinned against the ceiling/floor, A will just come to rest against B.

All non-occupied spaces of the string/list should be filled with the empty character.
If it wasn't clear already: each character in the string/line is on top of the next one.  i.e. NL is the same as:
N
L

And  SD is:
(blank)
S
D

Test cases: (uses  (the space character) to show empty space)
" L D " -> " LD  " or "  LD "

" SDLN " -> "SD  LN"

" NLLSSD " -> "NLLSSD  "

"Given a delimited string or list." Can also use a string without delimiters? Since all items are just individual characters that shouldn't be a problem, right? And what's the expected outcome for N0S or L0D?

@MartinEnder About the delimited string, that was left over form a previous version of the question. It has been edited out. And I added a test case to address the second issue. If it is still unclear, please let me know.

Why the NUL character?

Should've specified a directional order-of-operations.

Side note: if "physics" is to be accounted for, letters with negative weights should probably fall downwards just like the rest.

Would ␣␣NSDLLD␣␣ become NSD␣␣␣␣LLD?

@zgrep Yes, it would.

Do things such as -2 and 2 fall/rise faster than -1 and 1?

@zgrep Everything falls/rises at the same rate.

Haskell, 169 180 bytes
g s=sum[n|c<-s,(d,n)<-zip"SD LN"[-2..],c==d]
w=elem ' '
h(x:y:r)|(w x&&g y<0)||(w y&&g x>0)=y:h(x:r)|w(x++y)||g x<0=x:h(y:r)|t<-x++y=h$t:r
h r=r
concat.until((==)=<<h)h.map(:[])

Try it online!
 Example usage: concat.until((==)=<<h)h.map(:[]) $ " SDLN ".
Edit: +11 bytes, now also works for the "  NSDLLD  " test case proposed by @zgrep.
(short) Explanation:
h works on a list of tokens where initially each char of the input string is token. Until the token list no longer changes, h bubbles through the list comparing two tokens x and y at a time. Depending on the tokens their order is kept (x:h(y:r)), they are swapped (y:h(x:r)) or combined to a single token (t<-x++y=h$t:r).
g computes the weight of a token and w checks whether a token contains a space.

OCaml, 379 bytes
let rec n f a i=try n f(f a i)(i+1)with _->a
let r s=String.(concat""(let rec w s=if ' '=s.[0]then`E else(function
0->`F|w when w<0->`L|_->`H)(n(fun a i->index"SD LN"s.[i]-2+a)0 0)and l=function
a::b::t->(function`E,`L|`H,`E->l(b::a::t)|_,`L|`H,_|`F,`F|`E,`E->l((a^b)::t)|_->let
c=a::l(b::t)in if b=List.nth c 1 then c else l c)(w a,w b)|x->x in l(n(fun a
i->a@[sub s i 1])[]0)))

To test:
let () =
    List.iter (fun s -> Printf.printf "`%s`\n" (r s)) [
        "   S S   S S   ";
        "   D D   D D   ";
        "               ";
        "   L L   L L   ";
        "   N N   N N   ";
        "NL";
        " SD";
        " L D ";
        " SDLN ";
        " NLLSSD ";
    ]

Python 2, 322 bytes
Try it online
import re
S=input()
C=str.count
D=''
while S!=D:
 D=S
 for i in[(i.group(),i.span())for i in re.finditer('\w+',S)]:
    s=i[0];g=C(s,'N')*2+C(s,'L')-C(s,'S')*2-C(s,'D');l=g<0;b=g>0;c=(1,-1)[b]
    if g:S=S[:i[1][0]-1]*l+re.sub('^ '*l+i[0]+' $'*b,''.join([i[0],' '][::c]),[S[i[1][0]-1:],S[:i[1][1]+1]][b])+S[i[1][1]+1:]*b
print S


text:
Decode the Void
A void list is a list that at no level contains any non-list objects.  Or if you prefer a recursive definition

The empty list is void
A list containing only other void lists is void

All void lists have a finite depth.
Here are some examples of void lists (using python syntax):
[]
[[]]
[[],[]]
[[[]]]
[[[]],[]]
[[],[[]]]

Here are some examples of things that are not void lists:
["a"]
[[...]]
[1]
2
[[],([],[])]

Task
Write two separate functions (or programs if you prefer).  One should take a positive integer (you may also include zero if you wish) as an argument and return a void list the other should take a void list and return it an integer.  These two functions should always be inverses of each other.  That is if you pass the output of f into g you should get the original input of f as the result of g. This means the mapping must be 1:1, i.e. for every integer, there may only exist exactly one void list for which g gives that integer and for every void list there should be exactly one integer for which f gives that void list.
You are essentially creating a Bijection
You may choose to use a string representation of a void list (with or without commas and spaces) instead of your languages native list type.
Scoring
Your score will be the lengths of your two functions together.  This is code-golf so you should aim to minimize this sum.

very related: https://codegolf.stackexchange.com/questions/94540/build-a-nest/94667#94667

Somewhat related.

Can the coder and decoder share code? Can we use natural numbers including zero?

@ChristianSievers The two should not share any code.

This question asks for two functions whereas the duplicate only asks for the first half.

Rats. I nearly posted the best answer I had written yet, and it doesn't qualify for the other challenge.

@IanMiller I would to say that the other challenge has different guidelines for encoding then this one does.

Perhaps it would make more sense for this question to be just the decoder? Because there's already a question about the encoder.

@ais523 That might be a good idea, but at this point it is too late, I don't want to pull the rug out from underneath anyone

Could possibly tag the challenge [tag:set-partitions]?

Pyth, 27 + 29 = 56 bytes
f:
L?bol`NS{sm[d+d]Y]d)ytb]Y@y

Test suite
g:
L?bol`NS{sm[d+d]Y]d)ytb]Yxyl`

Test suite
The system is very simple: I generate all possible lists with no more than a certain number of ['s. Then, I sort them in such a way that the lists I haven't generated yet would be near the end. This is all done by the function y, identical in both programs. It is written as
L?bol`NS{sm[d+d]Y]d)ytb]Y

Then, I index into this list for f, and search through it for g.
The number of lists I generate is chosen to be large enough that I have generated all possible lists which would appear at or before the desired location in the infinite sorted list.
The programs allow/return 0 as an option.

Python 2, 96 bytes
Try it online! to test the bijection.
f=lambda l:len(l)and f(l[0])*2+1<<f(l[1:])

Takes void lists to non-negative integers. 42 bytes.
g=lambda n:n*[g]and[g(n/(n&-n)/2)]+g(len(bin(n&-n))-3)

Takes non-negative integers to void lists. 54 bytes. A more recursive attempt gave the same length.
g=lambda n,i=0:n*[g]and[g(n/2,i+1),[g(n/2)]+g(i)][n%2]

Java 7, 725 bytes
f(int) (325 bytes):
String f(int i){String s="";for(int j=0,e=0;e<i;e+=v(s))s=Integer.toBinaryString(j++);return"["+s.replace("1","[").replace("0","]")+"]";}int v(String s){for(;!s.isEmpty();s=s.replaceFirst("1","").replaceFirst("0",""))if(s.replace("1","").length()!=s.replace("0","").length()|s.charAt(0)<49|s.endsWith("1"))return 0;return 1;}

g(String) (75 + 325 bytes):
int g(String s){int r=0;for(String i="10";!i.equals(s);i=f(++r));return r;}

Since method g uses method f to calculate it's result by looping over possible void-list until it founds the one equal to the one inputted, the bytes of f are counted twice (since both methods should be able to run without the other for this challenge).
Explanation:
In general, method f simply loops over all binary String-representations of integers, and increase a counter every time a valid one is found. Valid binary-Strings for this challenge comply to the following rules: They start with a 1, and end with a 0; they have an equal number of 1s and 0s; and every time you remove the first 1 and 0 and validate what is left again, these two rules still apply. After the counter equals the input, it converts that binary-String to a String void-list, by replacing all 1 with [ and all 0 with ].
As for method g: We start with "[]" (representing void-list 0), and then continue using method f while increasing an integer, until it matches the input-String.
String f(int i){         // Method `f` with integer parameter and String return-type
  String s="";           //  Start with an empty String
  for(int j=0,e=0;e<i;   //  Loop as long as `e` does not equal the input
      e+=v(s))           //    And append increase integer `e` if String `s` is valid
    s=Integer.toBinaryString(j++);
                         //   Change `s` to the next byte-String of integer `j`
                         //  End of loop (implicit / single-line body)
  return"["+             //  Return the result String encapsulated in "[" and "]"
    s.replace("1","[").replace("0","]")+"]";
                         //  after we've replaced all 1s with "[" and all 0s with "]"
}                        // End of method `f`

int v(String s){         // Separate method with String parameter and integer return-type
  for(;!s.isEmpty();     //  Loop as long as String `s` isn't empty
      s=s.replaceFirst("1","").replaceFirst("0",""))
                         //    After each iteration: Remove the first "1" and "0"
    if(s.replace("1","").length()!=s.replace("0","").length()
                         //   If there isn't an equal amount of 1s and 0s
       |s.charAt(0)<49   //   or the String doesn't start with a 1
       |s.endsWith("1")) //   or the String doesn't end with a 0
      return 0;          //    Return 0 (String is not valid)
                         //  End of loop (implicit / single-line body)
  return 1;              //  Return 1 (String is valid)
}                        // End of separate method

int g(String s){         // Method `g` with String parameter and integer return-type
  int r=0;               // Result integer
  for(String i="[]";!i.equals(s);
                         //  Loop as long as `i` does not equal the input String
      i=f(++r));         //   After each iteration: Set `i` to the next String in line
  return r;              //  Return the result integer
}                        // End of method `g`

Example input & output cases:
Try it here. (NOTE: It's pretty slow for the last few test cases. Will take around 10-15 sec for all of them.)
0   <-> []
1   <-> [[]]
2   <-> [[][]]
3   <-> [[[]]]
4   <-> [[][][]]
5   <-> [[][[]]]
6   <-> [[[]][]]
7   <-> [[[][]]]
8   <-> [[[[]]]]
9   <-> [[][][][]]
10  <-> [[][][[]]]
11  <-> [[][[]][]]
12  <-> [[][[][]]]
13  <-> [[][[[]]]]
14  <-> [[[]][][]]
50  <-> [[[][[[]]]]]
383 <-> [[[][]][[[][]]]]

I don't think that [][] is a list.  Perhaps I am misunderstanding the way Java does its whatever.  Adding [...] around all of them and having 0 map to [] should do the trick.

@WheatWizard Ah, good call. Will try to fix this. I didn't had enough bytes yet anyway. ;P

@WheatWizard Ok, it should be fixed now. Tough but fun challenge btw. It took a while before I understand what you meant, and even longer to write this answer, but it was fun. :)

K (ngn/k), 49 bytes
{$[#x;2/,/1,'&:'o'x;0]}
{$[x;o'|-1+-1-':&|2\x;()]}

Try it online!
uses the formula from the example in Bijection: tree-like lists - natural numbers

JavaScript (Node.js), 82 bytes
f=(n,i)=>n?n&1<<i?[f(i),...f(n>>-~i)]:f(n,-~i):[]
g=([a,...b])=>a?g(b)*2+1<<g(a):0

Try it online!
xnor's idea

Python 3 - sign/abs, 73 bytes
f=lambda n:[[[]]*(n<0),[[]]*abs(n)]
g=lambda l:[-1,1][not l[0]]*len(l[1])

Try it online!
Straight forward implementation, supports negative numbers.
Integer i is encoded [sign(i), abs(i)], where sign(i)=[] if i > 0 else [[]] and abs(i)=[[]] * i, i.e.  a list of empty lists with length abs(i).
Python 3 - binary, 126 bytes
This is a more elaborate version (and a lot longer...), where the absolute value is encoded in a binary list representation.
f=lambda n:[[[]]*(n<0),[[[]]*int(i)for i in f"{n:+b}"[1:]]]
g=lambda l:[-1,1][not l[0]]*int(''.join(map(str,map(len,l[1]))),2)

Try it online!

Doesn't work for more complex void lists: Try it online!

Ah, I somehow missed, that there should be a mapping for every void list... you're right.

Stax, 33 total bytes
These programs are inverses of each other.  They convert to and from all void lists and all non-negative integers, so that includes 0.  This seems like it's maybe a famous function from some kind of algebra I don't know.  In order to wrap my head around it, I first implemented the programs as functions in python.
def convert_to_void(n):
    lst = []
    while n > 0:
        n -= 1
        choices = len(lst) + 1
        choice = n % choices
        cutpoint = len(lst) - choice
        n //= choices
        newgroup = lst[cutpoint:]
        del lst[cutpoint:]
        lst.append(newgroup)
    return lst

def convert_from_void(lst):
    n = 0
    while lst != []:
        newgroup = lst.pop()
        n *= len(lst) + len(newgroup) + 1
        n += len(newgroup) + 1
        lst.extend(newgroup)
    return n

The stax programs have the same behavior.
Non-negative integer → Void list, 15 bytes
ƒâ₧~└3BI─¿-rÅ;ì

Run and debug it
Void list → Non-negative integer, 18 bytes
Çäê[!σ`c↑Ö§░NR╥ç=Æ

Run and debug it