text:
The Extreme Voters
Challenge
Output the person on PPCG who has cast the most upvotes and the person who has cast the most downvotes.
Voters
You should only look at the people who have cast more than 1000 votes in total.
To find the person who upvotes the most, you should the find the person with the highest upvotes/total votes value. Similarly, the person who downvotes the most has the highest downvotes/total votes value.
Rules
Your output should be the two users' id (the number found in the URL of the user's page). You must put the upvoter first.
In the case of a tie, you must choose the user whose id is the lowest.
The Stack Exchange API is allowed, but entries in T-SQL using the Stack Exchange Data Explorer are disallowed.
Winning
The shortest code in bytes wins.

Easy: Conor O'Brien and Geobits, respectively. Where's my prize? :P

You should specify that submissions have to access the SE API (and only the SE API)

Votes cast seem to be private to the user only.

Individual votes are private, but vote counts aren't. They're on the user profile.

@Mego Contrary to popular belief... ;) http://data.stackexchange.com/codegolf/query/466199/top-downvoters

@Mego Also contrary to popular belief... ;) http://data.stackexchange.com/codegolf/query/536416/top-upvoters

@ETHproductions makes me where wonder how bad the post had to be that alephalpha cast their only ever downvote on it. :D

@MartinEnder I accidentally downvoted a post once and realized after the grace period :D

So http://codegolf.stackexchange.com/users is also off limits?

@Dennis Uhh no, I shouldn't have limited the question to the API only

Am I allowed to use http://data.stackexchange.com/codegolf/csv/678543 so that I don't have to register for the API?

Kind of scary that I'm 23rd in downvotes but not even near top 100 upvotes. I guess I'm just that evil

Java, 1106 bytes
import java.io.*;import java.util.regex.*;()->{String u="",y="",z="",s,t;float h=0,a,l=0,d;int i=-1,k=-1;Matcher m;Pattern p=null;while(i<=k){try(BufferedReader g=new BufferedReader(new InputStreamReader(new java.net.URL("https://codegolf.stackexchange.com/users"+(k==-1?"?tab=NewUsers&sort=creationdate":"/"+i+"/?tab=topactivity")).openStream()));){while((s=g.readLine())!=null){Integer v=0;if(k==-1&s.contains("users/")&!s.contains("profile-me")){m=p.compile("(?<=users/)(\\d+)").matcher(s);if(m.find()){k=v.parseInt(m.group());break;}}if(s.contains("User")){m=p.compile("(?<=User )(.*)(?= - P)").matcher(s);if(m.find())u=m.group();}if(s.contains("Cast")){m=p.compile("(?<=\\>\\().*(?=\\)\\<)").matcher(s);if(m.find()&&(v=v.parseInt(m.group().replace(",","")))>1000){while(1>0){s=g.readLine();m=p.compile("(\\d*,?\\d+)(?=\\<.*\\>)").matcher(s);if(m.find()){if((t=g.readLine()).contains("up")&&(a=0f+v.parseInt(m.group().replace(",",""))/v)>h){y=""+u;h=a;}if(t.contains("down")){if((d=0f+v.parseInt(m.group().replace(",",""))/v)>l){z=""+u;l=d;}break;}}}}}}}catch(Exception e){}}System.out.print(y+"\n"+z);}

As a full class:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.*;

public class C {
    public static void main(String[] args) throws Exception {
        String u="", y="", z="", s, t;
        float h = 0, a, l = 0, d;
        int i = -1, k = -1;
        Matcher m;
        Pattern p = null;
        while (i < k) {
            // System.out.println(i);
            try (BufferedReader br = new BufferedReader(new InputStreamReader(new URL("https://codegolf.stackexchange.com/users" + (k == -1 ? "?tab=NewUsers&sort=creationdate" : "/" + i + "/?tab=topactivity")).openStream()));) {
                while ((s = br.readLine()) != null) {
                    Integer v = 0;
                    if (k == -1 && s.contains("users/") && !s.contains("profile-me")) {
                        m = p.compile("(?<=users/)(\\d+)").matcher(s);
                        if (m.find()) {
                            k = v.parseInt(m.group());
                            break;
                        }
                    }
                    if (s.contains("User")) {
                        m = p.compile("(?<=User )(.*)(?= - P)").matcher(s);
                        if (m.find())
                            u = m.group();
                    }
                    if (s.contains("Cast")) {
                        m = p.compile("(?<=\\>\\().*(?=\\)\\<)").matcher(s);
                        if (m.find() && (v = v.parseInt(m.group().replace(",",""))) > 1000) {
                            while (true) {
                                s = br.readLine();
                                m = p.compile("(\\d*,?\\d+)(?=\\<.*\\>)").matcher(s);
                                if (m.find()) {
                                    if ((t = br.readLine()).contains("up") && (a = 0f + v.parseInt(m.group().replace(",",""))/v)>h) {
                                        y = ""+u;
                                        h = a;
                                    }
                                    if (t.contains("down")) {
                                        if ((d=0f + v.parseInt(m.group().replace(",",""))/v)>l) {
                                            z = ""+u;
                                            l = d;
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {}
        }
        System.out.print(y+"\n"+z);
    }
}

One word: Damn.
I mean, I've always wanted to do a challenge like this, but boy was it a doozy.
I didn't use the Stack Exchange API (don't know what it is, where to access it, or how to use it :P), so I basically had to do everything on my own; having the program crawl through each of the nearly 60,000 PPCG users' profile pages for the right data, looking up the HTML scripts and accounting for how the vote totals were laid out differently for different users1, and debugging (which was, perhaps unsurprisingly, a huge pain). And let me just say, this code could probably use some serious optimization. It takes well over two hours for the program to finish running on my machine, though most of the time is probably used opening the connections to the sites.
So here's a quick rundown of how it works:

Create String variables to hold the upvotingest and downvotingest users on PPCG.
Figure out the total number of active (and deleted/nonexistent) user accounts there are on the site. The program visits https://codegolf.stackexchange.com/users?tab=NewUsers&sort=creationdate and looks for the first user on the page, who happens to be the most recent addition to the community, and as such has the highest ID number. This ID number is set to be the total number of iterations for the loop.
Start at ID 1 and visit https://codegolf.stackexchange.com/users/#, where the pound symbol represents the ID. Parse the HTML code (with regex͠,̰ nőͣ l͇̪e̐̃s̸͖̚͜͝s̡͍̲̫̋ͯ
) and collect the user's username, vote total, upvote total, and downvote total.
Check to see if the upvotes to total votes ratio is larger than the current largest ratio, and set the current ratio to the new ratio if necessary. Do the same for the downvotes to total votes ratio, and also set the upvotingest and downvotingest user names when needed.
Do steps 3 and 4 another (near) 60,000 times, incrementing the ID each time. (This takes care of the event when there is a tie.) If the user doesn't exist, either nothing matches or an Exception is thrown, and move on.
Print the upvotingest and downvotingest users.

Yes, there are quite a few places where I can shave off a few bytes (especially on the strings where I use the contains method), but I'll save that for later... maybe.
If you decide to run this program, be prepared to wait a couple hours for it to finish execution.
Here's a screenshot of the output:

In case it's difficult to read, at the bottom it says...
gnat
Peter Taylor

...and the total time it took for the program to finish: a whopping two hours, forty-eight minutes, and twenty-three seconds!

1 The instance on which this occurred had to do with how recently the user voted. If the user voted at least once within the past week or month, two(?) additional stats showing how many times they voted over the past week or month appear on their activity page.

+1 This is a great solution. You can save yourself some bytes because the questiom asked for the user's id instead of their name :)


text:
Esolang-Comment-Template-Generator
Lots of people on this site use esoteric languages, and since these languages are unusual and hard to understand, they will frequently write an explanation in a certain format. For example, if the code was
abcdefghijklmnop

And this languages uses # for comments, they would write an explanation like this:
a                #Explanation of what 'a' does
 bc              #Bc
   d             #d
    e            #Explanation of e
     fgh         #foobar
        ij       #hello world
          k      #etc.
           l     #so on
            mn   #and
              op #so forth

I frequently do this too, but every time I do this, I feel like creating the layout of text is really obnoxious and time-consuming. So I want you to create a "Esolang-Comment-Template-Generator" for me. For example, if we ignore the comments, the previous code has this template:
a                #
 bc              #
   d             #
    e            #
     fgh         #
        ij       #
          k      #
           l     #
            mn   #
              op #

The Challenge:
You must write a program or function that takes two strings as input, and outputs this "Esolang-Comment-Template". The first input will be the code, but with bars (|) inserted where the newlines go. The second input is what we will use for comments. So our last example would have this for input:
"a|bc|d|e|fgh|ij|k|l|mn|op", "#"

Unfortunately this excludes bars from being part of the code input, but that's OK. You can assume that the comment input will be a single character. For simplicity's sake, the comment char will not be a bar. The code input will only contain printable ASCII, and it will not contain any newlines.
Hopefully you can infer what to do from the testcases, but I'll try to clarify some things.
You must split the code input up into "code-sections" on every bar. Then, each section of code is output on its own line and left-padded with the length of all the previous code (not including the bars). Then, each line is right-padded with enough spaces so that the last two characters on every line are "One additional space" + "The comment character".
One trailing newline is allowed.
Here is another example. For the input
"Hello|World", "/"

The first section of code is "Hello" and the second is "World". So it should give the output:
Hello      /
     World /

Here are some more samples:
Input:
"a|b|c|d|e|f|g", ","

Output:
a       ,
 b      ,
  c     ,
   d    ,
    e   ,
     f  ,
      g ,

Input:
"abcdefg", ":"

Output:
abcdefg :

Input:
"4|8|15|16|23|42", "%"

Output:
4          %
 8         %
  15       %
    16     %
      23   %
        42 %

Input:
"E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last!", "!"

Output:
E                                                   !
 ac                                                 !
   h s                                              !
      ecti                                          !
          on is                                     !
                one c                               !
                     haracte                        !
                            r longer                !
                                     than the       !
                                              last! !

Input:
"This|Code|has||empty||sections", "@"

Output:
This                     @
    Code                 @
        has              @
                         @
           empty         @
                         @
                sections @

Rules:
You may take these inputs and outputs in any reasonable format. For example, reading/writing a file, STDIN/STOUT, function arguments/return value, etc. As usual, this is code-golf, so try to make your code as short as possible and you win if you can get the shortest solution in your language! I will also select the shortest solution as the overall winner. Standard loopholes are banned.

Related

Are trailing blanks allowed?

Next step : a 3D representation for 2D languages

A bonus if you manage to do it without using the | character would be nice, so you can explain yourself

Can the comment character be a bar (|) ?

Pyth - 28 27 24 23 bytes
Might be able to golf a little off. A lot off, apparently!
jt+R+;zC.t.u+*lNdYcQ\|k

Try it online here.

Java 11, 189 159 136 bytes
s->c->{int p=0;for(var a:s.split("\\|"))System.out.println(" ".repeat(p)+a+" ".repeat(s.replace("|","").length()-(p+=a.length())+1)+c);}

-30 bytes converting Java 7 to Java 10 and optimizing the loops.
-23 bytes converting Java 10 to Java 11, so String#repeat builtin can be used.
Try it online.
Explanation:
s->c->{                     // Method with String & char parameters and no return-type
  int p=0;                  //  Position-integer, starting at 0
  for(var a:s.split("\\|")) //  Loop over the parts split by "|":
    System.out.println(     //   Print with trailing newline:
      " ".repeat(p)         //    `p` amount of spaces
      +a                    //    plus the current part
      " ".repeat(s.replace("|","").length()-(p+=a.length())+1)
                            //    plus the correct trailing amount of spaces
                            //    (and add the length of the current part to `p` at the
                            //    same time)
      +c);}                 //    plus the current comment character

Retina, 35 34 bytes
Byte count assumes ISO 8859-1 encoding.
\|
·$'¶$`±
T0-2`·±|p`___ `.+±.|·.+

The two input strings are separated by a space (which is unambiguous since we know that the comment delimiter is always a single character).
Try it online!

Why do you need a space to delimit the strings? Since it is a single character, it could just be the last one.

@Adám I'm reusing it as the space separator in the final output.

Pyke, 31 28 24 bytes
\|cDslF2l-hd*Q+Zi:il?+ZK

Try it here!

JavaScript (ES6), 92 bytes

f=
(s,c)=>s.split`|`.map((_,i,a)=>a.map((e,j)=>i-j?e.replace(/./g,` `):e).join``+` `+c).join`
`
;

<input id=s placeholder=Code><input id=c size=1 maxlength=1 value=#>

Python 2, 107 105 102 99 bytes
Tested with all test cases above
EDIT Golfed off 2 bytes by changing d=a.split("|");i=0 to d,i=a.split("|"),0
Not sure how I missed that one. Thanks @Oliver Ni
Another 3 bytes gone. Thanks again.
Suggestion from @Jonathan actually saves 3 bytes and takes it down to the magic 99. Thanks.
def c(a,b):
 d,i=a.split("|"),0
 for e in d:j=i+len(e);print" "*i+e+" "*(len("".join(d))-j+1)+b;i=j

Golfed it down 6 bytes

Golfed it down another byte

Hey @OliverNi , providing tips for golfing stuff down is appreciated, but editing code isn't really appropriate on this site (source), so I've rolled back your edit. Feel free to post those tips as a comment though! I'm sure the OP would appreciate it, but it should be up to them to test it and choose if they want to use it.

Thanks to both of you. Firstly to @Oliver for taking the interest and the time to improve my humble effort and secondly to DJMcMayhem for clarifying what I believed to be the case but had not had a chance to comment on. Oliver - thanks again and please feel free to post changes as comments so that I can learn from your golfing experience.

You can remove the parenthesis around " "*i to ave 2 bytes

Also, change len("".join(d))-(i+len(e)-1) to len("".join(d))-i-len(e)+1 to save another two bytes

You can also set a variable to len(e) like for e in d:z=len(e).... to save a byte because it is used twice

Tips 1 and 3 worked but 2 seemed to mess up the formatting of the comment characters (not in a vertical line). Maybe I am missing something?

Hmm... I tworks for me

It's just the distributive property

Take it down to a nice round 100 with this as your for loop: for e in d:j=i+len(e);print" "*i+e+" "*(len("".join(d))-j+1)+b;i=j

GNU sed (85 + 1 for -r) 86
:s;h;:;s,\|( *)[^ \|](.),|\1 \2,;t;s,\|,,g
p;g;:l;s,^( *)[^ \|],\1 ,;tl;s,\|,,;/\S/bs

The inputs are strings separated by a space.
Tests:
input.txt:
a|b|c|d|e|f|g ,
abcdefg :
4|8|15|16|23|42 %
E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last! !
This|Code|has||empty||sections @

Output:
$ cat input.txt | sed -rf template
a       ,
 b      ,
  c     ,
   d    ,
    e   ,
     f  ,
      g ,

abcdefg :

4          %
 8         %
  15       %
    16     %
      23   %
        42 %

E                                                   !
 ac                                                 !
   h s                                              !
      ecti                                          !
          on is                                     !
                one c                               !
                     haracte                        !
                            r longer                !
                                     than the       !
                                              last! !

This                     @
    Code                 @
        has              @
                         @
           empty         @
                         @
                sections @

The nameless label : is a GNU sed feature/bug and \S is I think an extension, so maybe the title should be GNU sed. Other than that, great code.

@seshoumara Thanks!

Python 2, 125 124 132 bytes
-1 byte thanks to @TuukkaX (missed golfing the space from i, v)
def g(s,c):x=s.split('|');print((' '+c+'\n').join(' '*len(''.join(x[:i]))+v+' '*len(''.join(x[i+1:]))for i,v in enumerate(x))+' '+c)

All test cases on ideone

Your supposed to use c as the comment char, not #.

@OliverNi - uh that was a hit for the code in its current form.

@Makonede Looks like nobody got the reference

Haskell, 139 135 bytes
s#p=j$foldl g("",0)s where g(a,n)c|c=='|'=(j(a,n)++"\n"++q n,n)|1>0=(a++[c],n+1);q m=' '<$[1..m];j(a,n)=a++q(sum[1|c<-s,c/='|']-n+1)++p

Saved 4 bytes by inlining a definition.
Ungolfed:
template :: String -> String -> String
template code comment = format $ foldl g ("", 0) code
    where g (acc, n) c
            | c == '|' = (format (acc, n) ++ "\n" ++ spaces n, n)
            | otherwise = (acc ++ [c], n+1)
          l = length $ filter (/= '|') code
          spaces n = replicate n ' '
          format (acc, n) = acc ++ spaces (l-n+1) ++ comment

Groovy, 120 113 111 Bytes
def m(s,c){s.split(/\|/).inject(0,{e,t->println((' '*e+t).padRight(s.replace('|','').size()+1)+c);e+t.size()})}

ungolfed*
def m(s,c){
  s.split(/\|/).inject(0, { e, t ->
    println((' '*e+t).padRight(s.replace('|','').size())+' '+c)
    e+t.size()
  })
}

(First Draft with 120 Bytes)
def m(s,c){def l=0;s.split(/\|/).collect{l+=it.size();it.padLeft(l).padRight(s.replace('|','').size())+' '+c}.join('\n')}

ungolfed*
def m(s,c){
  def l=0 // minimized version needs a semicolon here
  s.split(/\|/).collect{
    l+=it.size() // minimized version needs a semicolon here
    it.padLeft(l).padRight(s.replace('|','').size())+' '+c
  }.join('\n')
}

Tests
%> m('a|bc|d|e|fgh|ij|k|l|mn|op', '#')
a                #
 bc              #
   d             #
    e            #
     fgh         #
        ij       #
          k      #
           l     #
            mn   #
              op #

%> m('Hello|World', '/')
Hello      /
     World /

%> m('a|b|c|d|e|f|g', ',')
a       ,
 b      ,
  c     ,
   d    ,
    e   ,
     f  ,
      g ,

%> m('abcdefg', ':')
abcdefg :

%> m('4|8|15|16|23|42', '%')
4          %
 8         %
  15       %
    16     %
      23   %
        42 %

%> m('E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last!', '!')
E                                                   !
 ac                                                 !
   h s                                              !
      ecti                                          !
          on is                                     !
                one c                               !
                     haracte                        !
                            r longer                !
                                     than the       !
                                              last! !

%> m('This|Code|has||empty||sections', '@')
This                     @
    Code                 @
        has              @
                         @
           empty         @
                         @
                sections @

How about .padRight(s.replace('|','').size()+1)+c)

good idea! thank you! saved another 2 chars!

05AB1E, 29 38 31 29 bytes
'|„ǝʒ:'ǝ¡'ʒмεD®>úsg®+©s}.Bεð²J,

Can definitely be golfed, but at least its working now..
+9 bytes because ¡ (split) removes empty items automatically, so I had to add '|„ǝʒ:'ǝ¡'ʒм..
-2 bytes thanks to @MagicOctopusUrn by changing '|„ǝʒ:'ǝ¡'ʒм to '|¶:.BεðÜ} (current solution doesn't work on items with trailing spaces, but I've assumed that's allowed according to the test cases).
Try it online.
Explanation:
'|¶:           # Take the first input, and replace every "|" with "¶"
               #  i.e. "abc|d|e||fg" → "abc¶d¶e¶¶fg" (¶ are new-lines in 05AB1E)
    .B         # Box all the items (appending trailing whitespace to make it a rectangle)
               #  i.e. "abc¶d¶e¶¶fg" → ['abc','d  ','e  ','   ','fg ']
      εðÜ}     # Remove all trailing spaces from each item
               #  i.e. ['abc','d  ','e  ','   ','fg '] → ['abc','d,'e','','fg']
               #  NOTE: `'|¡` would have resulted in ['abc','d','e','fd'], hence the use of
               #        Box which implicitly splits on new-lines to keep empty items
ε              # For-each:
 D             #  Duplicate the current item
  ®>ú          #  Prepend global_variable + 1 amount of spaces
               #  (+1 because the global_variable is -1 by default)
               #   i.e. "e" and 3+1 → "    e"
 sg            #  Swap so the duplicated item is at the top, and take its length
   ®+          #  Sum it with the global_variable
               #   i.e. "e" (→ 1) and 4 → 5
     ©         #  And store it as new global_variable
      s        #  Then swap so the space appended item is at the end again
       }       # And end the for-each loop
.B             # Box all the items (appending the appropriate amount of spaces)
               #  i.e. ['abc','   d','    e','     ','     fg']
               #   → ['abc    ','   d   ','    e  ','       ','     fg']
ε              # For-each again:
 ð             #  A space character
  I            #  The second input-character
   J           #  Join both together with the current item
    ,          #  And print the current row with trailing new-line

This is invalid if the code were to contain ǝʒ. '|¶:.B could work tho.

@MagicOctopusUrn The challenge description states "The code input will only contain printable ASCII, and it will not contain any newlines." Also, what part of the code should be replaced with '|¶:.B?

I was thinking that'd be a shorter split, but it wouldn't work with your current code just slamming it in, you'd have to trim the excess. OR just ignore the excess and .B a second time after adding in the preceeding spaces.

@MagicOctopusUrn It indeed might save some bytes, since my current work-around is pretty long, but it'll be harder to calculate the amount of preceeding spaces with the spaces after the .B already present.

'|¶:.BεðÜ}εD®>úsg®+©s}.BεðIJ,? 29 bytes. Back to iteration 1 :). .B splits on newlines, which is a feature not many people know. It's the only way I know of to keep empty elements. I'd request this as a feature. .¡ should mean split, but keep empty elements..

@MagicOctopusUrn Thanks. Indeed didn't knew .B implicitly splits on newlines. And using .¡ as split but keep empty items seems like a nice addition.

Japt -R, 17 bytes
There's a byte to be saved here, at least, I just can't quite see it.
q| ËùT±DÊÃú Ë+ViS

Try it
q| ËùT±DÊÃú Ë+ViS     :Implicit input of strings U=programme & V=character
q|                    :Split U on |
   Ë                  :Map each D
    ù                 :  Left pad with spaces to length
     T±               :    Increment T (initially 0) by
       DÊ             :    Length of D
         Ã            :End map
          ú           :Right pad each with spaces to length of longest
            Ë         :Map
             +        :  Append
              Vi      :    V prepended with
                S     :      Space
                      :Implicit output joined with newlines

Wow, this is almost exactly the code I came up, the only difference being that I had ®+S+V instead of Ë+ViS

I found that byte you were looking for :)

PowerShell v2+, 103 99 bytes
param($a,$b)$a-split'\|'|%{" "*$l+$_+" "*(($a-replace'\|').length+1-$_.length-$l)+$b;$l+=$_.Length}

Takes input as two strings, -splits the first on literal pipe (since split uses regex syntax), and feeds the elements into a loop |%{...}.
Each iteration, we construct a string as being a number of spaces defined by $l concatenated with the current element. For the first loop, $l initializes to $null, which gets evaluate here as 0.
That string is further concatenated with another number of spaces (defined by how long $a would be if we -replaced every pipe with nothing, plus 1 for the additional padding between code and comments, minus the .length of the current element, minus $l which is how many spaces we padded left on this iteration), concatenated with our comment character $b. That's left on the pipeline.
We then update $l for the next iteration.
The resultant strings are all left on the pipeline, and output via implicit Write-Output happens at program execution, with a newline between them by default.
Examples
PS C:\Tools\Scripts\golfing> .\esolang-comment-template-generator.ps1 "This|Code|has||empty||sections" "@"
This                     @
    Code                 @
        has              @
                         @
           empty         @
                         @
                sections @

PS C:\Tools\Scripts\golfing> .\esolang-comment-template-generator.ps1 "a|bc|def|ghi|h" "|"
a          |
 bc        |
   def     |
      ghi  |
         h |

Vim, 39 38 keystrokes
-1 byte thanks to DJMcMayhem
Expects as input a buffer (e.g. a file) whose first character is the comment delimiter, followed by the code, e.g. #foo|bar|baz.
"cxqaf|m`Yp<Ctrl+o>v$r jv0r x@aq@a$p<Ctrl+v>gg$C <Ctrl+r>c<Esc>

Explanation
("_" denotes a literal space.)
"cx          " Delete the first character (the comment delimiter) and store in register 'c'
qa           " Start recording macro 'a'
f|m`         " Advance to the first '|' on the line and set mark
Yp<Ctrl+o>   " Duplicate this line and return to mark
v$r_         " Replace everything after the cursor on this line (inclusive) with spaces
jv0r_x       " Go down a line and replace everything before the cursor on this line (inclusive) with
             "   spaces, then delete one space
@a           " Call macro recursively
q@a          " Stop recording and immediately call the macro
$p           " Paste the deleted space at the end of the last line
<Ctrl+v>gg$       " Highlight the column where the comment delimiters will go and all trailing spaces
C_<Ctrl+r>c<Esc>  " Replace the highlighted text on each line with a space and the contents of
                  "   register 'c' (the comment delimiter)

:D I always upvote vim! I think you could take one byte off if you change mm to m\`` and then change `mto`

@DJMcMayhem Thanks! I love golfing in Vim because I always learn something about a tool I use every day.

Floroid - 94 bytes
Ah(a,b):c=a.fn("|");z(" "+b+"\n".y(' '*Z("".y(c[:j]))+l+" "*Z("".y(c[j+1:]))Kj,lIai(c))+' '+b)

Uses an approach similar to @JonathanAllans' Python solution.
Testcases
Call: h("a|bc|d|e|fgh|ij|k|l|mn|op", "#")
Output:
a                #
 bc              #
   d             #
    e            #
     fgh         #
        ij       #
          k      #
           l     #
            mn   #
              op #

C# 176 167 154 bytes
string f(string s,char x){var c=s.Split('|');var d="";int i=0;foreach(var b in c)d+=b.PadLeft(i+=b.Length).PadRight(s.Length+2-c.Length)+x+"\n";return d;}

UnGolfed
string f(string s, char x)
{
    var c = s.Split('|');
    var d = "";
    int i = 0;
    foreach (var b in c)
        d += b.PadLeft(i += b.Length).PadRight(s.Length + 2 - c.Length) + x + "\n";
    return d;
}

A LINQ solution would have been 146 but needed using System.Linq; bringing it back up to 164:
string f(string s,char x){var c=s.Split('|');int i=0;return c.Aggregate("",(g,b)=>g+b.PadLeft(i+=b.Length).PadRight(s.Length+2-c.Length)+x+"\n");}

Old solutions:
167 bytes:
string f(string s,char x){var c=s.Split('|');var d="";int i=0;foreach(var b in c){d+=b.PadLeft(i+b.Length).PadRight(s.Length+2-c.Length)+x+"\n";i+=b.Length;}return d;}

176 bytes using string interpolation
string f(string s,char x){var c=s.Split('|');var d="";int i=0;foreach(var b in c){d+=string.Format($"{{1,{i}}}{{0,-{s.Length+2-c.Length-i}}}{x}\n",b,"");i+=b.Length;}return d;}

Perl, 63 bytes
Includes +5 for -Xpi
Run with input on STDIN and comment character after -i:
perl -Xpi% esolang.pl <<< "Ab|Cd||ef"

esolang.pl:
s/
/|/;s%(.*?)\|%$"x$`=~y/|//c.$1.$"x$'=~y/|//c." $^I
"%eg

Totally boring straightforward solution

Jelly, 10 bytes
ṣ”|⁶ṁ;ɗ\pG

Try it online!

Explanation by hyper-neutrino

AWK, 107 104 103 bytes
w=2-(n=split($1,p,"|"))+gsub(t=".",FS,$1){for(;s++<n;gsub(t,FS,b))y=y substr((b=b p[s])$1,1,w)$2RS}$0=y

Try it online!
Thanks to Pedro Maimere for helping shave off more 3 chars
One interesting thing about this challenge...  I found a quirk about the TIO AWK setup.  I can't figure out way to specify input where a positional argument can contain a space.  Meaning setup a TIO test that behaves like this commandline,
echo "this is the first parameter" second | gawk '{ print $1 }'

In TIO, the first parameter will be "this not the whole string.  That means while it works in a terminal window, I can't show that it handle the second test for this challenge in TIO.
Here's how the code works...  The test associated with the codeblock is always truthy, so the code always runs.  It's only a test (rather then code) to avoid needing a ; character.  It does a couple of things by using AWK's willingness to combine multiple expressions into one "line" of code.
w=2-(n=split($1,p,"|"))+gsub(t=".",FS,$1)

First is splits the first parameter into in array of strings using the pipe character as the delimeter with n=split($1,p,"|").  It also saves the number of substrings generated in n.  Then it changes all the characters in the first parameter to spaces with gsub(t=".",FS,$1) setting convenience constants t and n in the process.
Finally the value of w is set to the number of non-pipe characters in the first parameter by subtracting the number of sub-strings from the total number of characters in the original.
The associated code block is one statement, a for loop, that processes each substring.
for(;s++<n;gsub(t,FS,b))y=y substr((b=b p[s])$1,1,w)$2RS

The iteration check is simple s++<n. The end of loop statement converts all the characters in the previous output line to blanks gsub(t,FS,b), which turns it into the prefix for the next line.  The body of the loop constructs and appends the next line of output to an accumulator y.  That string is a concatenation of the previous string, plus the current string (code fragment) with a bunch of blanks appended (meaning $1) (b=b p[s])$1.  That mess is truncated to the length we want w and the comment delimiter and LF are appended with y=y substr(...,w)$2RS.
Once all the code substrings have been processes, assigning $0 to the accumulator takes care if printing out the results.
$0=y

104 bytes. It is having trouble when the code has spaces. I haven't figured out a way to fix that, though.

I keep forgetting to use FS and RS. :)  Thanks!  The spaces work when I run it from the command line.  Meaning when I run it in a terminal window.  I think it's something about passing tokenized input to AWK in TIO.  I haven't found a way to pass something like "this is one parameter" as $1 in TIO.

I tried in gawk 5.0.1 and mawk 1.3.3, without success. What version of awk are you using? I also tried another algorithm, but only reached 105 bytes. (sigh)

This works on my system echo "E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last!" '!' | gawk 'w=2-(n=split($1,p,"|"))+gsub(t=".",c=FS,$1){for(;s++<n;gsub(t,c,b))y=y substr((b=b p[s])$1,1,w)$2RS}$0=y' and it's on Ubuntu 18.04 running GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)

That didn't work either. Well, I modified a bit of your code, and managed to run it on TIO and command-line, costing 2 more bytes. Please check it out, there might be some opportunity to shorten it.

I will also leave my own attempt here, which also has 105 bytes.

I'd post that one as a separate answer since it's a completely different approach.

JavaScript (Node.js), 79 bytes
c=>s=>s.split`|`.map((_,i,a)=>a.map(y=>i--?y.replace(/./g,' '):y).join``+' '+c)

Attempt This Online!
+4 to add an extra space before #

Vyxal j, 74 bitsv2, 9.25 bytes
\|/:¦↳:t↲Ḋ

Try it Online!
Bitstring:
01101010100010101110000101000000110001011111111110001111111100110011110001

Explained
\|/:¦↳:t↲Ḋ
\|/         # Split on "|"s
   :¦       # Push the cumulative sums without popping. This acts as the space length before each section
     ↳      # Pad each item right with spaces to length in ^
      :t↲   # And pad each item left with spaces to length of tail of ^
         Ḋ  # Append " {comment char}" to each
Implicitly join on newlines

Created with the help of Luminespire and not this challenge.

You should probably make the Try it Online link have a test case that actually shows the task

Ruby, 96 80 bytes
->s,c{s.gsub(/(^|\|)([^|]*)/){" "*$`.count(t="^|")+$2+" "*(1+$'.count(t))+c+$/}}

See it on eval.in: https://eval.in/639012
I really ought to just learn Retina.

PHP, 120 117 116 110 109 bytes
foreach($a=split('\|',$argv[1])as$i=>$t){$c=preg_replace('#.#',' ',$a);$c[$i]=$t;echo join($c)," $argv[2]
";}

or
foreach($a=split('\|',$argv[1])as$t){$c=preg_replace('#.#',' ',$a);$c[$i++|0]=$t;echo join($c)," $argv[2]
";}

MATL, 33 31 bytes
'\|'0'|'hYXo8M&YbY:&YdtaZ)0ihYc

Try it online!
Explanation
The builtin function Yd (blkdiag), which builds a block-diagonal matrix from its inputs, does most of the work. The fill values in the matrix are 0, and char 0 is treated as a space for displaying purposes. The code would simply split on |, build a matrix from the resulting blocks, convert to char, and append two columns with space and comment symbol.
However, the possibility of empty sections in the input string complicates makes the problem more interesting: the resulting block would be empty and thus wouldn't show in the resulting matrix.
To solve this, we introduce a char 0 before each |, so no block will be empty; and then in the resulting char matrix we remove columns that are formed by char 0 only. A non-empty code section will have some printable ASCII char, and thus the columns it spans will survive. An empty section will contribute a row, but won't introduce an extra column.
'\|'    % Push this string: source for regexp matching. It's just | escaped
0'|'h   % Push a string formed by char 0 followed by | (no escaping needed)
YX      % Input string implicitly. Replace first of the above string by the second
o       % Convert from chars to code points. Gives a numeric vector
8M      % Push '|' again
&Yb     % Split numeric vector at occurences of | (the latter is automatically
        % converted  to its code point). This gives a cell array of numeric vectors
Y:      % Unbox cell array: pushes the numeric vectors it contains
&Yd     % Form a block-diagonal matrix from those vectors
ta      % Duplicate. Compute vector that equals true for columns that have some
        % nonzero value
Z)      % Used that as a logical index (mask) for the columns of the matrix.
        % This removes columns that contain only zeros
0ih     % Input comment symbol and prepend char 0 (which will be displayed as space)
Yc      % Append that to each row of the matrix. The matrix is automatically
        % converted from code points to chars
        % Display implicitly

I'm vaguely disappointed that you didn't put your explanation in the format the OP mentioned

@Random832 I don't use that format often. It uses up a lot of space, leaving little room for the explanations

Why is the escape needed in the first string?

@ConorO'Brien Good question. I never know which/when special symbols need escaping and which/when not. In this case, | (match subexpression before or after the |) does need it, at least in the Matlab/Octave regexp engine

APL (Dyalog Unicode), 28 bytes
Full program. Prompts for code, then for comment character.
⍞,⍤1⍨⎕FMT⎕TC[2]@('|'∘=)⍞,' '

Try it online!
⍞,' ' append a space the to prompted-for code
⎕TC[2]@(…) place the 2nd Terminal Control character (Line Feed) at the positions indicated by:
 '|'∘= the mask indicating where the pipe symbol is equal to the characters
⎕FMT ForMaT as a character matrix, evaluating terminal control characters (Line Feed moves the "cursor" down one line)
⍞,⍤1⍨ prompt for comment character and append it to each line (lit. to each 1D sub-array)

How is dyalog APL non-competing still? Is it still in-dev?

@DJMcMayhem Yes. I work for Dyalog and have had access to 16.0 even before 15.0 was released. 16.0 is scheduled for release in 2017Q1.

How does this work?

@ConorO'Brien Rewritten, and explanation added.

Pyth, 30 bytes
VJcE\|s[*ZdN*h--lsJZlNdQ)=+ZlN

or
jm+dQ.t.t+MC,.u*l+NYdJc+Ed\|kJ

Both are full programs that take input on STDIN of the comment string, and then the program string, newline-separated.
Try the first version online
Try the second version online
How they work
VJcE\|s[*ZdN*h--lsJZlNdQ)=+ZlN  Program. Inputs: E, Q
  cE\|                          Split E on "|"
 J                              Assign to J
                                Implicit Z=0
V                               For N in that:
       [                )        Create a list with elements:
        *Zd                       Z spaces
           N                      N
               -lsJZ              len(concatenate(J))-Z
              -     lN             -len(N)
             h                     +1
            *         d            spaces
                       Q          Q
      s                          Concatenate the list
                                 Implicitly print
                        =+ZlN    Z=Z+len(N)

jm+dQ.t.t+MC,.u*l+NYdJc+Ed\|kJ  Program. Inputs: E, Q
                       +Ed      Add a trailing space to E
                      c   \|    Split that on "|"
                     J          Assign to J
             .u                 Cumulatively reduce J with:
                            k    starting value empty string and
                                 function N, Y ->
                l+NY              len(N+Y)
               *    d             spaces
            ,                J  Two-element list of that and J
           C                    Transpose
         +M                     Map concatenation over that
       .t                       Transpose, padding with spaces
     .t                         Transpose again
 m+dQ                           Map concatenation with Q over that
j                               Join on newlines
                                Implicitly print

GolfScript, 85 bytes
{(;);}:r;", "%(r\(r n+:c;;.,\'|'%.,@\-)):l;0:m;{.,0>}{" "m*\(.,m+:m l\-" "\*+c@}while

Try it online
2017 Update - GolfScript - 71 bytes
', '/~~:c;~1/.,\.{'|'=},,@\-):l;['|']/0:i;{.,i+:i l i-' '*c+\' '*"
"\}/

Explanation
', '/~~:c;~1/        # Parses input
.,\.{'|'=},,@\-):l;  # Computes string length without '|'
['|']/               # Splits the array
0:i;                 # Counter
{.,                  # Length of the substring
i+:i                 # Counter update
l i-' '*c+\          # Adds spaces after the substring
' '*"\n"\            # Adds spaces before the next substring
}/                   # ...For each substring

Turtlèd, 35 bytes (noncompeting)
Takes one input, the last character is the comment character. Does not work with comment character as space, but I assume that isn't necessary.
!' [*.+(|' dl)r_]' r[*+.(|u)_][ .d]

Explanation:
!                                  take input into string variable
 '                                 write space over current cell
   [*           ]                  while cell is not *
     .+                            write pointed char of string, stringpointer+1 (starts 0)
       (|    )                     if current cell is |
         ' dl                      write space (over |), move down, left
              r_                   move right, write * if pointed char is
                                   last char, else space

                 ' r               write space, move right
                    [*       ]     while cell is not *
                      +.           increment pointer and write pointed char
                        (|u)       if cell is |, move up
                            _      write * if the pointed char is the last char

                              [   ] while cell is not space
                                .d  write the pointed char from string, move down

Funky, 89 bytes
s=>c=>{y=0forn inl=s::split"|"print((v=" "::rep)(y)+l[n]+v((#l::reduce@++1)-y+=#l[n])+c)}

Try it online!

Python 3.8 (pre-release), 99 bytes
Different approach:
def f(c,d,i=0):
 for y in(x:=c.split('|')):z=[' '*len(e)for e in x];z[i]=y;print(''.join(z),d);i+=1

Try it online!
Ungolfed with explanation:
def f(c,d,i=0):
 x=c.split('|')              # break string by '|'
 for y in x:                 # for each element of list
  z=[' '*len(e) for e in x]  # create a list of blank strings
  z[i]=y                     # insert element we care about into otherwise blank list
  print(''.join(z),d)        # print line
  i+=1                       # increment

Stax, 16 bytes
ù3l╛CrΣ╝▀↕┘╣óétº

Run and debug it

Python 3, 108 bytes
s,c=input().split("|"),input()
i,S=0,len("".join(s))
for l in s:L=len(l);print(" "*i+l+" "*(S-L-i+1)+c);i+=L

Try it online! Simple solution -- keep track of how many spaces we have (i) and accumulate.

Go, 209 bytes
import."strings"
func f(C,c string)string{L,Q,S:=Split(C,"|"),[]string{},0
for _,l:=range L{q:=len(l)
if q<1{continue}
Q=append(Q,Repeat(" ",S)+l+Repeat(" ",len(Join(L,""))-q+1-S)+c)
S+=q}
return Join(Q,"\n")}

Attempt This Online!
Explanation
import."strings"
func f(C,c string)string{
// split C into substrings, and init the output slice and space count
L,Q,S:=Split(C,"|"),[]string{},0
// for each substring...
for _,l:=range L{
// if it's empty, skip it
q:=len(l)
if q<1{continue}
// add to the output slice...
Q=append(Q,
    // initial spaces
    Repeat(" ",S)+
    // the substring
    l+
    // the following spaces
    Repeat(" ",len(Join(L,""))-q+1-S)
    // and the comment
    +c)
// increment the space count
S+=q}
// join together with newlines
return Join(Q,"\n")}

JavaScript (Node.js), 84 79 bytes
c=>s=>s.split`|`.map(l=>z="".padEnd(a=z.length)+l,z="").map(l=>l.padEnd(a+2)+c)

Attempt This Online!
Saved 5 bytes by using two iterations instead of 1 but keeping track of the previous string so no number is needed to keep track of the length.

Japt -R, 16 bytes
q| åÏiXîÃú m+S+V

Try it
The boilerplate is similar to @Shaggy's 17 byte Japt submission.
Explanation:
q|                 split on |
   åÏ              cumulatively reduce each X, Y to:
     i               prepend to Y
      Xî             spaces to the length of X
        Ã          end cumulative reduce
         ú         right-pad each to the longest line
           m+      to each, append
             S+V     space (S) and comment char (V)

flag -R            join the final result on newlines

Ruby, 80 74 bytes
->i,c{a=0;(i=i.split ?|).map{" "*a+_1+" "*(1+i.join.size-(a+=_1.size))+c}}

Attempt This Online!
I managed to golf a non-regex based solution to beat the other Ruby. The solution previously tied but I found a slightly different method that is 6 bytes shorter.
Explanation:
->i,c{…} Proc (lambda function) taking arguments i (code) and c (comment)

a=0; Assign variable a to zero

(i=i.split ?|) Assign i to it split on |

.map{…} Map each _1 in the list to:

" "*a a spaces

+_1 Append the list item

+" "*(…) Append this many spaces:

1+i.join.size The size of i with | removed, plus one for the extra space
-(a+=_1.size) Add the size of the list item to a and subtract a from this.

+c Append the comment character to the end of the line.

Haskell, 96 bytes
f"".lines.map r
r '|'='\n'
r c=c
w=(' '<$)
f l(a:s)c=(w l++a++(w=<<c:s)++c):f(l++a)s c
f l s c=s

Attempt This Online!
Eplanation
The function r is defined to map pipe characters to newlines (r '|'='\n') and every other char to itself (r c=c). lines.map r thus first replaces all pipes in the input string with new lines (map r), and then splits the string at the newlines with the build-in lines function.
The main function f iterates over this list of strings and constructs the output line by line with the expression w l++a++(w=<<c:s)++c where

a is the part of the code that appears on the current line
c is the comment character (as a string) that gets put at the end of the line
w is a function that replaces each character of a string by spaces (definde by w=(' '<$))
l is the string of code fragments to the left of a, which is put at the beginnig of the line as spaces with w l
s is the list of remaining code strings which are also converted to spaces, concatenated, and put after a (c is added to s to get the extra space required before the comment character)

Uiua, 42 40 36 bytes
≡⊂⬚@ ≡°□\⍚(⊂≡⋅@ )⊕□⍜▽¯⟜\+=,@|:¤⊟@

Try it
-2 bytes thanks to chunes :)
This was one of my first Uiua answers, I got so much better in only 2 weeks, and was able to save 10%!

-2 since ⊙(F⊙(G)) is equivalent to ⊙(F|G).

@chunes Cool! So many neat features I haven’t seen yet

Perl 5 -pl, 50 bytes
$f=<>;s%\||$%$"x$'=~y/|//c." $f
".$"x$`=~y/|//c%ge

Try it online!

Scala, 123 bytes
def?(i:String,c:String)={var b=0
i.split('|').map{s=>println(" "*b+s+" "*(i.replace("|","").size-b-s.size+1)+c)
b+=s.size}}

Test code + Output:
?("a|b|c|d|e|f|g", ",")
a       ,
 b      ,
  c     ,
   d    ,
    e   ,
     f  ,
      g ,

?("abcdefg", ":")
abcdefg :

?("4|8|15|16|23|42", "%")
4          %
 8         %
  15       %
    16     %
      23   %
        42 %

?("E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last!", "!")
E                                                   !
 ac                                                 !
   h s                                              !
      ecti                                          !
          on is                                     !
                one c                               !
                     haracte                        !
                            r longer                !
                                     than the       !
                                              last! !

?("This|Code|has||empty||sections", "@")
This                     @
    Code                 @
        has              @
                         @
           empty         @
                         @
                sections @

Jelly, 41 bytes
This looks like it has far to many increments, and probably too many links...
ṫø⁹‘‘µFL‘⁶ẋ
‘ị
ḣFL⁶ẋ$;ç@;1ŀ
J’ç@€
ṣ”|Ç;€Y

Test it at TryItOnline
How?
ṫø⁹‘‘µFL‘⁶ẋ  - link 1: get the spaces for after the code, dyadic(split string, index)
 ø           - next chain as a nilad
  ⁹‘‘        - right argument incremented twice (the index we actually want)
ṫ            - tail (get the rest of the split string)
     µ       - next chain as a monad
      FL‘    - flatten, get its length and increment
         ⁶   - a space character " "
          ẋ  - repeat the space character that many times

‘ị           - Link 2: get the code for a line dyadic(index, split string)
‘            - increment the index
 ị           - retrieve the string at that index

ḣFL⁶ẋ$;ç@;1ŀ - Link 3: get the code and join with spaces, dyadic (index, split string)
ḣ            - head: split string[index:]
 FL          - flatten and get its length
     $       - previous two atoms as a monad
   ⁶         - a space character, " "
    ẋ        - repeat the space that many times
      ;      - concatenate with
       ç@    - the result of the previous link (the code) - reverse inputs
         ;   - concatenate with
          1ŀ - the result of Link 1 (the spaces after the code)

J’ç@€        - Link 3: a for loop, monadic(split string)
J’           - [0,...,Len(split string)-1]
  ç@€        - the result of the previous link, with revered inputs, for each

ṣ”|Ç;€Y      - Main Link: dyadic(code string, comment character)
ṣ”|          - split on "|"
   Ç         - the result of the previous link
    ;€       - concatenate each with the comment character
      Y      - join with line feeds
             - implicit print

CJam, 32 bytes
l'|/_s,)L@{1$,S*\+}%@f{Se]}lN+f+

Explanation
l                                  get code string
 '|/                               split into code parts
    _s,)                           length of all the parts +1
        L@{1$,S*\+}%               left pad spaces to every part for the length of the previous parts
                    @f{Se]}        right pad spaces
                           lN+f+   add comment character and newline

Try it online

Thunno 2 N, 25 bytes
'|/DJl⁺X0Yıyṣs+xðĿnlẏ+ƥ¹+

Try it online!
Explanation
(Yes, this is in the exact same format as the outputs for this challenge :P)
'|/DJl⁺X0Yıyṣs+xðĿnlẏ+ƥ¹+  '# Implicit input
'|/                        '# Split the input on "|"
   DJl                      # Duplicate, join, and get length
      ⁺X                    # Increment this and store it in x
        0Y                  # Store 0 in y
          ı                 # Map over the list:
           yṣ               #  Push y spaces
             s+             #  Prepend this to the input
               xðĿ          #  Pad with spaces to length x
                  nlẏ+ƥ     #  Add the length to y
                       ¹+   #  Append the second input
                            # Implicit output, joined on newlines

GolfScript, 44 43 bytes
~:~;"|"/[""\{\," "*\+.}/,):l;]{l" "*+l<~n}/

Try it online!
This was my first GolfScript submission, and I’ve improved quite a lot since I first tried this task.
Explanation:
~:~;

Eval STDIN as GolfScript. Assign the comment character to the ~ variable, and pop out of the stack, so the code is on top.
Using a symbol instead of a letter as a command name let me remove a whitespace later on.
"|"/

Split the code on |s.
[""\{\," "*\+.}/

This is equivalent to a scan (reduce, keeping in-between values) by repeating spaces to the length of the previous value, and prepending that to the current value.
GolfScript doesn’t have scan built-in, so this is implemented somewhat cumbersomely, using / (each) and duplicating the result each iteration.
,):l;]

The previous step left an extra copy of the last value. We take its length, increment that, and assign it to l.
{l" "*+l<~n}/

For each line ({ … }/): append l spaces (l" "*+), take the first l characters (l<), then push ~ (the comment character) and n (newline).
The entire stack is printed when the program ends.
Original solution:
GolfScript, 64 63 bytes
~n+:c;0:a;."|"/""*,):b;{.124={;b" "*c" "a*}{a):a;b(:b;}if}%" "c

Try it online!
Full program, takes input like "abc|def|g" "#" on STDIN.
I’ve always thought GolfScript seemed interesting but have never actually tried it. After using quite a few more modern golfing languages with hundreds of built-ins, the terse but very readable syntax of GolfScript is really refreshing. I had a lot of fun trying to get this to work, so I’m glad I could beat the 75 byte solution posted in 2017.
I had a 50-or so byte version that used stack manipulation instead of variables, but couldn’t get it to work.
I hope you like the smileys ): (: :b :c ={
Explanation
Eval the input; this leaves two strings on the stack. Append a newline to the top one, store it in c as the comment character, and pop it off the stack. The variable a is initialized to 0. The variable b is initialized to the length of splitting the input on | and joining it back.
The top of the stack is now the |-separated string. Map each character of the input string to:

If the character is |, leave b spaces, c, a newline, and a spaces on the stack.

Otherwise, increment a, decrement b, and leave the original character in the stack.

Finally, push a space and c to the stack. The whole stack is implicitly output at the end.

Swift 5.9, 153 152 bytes
let f={var x={{String.init}()(" ",$0)},s=($0+"").split{$0=="|"},i=0
return{s.map{x(i)+$0+x(s.joined().count-(i+=$0.count,i).1+1)}.joined}()($1+"\n")+$1}

This is an almost direct port of Kevin Cruijssen's Java answer. Here's an ungolfed version:
let function = { (code: String, comment: String) -> String in
  // convenience closure to repeat the space character
  let spaces = { String(repeating: " ", count: $0) }

  // split the code into substrings using the pipe as
  // a separator
  let splitCode = code.split(separator: "|")

  var indentLevel = 0

  let indentedCode = splitCode.map { line in
    // start off with the previous indent level
    let leadingIndent = spaces(indentLevel)

    // update the indent level for the trailing indent
    // and the next leading indent
    indentLevel += line.count

    // gets the total length of the code, subtracts the
    // current indent level, and adds 1 for an extra
    // trailing space
    let trailingIndentAmount = splitCode.joined().count - indentLevel + 1
    let trailingIndent = spaces(trailingIndentAmount)

    return leadingIndent + line + trailingIndent + comment
  }

  // finally, join the code with newlines and return it
  return indentedCode.joined(separator: "\n")
}

Perl 5 + -lF\| -M5.10.0, 31 bytes
A different approach to both the existing Perl answers.
$,=v12;say@F," .[A@{[<>]}.."x@F
Try it online!
Explanation
Sets $, (which is the record separator, automatically printed between each item of a list) to v12 (which is chr(12), or form feed - which moves the cursor down a line), then we say @F (which is the input, split on |), followed by a raw string consisting of space, the ANSI escape sequence for "up one line", the comment char from STDIN (<>), which is embedded to the string using @{[...]}, and two backspace characters, which is repeated the same number of times as there are items in the input (using the list of input, @F, in a scalar context yield the list length).

source: Stack Exchange

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

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

sort: votes


text:
Hexagolf: Validagons
Challenge
Given an ASCII art shape, you must find out whether the shape is a regular hexagon or not.
Hexagons
A regular hexagon is defined using two rules:

It has six sides
Each side has equal numbers of characters

For example, the following shape is regular but it doesn't have six sides and so is not a regular hexagon:
B a a h
s a i d
y o u r
g a o t

Similarly, the following shape has six sides but has sides of different lengths and so is not a regular hexagon:
  * *
 * * *
* * * *
 * * *
  * *

However, the following shape has six sides and all of the sides have the same number of characters, so it is a regular hexagon:
  T h e
 h e x a
g o n s a
 r e c o
  m i n

Rules
Output should be a truthy or a falsey value (truthy if the shape is a regular hexagon, falsey if not).
The shapes will only ever contain printable ASCII characters.
The border of the shape will never contain spaces. If it does, you can return falsey.
There can be arbitrary amounts of whitespace before and/or after the shape.
All angles in the shape may not be equal for example, the following shape is valid input:
  . . .
   . . .
. . . . .
 . . . .
  . . .

It will return a falsey value.
All shape inputs will be on a space separated grid. Hexagonal input will be on a staggered grid (each line is offset from the next).
Examples
Truthy
The following shapes should return truthy values:
 # _
+ + +
 9 :

  5 6 7
 8 9 0 1
2 3 4 5 6
 7 8 9 0
  1 2 3

    t h i s
   i       s
  a         h
 e           x
  a         g
   o       n
    ! ! ! !

    5 6 7
   8 9 0 1
  2 3 4 5 6
   7 8 9 0
    1 2 3

Falsey
The following should return falsey values
r e c t a
n g l e s

  h e l l o
 w o r l d s
t h i s i s b
 e t a d e c
  a y n o w

  *
 * *
* * *

  .....
 .......
.........
 .......
  .....

This shape is not on a space separated grid and is not staggered.

   * * * *
  ---------
 * * * * * *
-------------
 * * * * * *
  ---------
   * * * *

5 6 7
8 9 0 1
2 3 4 5 6
7 8 9 0
1 2 3

For single character inputs, your program may output either truthy or falsey:
&

Winning
The shortest program in bytes wins.

Mathematica one liner incoming.

I think you might want to add two test cases: One without leading spaces, for example: 5 6 7\n8 9 0 1\n2 3 4 5 6\n7 8 9 0\n1 2 3 and one with an additional space leading for one of the rows: ss5 6 7\nss8 9 0 1\n2 3 4 5 6\ns7 8 9 0\nss1 2 3 (leading spaces are replaced with s to make it a bit more clear in this unformatted form). All 10 of your test cases are validating correctly with my code currently, but these two cases would fail with the approach I used.

Is the example with the periods necessarily falsey ? The missing period is  a space which is one of the valid characters that can make up the hexagon,

@TonHospel I think the idea is that the outline is an unbroken regular hexagon.

All angles in the shape may not be equal for example, the following shape is valid input: This phrasing seems misleading. Surely we are detecting regular hexagons? Do you mean to write that the symbols don’t necessarily have angular symmetry?

@Lynn It's more that all input will not necessarily be a regular shape

Ah. That seems like a strange thing to specify. Anyway, I agree with Ton Hospel’s complaint. You need to specify that we’re interested in non-space printable ASCII characters

@Lynn That isn't the case, though as you have spaces in the ring (the third truthy example)

Okay, then you need to specify that we’re interested in hexagons with a space-free border, like Martin says.

What about input with a single non-space but also a non-zero number of spaces (and/or newlines) ? (so not JUST a single character)

@TonHospel Well those are leading/trailing spaces, so it's stilk effectively a single character

the 3rd truthy example shows just the outline of the hexagon, which depending on your interpretation does not comply with the rule "The shapes will only ever contain printable ASCII characters." What should we do with a shape that has a hexagonal outline and is partially filled in, for example it also has a diagonal? Or a hexagon that is solidly filled on one side and just an outline on the other?

@LevelRiverSt You can expect a hexagon like http://pastebin.com/kcFRBbgi

"All shape inputs will be on a space separated grid" conflicts with test case labeled "This shape is not on a space separated grid."

Some more falsey test cases: http://pastebin.com/fHnfHPiJ

R, 184 bytes
Golfed, could probably be golfed by a few bytes
function(m){e=min;f=max;l=length;v=which(m!=" ",T);a=v[,1];n=l(v[a==1,2]);u=(v[a==e(a),2]);all(u==v[a==f(a),2])&all(c(e(d<-v[a==ceiling(f(v[,1])/2),2]),f(d))==c(u[1]-n+1,u[l(u)]+n-1))}

Ungolfed, very messy, more like half way golfed
f=function(m) {
  v = which(m!=" ",T)
  a = v[,1]
  n = length(v[a==1,2])
  u=(v[a==min(a),2])
  c1 = all(u==v[a==max(a),2])
  d = v[a==ceiling(max(v[,1])/2),2]
  c2 = all(c(min(d), max(d))==c(u[1]-n+1,u[length(u)]+n-1))
  c1 & c2
}

Since the input format is unspecified, Input needs to be specified in an R array format, looking something like this.
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] " "  " "  "5"  " "  "6"  " "  "7"  " "  " "
[2,] " "  "8"  " "  "9"  " "  "0"  " "  "1"  " "
[3,] "2"  " "  "3"  " "  "4"  " "  "5"  " "  "6"
[4,] " "  "7"  " "  "8"  " "  "9"  " "  "0"  " "
[5,] " "  " "  "1"  " "  "2"  " "  "3"  " "  " "

Here is a generator function that generates the input. The generator doesn't generate an object that is fed into hexagon check function, but rather the code specifying the array (effectively the same thing). So this should not count as parsing the text. Remember that I'm not inputting text, but rather an array structure.
generate = function(x) {
  s = strsplit(strsplit(x, "\n")[[1]], "")
  m = max(sapply(s, length))
  dput(do.call(rbind, lapply(s, function(x) c(x, rep(" ", m-length(x))))))
}

For example, the generated code would be: structure(c(" ", " ", "2", " ", " ", " ", "8", " ", "7", " ", "5", " ", "3", " ", "1", " ", "9", " ", "8", " ", "6", " ", "4", " ", "2", " ", "0", " ", "9", " ", "7", " ", "5", " ", "3", " ",
"1", " ", "0", " ", " ", " ", "6", " ", " "), .Dim = c(5L, 9L
)) which is identical to array(c(" ", " ", "2", " ", " ", " ", "8", " ", "7", " ", "5", " ", "3", " ", "1", " ", "9", " ", "8", " ", "6", " ", "4", " ", "2", " ", "0", " ", "9", " ", "7", " ", "5", " ", "3", " ", "1", " ", "0", " ", " ", " ", "6", " ", " "), dim = c(5, 9))
Hopefully this input method is in compliance with the rules.
Here are the test cases
x1 =
"  5 6 7
 8 9 0 1
2 3 4 5 6
 7 8 9 0
  1 2 3"

x2 =
" # _
+ + +
 9 :"

x3 =
"    t h i s
   i       s
  a         h
 e           x
  a         g
   o       n
    ! ! ! !"

x4 ="    5 6 7
   8 9 0 1
  2 3 4 5 6
   7 8 9 0
    1 2 3"

x5 = "r e c t a
n g l e s"

x6 = "  h e l l o
  w o r l d s
t h i s i s b
 e t a d e c
  a y n o w"

x7 ="  *
 * *
* * *"

x8 ="   .....
  .......
.........
  .......
   ....."

Generate input arrays
sapply(mget(paste("x", 1:8, sep = "")), generate)

Test for hexagon
sapply(.Last.value , f)

   x1    x2    x3    x4    x5    x6    x7    x8
 TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE

@DLosc You didn't have the generate function defined. Try this link:
http://goo.gl/9MtCLg You can also check with a manual input like f(array(c(" ", " ", "2", " ", " ", " ", "8", " ", "7", " ", "5", " ", "3", " ", "1", " ", "9", " ", "8", " ", "6", " ", "4", " ", "2", " ", "0", " ", "9", " ", "7", " ", "5", " ", "3", " ", "1", " ", "0", " ", " ", " ", "6", " ", " "), dim = c(5, 9)))

Ah, I missed that part. Thanks.

JavaScript (ES6), 214 bytes
(s,a=s.split`\n`,n=a[l=a.length>>1].match(r=/(?=\S).*\S/),i=n.index)=>!/\S(  )*\S/.test(s)&&!a.some((s,j)=>(m=r.exec(s))&&(k=m.index)<i+(j<l?j=l-j:j-=l)|k+(m=m[0].length)+j>i+n[0].length|k+i+j&1|j%l<1&m+j+j!=l*4+1)

Where \n represents a literal newline character. Ungolfed:
function validhex(s) {
    if (/S(  )*/S/.test(s)) return false;
    var a = s.split("\n");
    var l = Math.floor(a.length / 2);
    var n = a[l].match(/(?=\S).*\S/);
    for (var j = -l; j <= l; j++) {
        var m = a[j+l].match(/(?=\S).*\S/);
        if (!m) continue;
        if (m.index < n.index + Math.abs(j)) return false;
        if (m.index + m[0].length + Math.abs(j) > n.index + n[0].length) return false;
        if ((m.index + n.index + j) % 2) return false;
        if (j % l) continue;
        if (m[0].length != l * 4 + 1 - 2 * Math.abs(j)) return false;
    }
    return true;
}

I found a bug: input "  x\n g g\ng g g\n g g" should give false, but gives true.

@DLosc I take it that's two spaces before the x?

@DLosc I think I have it fixed now, cost me 30 bytes though...

SnakeEx, 200 bytes
The right language for the job... sort of.
m:{v<>}{r<RF>2P}{r<R>2P}{h<RF>1P}{w<>}{l<RF>2P}{l<R>2P}{h<.>1}
w:{u<>P}{v<>}
v:{e<L>}{u<R>1}
u:.*{e<>}
e:.$
r:[^ ]+
h:([^ ] )+
l:({c<.>}[^ ])+{c<.>}
c:{b<B>}(. )+{x<>LP}{s<>}
b:.{s<>}
s:[^\!-\~]*$
x:.

SnakeEx is a language from the 2-D Pattern Matching challenge. It ought to be really good at this task, but unfortunately all the corner cases really bloated the code. I also turned up a couple of interpreter bugs. Still, it was a fun challenge.
m is the main snake that calls all the others to do the actual work. It matches starting at the top right corner of the hexagon and going clockwise. Numbered groups are used to verify that the diagonal side lengths are all equal and that the horizontal side length matches the height of the whole figure. I could write a more detailed explanation, but I've spent the last two days dealing with corner cases, so just try it out for yourself here. :^)

Perl, 127 125 124 121 bytes
Includes +4 for -0p
Give input on STDIN
#!/usr/bin/perl -0p
/ *(.*\S)/;$a=join'\S *
\1',map$"x(abs).'\S '.(/$n/?'\S ':'. ')x(2*$n-1-abs),-($n=$1=~y/ //)..$n;$_=/^$`( *)$a\S\s*$/

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


text:
What's your next move?
This challenge is to write a minimax function in a language of your choice, to output the next best move in an NxN game of tic-tac-toe given the current board state. The board input can be accepted as a Matrix, 2D Collection or anything else that makes sense to you, but adheres to the rules. The output being the next best move for whoever's turn it is currently, where X is considered to have started.
Quick Background on the Minimax Algorithm
The basic idea of the minimax algorithm is to enumerate all possible outcomes as a DAG then weight them by the benefit that the sequence of moves has to the player, keyed by the first move made. All possible outcomes are then 'bucketed' by the first move, and are scored based on the sum of all outcomes (-1 for a loss, 0 for a tie and a 1 for a win). In implementations that require multiple players to play, you enumerate all possible moves by the player, and all possible responses by the opponents as well. For instance, in a game of tic-tac-toe (after the first move) there are 8 possible first moves you can make, and they all may seem equal when only analyzing the next turn. But by iterating through all possible outcomes for each possible set of moves that results in a final outcome and summing them all up, we can get a score for our next move, and have a basis for our choices.
For a better, more in-depth and contextual summary of the mini-max algorithm in terms of tic-tac-toe, read more here: http://neverstopbuilding.com/minimax
XKCD (3x3 Solution Only)

The Rules

Any language can be used, but no external minimax libraries are allowed.
Output can be a coordinate (0-n,0-n) or a number (1-n*n) indicative of the best next move.

In addition to this, you must be able to identify when the best case scenario is a loss or a tie instead of a win.
The way you denote a loss or a tie is, once again, up to you.

Input must use the traditional X and O, and you must assume X moves first; blank spaces can be represented by anything.
You may assume any inputs coming into your program have n O's and n+1 X's, in other words you may assume you're getting a well-formed board.
The current state of the board must be the only input to your program, if you are using recursion, helper methods must be made to facilitate the input requirements. See https://codegolf.stackexchange.com/a/92851/59376 for clarification.
Any value of 10 >= n >= 1 must be supported; if your program "times out" for n > 10, I find this acceptable as well, as some languages have significantly lower processing power (Especially using web-facing consoles).

Judging

This is code-golf, so the lowest byte-count of the program wins and standard loopholes are universally disallowed.
In the case of a tie, the program that supports the largest 'n' will win.

Example Inputs
2x2
[[X,O]
 [-,-]]

Output: 2 or [0,1]  (3 or [1,1] would also be arguably correct)
(Some form of indication of the location, arbitrary as long as you can easily explain the format you used)

3x3
[[X,O,X]
 [O,X,-]
 [-,-,-]]

Output: -1 (Loss)

Once again any input format you want is allowed, but X's and O's must be used, the examples provided were not meant to constrain to that format, just to inspire.

Sorry DJMCMayhem, I actually tried to tag those things but I couldn't, as I am new here.

Bonus also removed, added nothing but tedium.

Is the following output format allowed: a diagram of the board position with on each originally empty space a unique character indicating if playing there leads to a win/loss/draw (e.g W, L and D)

In the 3x3 example,O should lose no matter what he plays, but you say output should be [2,1], why is that?

Edited, good catch. Don't know what I was thinking, that was the negative example.

In the 2x2 example above [x,o][-,-] will win the one make the next move... So the result of evaluation routine must be 1 win... Or I understand wrong?

In a 4x4 board will win the one write first xxxx or oooo in columns row or diagonal?

Traditional tictacyoe rules, so yes.

Perl, 101 98 bytes
Includes +4 for -0p
Run with the input on STDIN
tictactoe.pl
OXO
---
--X
^D

Output is the same diagram, but with each move updated with its status, 1 represents a win, 2 represents a draw and 3 represents a loss. For this case that would be
OXO
223
21X

so 3 moves draw, 1 wins and 1 loses
(I'll update the solution if this output format is unacceptable, but the basic code will remain the same)
tictactoe.pl:
#!/usr/bin/perl -0p
m%@{[map"O.{$_}"x"@-"."O|",1-/.(
)(.)/,@-]}Z%sx||s%-%$_="$`X$'";y/XO/OX/;do$0%eg?/1/?3:1+/2/:2

This is already painfully slow and uses lots of memory for the empty 3*3 board (why actually, the recursion doesn't go that deep. Must be some memory leak). Adding memoizing costs 6 bytes but is a lot saner:
#!/usr/bin/perl -0p
$$_||=m%@{[map"O.{$_}"x"@-"."O|",1-/.(\n)(.)/,@-]}Z%sx||s%-%$_="$`X$'";y/XO/OX/;do$0%eg?/1/?3:1+/2/:2

Wow, overlooking that it's pl and likely would absolutely not run for n=10 with lots of empties... You did both of the things i was hoping to see someone do. A string input and mapping the outcome for all moves, not just the best. Bravo.

If one recursive function 'leak' how can be ok??? Too high language make not see the 32 bit register in the CPU (or something as that the simple instruction)

@RosLup Leak in this context doesn't necessarily mean unreachable lost memory. Perl is rather peculiar in when it releases memory, quite often doing this later than you would expect and so using a lot more memory than you would expect. It also tends to allocate more than directly needed in the expectance that you will grow your datastructures. In this case using "normal" recursion with a function instead of the abuse of do$0 would use 10 times less memory. Mind you, this case is so extreme it might actually be a real memory leak.

Not only one not see the registers or the base instructions (from the hlls instructions) but lose the control of memory use... For me they not scale...

It's been long enough, you win my man, sad we didn't get more attempts though.

Thank you... Good explanation in how represent result, I understand that better than minimax function theory... My code after some days in debugging is in assembly it is too much long for this place

Javascript (ES6), 320 294 bytes
(b,p,d,M,S=-2)=>(T=(p,q,r,s)=>b[p][q]==(n=b[r][s|0])&&n!='-',w=0,b.map((r,y)=>(l=r.length-1,m=15,r.map((c,x)=>(m&=8*T(l-x,x,l)+4*T(x,x,0)+2*T(x,y,0,y)+T(y,x,y))),w|=m)),w?-1:(b.map((r,y)=>r.map((c,x)=>S<1&&c=='-'&&(r[x]='O.X'[p+1],(s=-f(b,-p,1))>S&&(S=s,M=[x,y]),r[x]=c))),S=S+2?S:0,d?S:[M,S]))

Input
1) An array of array of characters describing the current board, such as:
[['X', '-'], ['-', 'O']]

2) An integer describing the current turn: 1 = X, -1 = O
Output
An array made of:

an array describing the best move in [x, y] format
the outcome of the game as an integer: 1 = win, -1 = loss, 0 = tie

Example
In the following example, X is guaranteed to win by playing [1, 2].

let f =
(b,p,d,M,S=-2)=>(T=(p,q,r,s)=>b[p][q]==(n=b[r][s|0])&&n!='-',w=0,b.map((r,y)=>(l=r.length-1,m=15,r.map((c,x)=>(m&=8*T(l-x,x,l)+4*T(x,x,0)+2*T(x,y,0,y)+T(y,x,y))),w|=m)),w?-1:(b.map((r,y)=>r.map((c,x)=>S<1&&c=='-'&&(r[x]='O.X'[p+1],(s=-f(b,-p,1))>S&&(S=s,M=[x,y]),r[x]=c))),S=S+2?S:0,d?S:[M,S]))

console.log(JSON.stringify(f(
  [['O','X','O'],
   ['-','-','-'],
   ['-','-','X']],
  1
)));

A STRANGE GAME. THE ONLY WINNING MOVE IS NOT PLAY.
HOW ABOUT A NICE GAME OF CHESS?

Well done, good first entry. Only remarks I have are the potential to save bytes with the given information 'X will always move first'. And have you tried with a non 3x3 board ;)?

@carusocomputing - Not sure to understand what you have in mind with  'X will always move first'. It could be used to deduce which side is on move given the board alone, but computing that would actually cost more bytes; so I guess you're talking about something else. Ans yes, I did some tests with slightly bigger boards. That should work as expected as long as ... err ... there aren't too many empty positions. :-)

The challenge says The current state of the board must be the only input to your program. Your code needs two inputs, which breaks this rule.

@Dada - I was wondering about that, but I assumed the active color  is part of the state of the board (just like a chess position always comes with active color + en passant square + castling availability). So I guess the OP should clarify that point. (And if you're right, that sounds like an unnecessary additional difficulty, IMHO.)

Mmm.. i really like the explanation of board state in his response. Thinking on it, some lanagues may only use strings as input, having a board like XXOOXO-OO would be hard to decipher in low byte counts without additional information like board dimensions. Ill allow any additional inputs that contribute to board state, though I still think the information 'assume X moves first' is different than 'given whos turn it is'. Some languages will take advantage of that as an assumption ;).

The input would be 1) the board 2) who is the next to move

The input can just one string of nxn dimension of X  or O; if the length is not nxn => error; if there is already a tris, error; if number of X - Number of O==0 move X, if number of X - number of O==1 move O; otherwise error...


text:
Golff y Côd - Treiglad
Read this yng Nghymraeg
Challenge
Given a word in Welsh, output all of the possible mutated forms of the word.
Mutations
A mutation is a change of the first letter of a word when following certain words or in certain grammatical contexts.
In Welsh, the following are considered "consonants":
b c ch d dd f ff g ng h l ll m n p ph r rh s t th

Note that multiple character consonants such as ch, ng and rh are counted as one letter in Welsh, and therefore one consonant.
The other letters in the Welsh alphabet are vowels, listed below:
a e i o u w y

See below, all of the mutations with the original letter on the left and the resulting mutated letters on the right:
Original | Mutations
---------+---------------
p        | b mh ph
t        | d nh th
c        | g ngh ch
b        | f m
d        | dd n
g        | [no letter] ng
m        | f
ll       | l
rh       | r

Here, [no letter] means that the g is removed from the start of the word.
Note that there are some consonants which do not mutate:
ch
dd
f
ff
j
l
n
ng
ph
r
s
th

Vowels may also be found at the start of words but do not mutate:
a
e
i
o
u
w
y

Examples
Input: dydd
Output:
dydd
ddydd
nydd

Input: pobl
Output:
pobl
bobl
mhobl
phobl

Input: gwernymynydd
Output:
gwernymynydd
wernymynydd
ngwernymynydd

Input: ffrindiau
Output:
ffrindiau

Input: enw
Output:
enw

Input: theatr
Output:
theatr

On the request of ArtOfCode ;)
Input: llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
Output:
llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
lanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch

Rules
The input will only ever be one word.
There will always be more letters after the leading consonant in your input.
Winning
The shortest code in bytes wins.

New test case: llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch

Another test case theatr; t mutates but th doesn't.

Should be 'Golff y Côd' - 'yr' only comes before a vowel, you use 'y' before a consonant.

If anyone's interested in the complicated rules regarding mutation in Welsh, there's an app called 'Ap Treiglo' which gives the rules and lists many of the words which cause mutations in the following word.

@Beta Decay Yeah, for the last 5 years. Rhyl before that, for my sins.

Irish does the same thing phonetically, but writes it quite differently (we prepend the urú, so b becomes mb (pronounced m). We even keep the case on the original initial letter, so in English is i mBéarla. Some writers keep the urú in lower case even when writing in block capitals.

JavaScript (ES6), 180 bytes
x=>x.replace(/^([cpt](?!h)|d(?!d)|[bgm]|ll|rh)(.+)/,(_,y,z)=>({p:"b mh ph",t:"d nh th",c:"g ngh ch",b:"f m",d:"dd n",g:" ng",m:"f"}[y]||y[0]).split` `.map(b=>a.push(b+z)),a=[x])&&a

Outputs as an array of strings. This is my first try, so it's almost certainly not optimal.
Try it out

f=x=>x.replace(/^([cpt](?!h)|d(?!d)|[bgm]|ll|rh)(.+)/,(_,y,z)=>({p:"b mh ph",t:"d nh th",c:"g ngh ch",b:"f m",d:"dd n",g:" ng",m:"f"}[y]||y[0]).split` `.map(b=>a.push(b+z)),a=[x])&&a
<input id=A value="pobl"><button onclick="B.innerHTML=f(A.value).join('
')">Run</button>

It's not optimal, but my PC decided to switch itself off, and I no longer remember what optimisation I was able to make.

C#, 356 338 360 bytes
I know that C# is a poor choice for code golf, but it's worth the shot:
Third attempt, all cases now pass, including th- ph- etc. This adjustment cost roughly 18 bytes.
Thanks pinkfloydx33 for the tips saving 24 bytes!
namespace System{using Linq;using S=String;class P{static void Main(S[]a){Action<S>w=Console.WriteLine;w(a[0]);foreach(S r in"th-dd-ch-ph-p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r".Split('-')){var b=r.Split('.');if(a[0].StartsWith(b[0])){foreach(S f in b.Skip(1))w(Text.RegularExpressions.Regex.Replace(a[0],$"^{b[0]}",f));break;}}}}}

Output
$> ./p gwernymynydd
gwernymynydd
wernymynydd
ngwernymynydd

Formatted Version
    namespace System {
    using Linq;
    using S = String;

    class P {
        static void Main(S[] a) {
            Action<S> w = Console.WriteLine;
            w(a[0]);
            foreach (S r in "th-dd-ch-ph-p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r"
                .Split('-')) {
                var b = r.Split('.');
                if (a[0].StartsWith(b[0])) {
                    foreach (S f in b.Skip(1))
                        w(Text.RegularExpressions.Regex.Replace(a[0], $"^{b[0]}", f));
                    break;
                }
            }
        }
    }
}

$"{f}" should just be f, you can also save the first call to write line, as well as the action, by not skipping the first element in b (saving the skip as well) and just replacing the first item with itself (I think). You also only make one call to regex so Caching/renaming the import costs more than just Text.RegularExpressions.Regex.Replace(...) in the body. The break is also superfluous since it's only gonna match once doesnt matter if it loops through to the end

There are no poor choices of language for golf - you are competing against anyone else who wants to try and beat you in the same language. Plus C# was once the golfing language of choice for Jon Skeet...

@pinkfloydx33 Thanks for the tips! However I can't remove the first Console.WriteLine call because this will skip outputting the word in case there are no replacements for it. I am sure there is a way how to optimize it by changing the condition.

I just spotted theatr case and it seems it isn't mutating correctly.

Yeah there are several test cases that don't pass at the moment because PH, TH, CH and DD do not get transformed

Fixed now, all cases pass. Thanks for noticing!

PowerShell v3+, 254 231 bytes
param($a)$a;$z=-join$a[1..$a.length]
if(($x=@{112='b mh ph';116='d nh th';99='g ngh ch';98='f m';100='dd n';109='f'})[+$a[0]]-and$a-notmatch'^[cpt]h|^dd'){-split$x[+$a[0]]|%{"$_$z"}}
($z,"ng$z")*($a[0]-eq103)
$z*($a-match'^ll|^rh')

working to golf further...
Examples
(Output is space-separated because that's the default Output Field Separator for stringified arrays. I don't know if the words I used for testing are actual words, but they fit the exceptions.)
PS C:\Tools\Scripts\golfing> 'dydd','pobl','gwernymynydd','ffrindiau','enw','rhee','llewyn','chern','ddydd','phobl'|%{"$_ --> "+(.\golff-yr-cod.ps1 $_)}
dydd --> dydd ddydd nydd
pobl --> pobl bobl mhobl phobl
gwernymynydd --> gwernymynydd wernymynydd ngwernymynydd
ffrindiau --> ffrindiau
enw --> enw
rhee --> rhee hee
llewyn --> llewyn lewyn
chern --> chern
ddydd --> ddydd
phobl --> phobl

Python 3, 196,189 185 bytes
Original attempt
w=input();print(w);[w.startswith(a)and[print(w.replace(a,i,1))for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th rh ph p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Vaultah noted that not w.find(a) would be a replacement for w.startswith(a) that would save 2 characters. But instead of not x and y we can use x or y which saves some characters more:
w=input();print(w);[w.find(a)or[print(w.replace(a,i,1))for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th rh ph p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Yet further savings by replacing w.replace(a,i,1) with i+w[len(a):]:
w=input();print(w);[w.find(a)or[print(i+w[len(a):])for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th rh ph p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Then I noticed that there was a bug, rh was listed twice; once in my short-circuit list that would take care of those double-letter consonants. Unfortunately dd was missing from there, so no savings, and we have
w=input();print(w);[w.find(a)or[print(i+w[len(a):])for i in
r]+exit()for(a,*r)in(j.split(',')for j
in'th ph dd p,b,mh,ph t,d,nh,th c,g,ngh,ch b,f,m d,dd,n g,,ng m,f ll,l rh,r'.split())]

Given any of the sample inputs, it gives the desired output; given
gorsaf

it outputs
gorsaf
orsaf
ngorsaf

and given input
theatr

it prints
theatr

C#, 349 bytes
Based on @grizzly's submission, but corrected to work with the consonants that don't get transformed (ph/ch/th/dd) that it wasn't working with, plus trimmed some excess out. Hope that's alright?
I had it down to 290 until I realized that I was missing the th/ch/ph/dd cases :-(. Adding in the Regex call killed it
namespace System{class P{static void Main(string[]a){var x=a[0];if(!Text.RegularExpressions.Regex.IsMatch(x,"^[pct]h|^dd"))foreach(var r in"p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r".Split('-')){var b=r.Split('.');if(a[0].StartsWith(b[0]))for(int i=1;i<b.Length;)x+='\n'+b[i++]+a[0].Substring(b[0].Length);}Console.Write(x);}}}

Interesting note, never knew that you could omit the space between var r in"string"
Formatted:
namespace System
{
    class P
    {
        static void Main(string[] a)
        {
            var x = a[0];
            if (!Text.RegularExpressions.Regex.IsMatch(x, "^[pct]h|^dd"))
                foreach (var r in"p.b.mh.ph-t.d.nh.th-c.g.ngh.ch-b.f.m-d.dd.n-g..ng-m.f-ll.l-rh.r".Split('-'))
                {
                    var b = r.Split('.');
                    if (a[0].StartsWith(b[0]))
                        for (int i = 1; i < b.Length;) x += '\n' + b[i++] + a[0].Substring(b[0].Length);
                }
            Console.Write(x);
        }
    }
}

Perl 6, 162 bytes
{/^(.|<[cprt]>h|dd|ff|ng|ll)(.*)/;(%('p',,'t',<d nh th>,'c',<g ngh ch>,'b',<f m>,'d',
,'g',«'' ng»,'m',<f>,'ll',<l>,'rh',<r>){$0}//~$0).map(*~$1)}

Try it online!

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