[Question]
  [
I want to try a new type of regex golf challenge, which asks you to solve nontrivial computational tasks with nothing but regex substitution. To make this more possible and less of a chore, you will be allowed to apply several substitutions, one after the other.
## The Challenge
We'll start simple: given a string containing two positive integers, as decimal numbers separated by a `,`, produce a string containing their sum, also as as a decimal number. So, very simply
```
47,987
```
should turn into
```
1034
```
Your answer should work for arbitrary positive integers.
## The Format
Every answer should be a *sequence* of substitution steps, each step consisting of a regex and a replacement string. Optionally, for each of those steps in the sequence, you may choose to repeat the substitution until the string stops changing. Here is an example submission (which does *not* solve the above problem):
```
Regex    Modifiers   Replacement   Repeat?
\b(\d)   g           |$1           No
|\d      <none>      1|            Yes
\D       g           <empty>       No
```
Given the input `123,456`, this submission would process the input as follows: the first substitution is applied once and yields:
```
|123,|456
```
Now the second substitution is applied in a loop until the string stops changing:
```
1|23,|456
11|3,|456
111|,|456
111|,1|56
111|,11|6
111|,111|
```
And lastly, the third substitution is applied once:
```
111111
```
Note that the termination criterion for loops is whether the string changes, not whether the regex found a match. (That is, it might also terminate if you find a match but the replacement is identical to the match.)
## Scoring
Your primary score will be the number of substitution steps in your submission. *Every **repeated** substitution will count for **10** steps.* So the above example would score `1 + 10 + 1 = 12`.
In the (not too unlikely) case of a tie, the secondary score is the sum of the sizes of all steps. For each step add the regex (*without* delimiters), the modifiers and the substitution string. For the above example this would be `(6 + 1 + 3) + (3 + 0 + 2) + (2 + 1 + 0) = 18`.
## Miscellaneous Rules
You may use any regex flavour (which you should indicate), but all steps must use the same flavour. Furthermore, you must *not* use any features of the flavour's host language, like replacement callbacks or Perl's `e` modifier, which evaluates Perl code. All manipulation must happen exclusively through regex substitution.
Note that it depends on your flavour and modifiers whether each single replacement replaces all occurrences or only a single one. E.g. if you choose the ECMAScript flavour, a single step will by default only replace one occurrence, unless you use the `g` modifier. On the other hand, if you're using the .NET flavour, each step will always replace all occurrences.
For languages which have different substitution methods for single and global replacement (e.g. Ruby's `sub` vs. `gsub`), assume that single replacement is the default and treat global replacement like a `g` modifier.
## Testing
If your chosen flavour is either .NET or ECMAScript, you can use [Retina](https://github.com/mbuettner/retina) to test your submission (I'm being told, it works on Mono, too). For other flavours, you will probably have to write a small program in the host language which applies the substitutions in order. If you do, please include this test program in your answer.
  
[Answer]
# .NET flavor, score:2
```
Regex        Modifiers  Replacement  Repeat?
<empty>      <none>     9876543210   No
<see below>  x          <empty>      No
```
I'm not bothered to golf it yet, and `x` is just for ignoring whitespaces.
It firstly insert `9876543210` at each position, then delete the original characters and the characters those are not the current digit of the sum.
The big regex (1346 bytes without whitespaces and comments):
```
# If the length of the left number <= right number, delete every digit on the left.
.(?=.*,(?<=^(?<len>.)*,)(?<-len>.)*(?(len)(?!)))|
# Do the opposite if it is not the case.
.(?<=(?(len)(?!))(?<-len>.)*(?=(?<len>.)*$),.*)|
# Remove leading zeros.
(?<=(^|,).{9})0|
# Delete everything that is not the current digit of the sum.
.(?!
    # For digits in the left part:
    (?<cur>.){0,9}               # cur = the matched digit
    (?=(.{11})*,)                # and find the position before the next digit.
    (?<first>)                   # first = true
    (                            # Loop on the less significant digits:
        (?<cur>){10}             # cur += 10
        (?<=                     # cur -= the current digit in this number.
            (
                0|^|
                1(?<-cur>)|
                2(?<-cur>){2}|
                3(?<-cur>){3}|
                4(?<-cur>){4}|
                5(?<-cur>){5}|
                6(?<-cur>){6}|
                7(?<-cur>){7}|
                8(?<-cur>){8}|
                9(?<-cur>){9}
            )
            .{10}
        )
        (?=
            (?<pos>.{11})*,      # pos = which digit it is.
            .*$(?<=              # cur -= the current digit in the other number.
                (
                    0|,|
                    1(?<-cur>)|
                    2(?<-cur>){2}|
                    3(?<-cur>){3}|
                    4(?<-cur>){4}|
                    5(?<-cur>){5}|
                    6(?<-cur>){6}|
                    7(?<-cur>){7}|
                    8(?<-cur>){8}|
                    9(?<-cur>){9}
                )
                .{10}
                (?(pos)(?!))     # Assert pos = 0.
                                 # Skip pos input digits from the end.
                                 # But stop and set pos = 0 if the comma is encountered.
                ((?<-pos>\d{11})|(?<=(?>(?<-pos>.)*),.{10}))*
            )
        )
        (?(first)                # If first:
            (?>((?<-cur>){10})?) #  cur -= 10 in case there is no carry.
                                 #  Assert cur = 0 or 1, and if cur = 1, set cur = 10 as carry.
            (?(cur)(?<-cur>)(?(cur)(?!))(?<cur>){10})
            (?<-first>)          #  first = false
        |                        # Else:
                                 #  cur is 10 or 20 at the beginning of an iteration.
                                 #  It must be 1 to 11 to make the equation satisfiable.
            (?<-cur>)            #  cur -= 1
            (?(cur)              #  If cur > 0:
                                 #   cur -= max(cur, 9)
                (?(cur)(?<-cur>)){9}
                (?(cur)          #   If cur > 0:
                                 #    Assert cur = 1 (was 11) and set cur = 10.
                    (?<-cur>)(?(cur)(?!))(?<cur>){10}
                |                #   Else:
                    .*(?=,)      #    cur was 2 to 10, break from the loop.
                )
            )                    #  Else cur is 0 (was 1) and do nothing.
        )
        (.{11}|,)                # Jump to the next digit.
    )*(?<=,)(?(cur)(?!))         # End the loop if it is the last digit, and assert cur = 0.
|
    # Do the same to the right part. So the sum will be calculated two times.
    # Both are truncated to the original length of the number on that side + 1.
    # Only the sum on the longer side will be preserved in the result.
    (?<cur>\d){0,9}
    (?=(\d{11})*$)
    (?<first>)
    (
        (?<cur>){10}
        (?<=
            (
                0|,|
                1(?<-cur>)|
                2(?<-cur>){2}|
                3(?<-cur>){3}|
                4(?<-cur>){4}|
                5(?<-cur>){5}|
                6(?<-cur>){6}|
                7(?<-cur>){7}|
                8(?<-cur>){8}|
                9(?<-cur>){9}
            )
            .{10}
        )
        (?=
            (?<pos>.{11})*$
            (?<=
                (
                    0|^|
                    1(?<-cur>)|
                    2(?<-cur>){2}|
                    3(?<-cur>){3}|
                    4(?<-cur>){4}|
                    5(?<-cur>){5}|
                    6(?<-cur>){6}|
                    7(?<-cur>){7}|
                    8(?<-cur>){8}|
                    9(?<-cur>){9}
                )
                .{10}
                (?(pos)(?!))
                ((?<-pos>\d{11})|(?<=^.{10})(?=(?>(?<-pos>.)*)))*
                ,.*
            )
        )
        (?(first)
            (?>((?<-cur>){10})?)
            (?(cur)(?<-cur>)(?(cur)(?!))(?<cur>){10})
            (?<-first>)
        |
            (?<-cur>)
            (?(cur)
                (?(cur)(?<-cur>)){9}
                (?(cur)
                    (?<-cur>)(?(cur)(?!))(?<cur>){10}
                |
                    .*$(?<end>)
                )
            )
        )
        (.{11}|$(?<end>))
    )*(?<-end>)(?(cur)(?!))
)
```
This made me think of the final level of Manufactoria... But I think .NET regex, which is obviously no longer "regular", can solve any problems in PH. And this is just an algorithm in L.
[Answer]
### Score: 24
I think this works...
```
Regex                                                                                                                       Modifiers   Replacement             Repeat?
(?|(\d*)(\d)(,\d*)(\d)|(^,?\d*)(\d)|, |^,)                                                                                  <none>      $1$3 $2$4               Yes
$                                                                                                                           <none>      ;111111111234567890     No
0|(?|(;.*)|9(?=.*(1{9}))|8(?=.*(1{8}))|7(?=.*(1{7}))|6(?=.*(1{6}))|5(?=.*(1{5}))|4(?=.*(1{4}))|3(?=.*(111))|2(?=.*(11)))    g           $1                      No
 1{10}                                                                                                                      <none>      1                       Yes
 (?|1{9}(?=.*(9))|1{8}(?=.*(8))|1{7}(?=.*(7))|1{6}(?=.*(6))|1{5}(?=.*(5))|1{4}(?=.*(4))|1{3}(?=.*(3))|1{2}(?=.*(2))|)       g            $1                     No
 (?!\d)(?=.*(0))| |;.*                                                                                                      g           $1                      No
```
I haven't spent much time golfing the individual regular expressions yet. I will try to post an explanation soon, but it's getting late now. In the meantime, here's the result between each step:
```
'47,987'
' 9 48 77'
' 9 48 77;111111111234567890'
' 111111111 111111111111 11111111111111;111111111234567890'
'1  111 1111;111111111234567890'
'1  3 4;111111111234567890'
'1034'
```
Full perl program:
```
$_ = <>;
chomp;
do {
    $old = $_;
    s/(?|(\d*)(\d)(,\d*)(\d)|(^,?\d*)(\d)|, |^,)/$1$3 $2$4/;
} while ($old ne $_);
s/$/;111111111234567890/;
s/0|(?|(;.*)|9(?=.*(1{9}))|8(?=.*(1{8}))|7(?=.*(1{7}))|6(?=.*(1{6}))|5(?=.*(1{5}))|4(?=.*(1{4}))|3(?=.*(111))|2(?=.*(11)))/$1/g;
do {
    $old = $_;
    s/ 1{10}/1 /;
} while ($old ne $_);
s/ (?|1{9}(?=.*(9))|1{8}(?=.*(8))|1{7}(?=.*(7))|1{6}(?=.*(6))|1{5}(?=.*(5))|1{4}(?=.*(4))|1{3}(?=.*(3))|1{2}(?=.*(2))|)/ $1/g;
s/ (?!\d)(?=.*(0))| |;.*/$1/g;
print "$_\n";
```
[Answer]
### Any regex flavor, 41
```
    s/0/d/g
    ...
    s/9/dxxxxxxxxx/g
rep s/xd/dxxxxxxxxxxx/g
    s/[d,]//g
rep s/(^|d)xxxxxxxxxx/xd/g
    s/(^|d)xxxxxxxxx/9/g
    ...
    s/(^|d)x/1/g
    s/d/0/g
```
Let's try unary. `d` serves for a digit order separator, `x` stores the value. First we unarise each digit, then we squeeze the x10 multipliers to the left, then drop all separators, then back-insert the multipliers, then convert each order back to digits.
[Answer]
# .NET Regex, 14
Not as good as user23013's solution, but it was fun. None of the replacements have modifiers.
The reason for the .NET regex isn't because of balancing groups for once — I just tested with [Retina](https://github.com/mbuettner/retina), which uses .NET, and I also found that the variable length lookbehinds helped a lot.
## Replacement 1 (repeat = no)
Regex:
```
\d(?=\d+$)|\d(?=\d+,)|\d(?=,(\d+)$)|(?<=(\d+),\d*)\d$
```
Replacement
```
0$1$2
```
Swap the two numbers, padding to have the same number of leading zeroes.
## Replacement 2 (repeat = no)
Regex:
```
(\d+)
```
Replacement:
```
 $1
```
Add a space before each number
## Replacement 3 (repeat = no)
```
$
```
Replacement:
```
&0 ~00000 ~00101 ~00202 ~00303 ~00404 ~00505 ~00606 ~00707 ~00808 ~00909 ~01001 ~01102 ~01203 ~01304 ~01405 ~01506 ~01607 ~01708 ~01809 ~01910 ~02002 ~02103 ~02204 ~02305 ~02406 ~02507 ~02608 ~02709 ~02810 ~02911 ~03003 ~03104 ~03205 ~03306 ~03407 ~03508 ~03609 ~03710 ~03811 ~03912 ~04004 ~04105 ~04206 ~04307 ~04408 ~04509 ~04610 ~04711 ~04812 ~04913 ~05005 ~05106 ~05207 ~05308 ~05409 ~05510 ~05611 ~05712 ~05813 ~05914 ~06006 ~06107 ~06208 ~06309 ~06410 ~06511 ~06612 ~06713 ~06814 ~06915 ~07007 ~07108 ~07209 ~07310 ~07411 ~07512 ~07613 ~07714 ~07815 ~07916 ~08008 ~08109 ~08210 ~08311 ~08412 ~08513 ~08614 ~08715 ~08816 ~08917 ~09009 ~09110 ~09211 ~09312 ~09413 ~09514 ~09615 ~09716 ~09817 ~09918 ~10001 ~10102 ~10203 ~10304 ~10405 ~10506 ~10607 ~10708 ~10809 ~10910 ~11002 ~11103 ~11204 ~11305 ~11406 ~11507 ~11608 ~11709 ~11810 ~11911 ~12003 ~12104 ~12205 ~12306 ~12407 ~12508 ~12609 ~12710 ~12811 ~12912 ~13004 ~13105 ~13206 ~13307 ~13408 ~13509 ~13610 ~13711 ~13812 ~13913 ~14005 ~14106 ~14207 ~14308 ~14409 ~14510 ~14611 ~14712 ~14813 ~14914 ~15006 ~15107 ~15208 ~15309 ~15410 ~15511 ~15612 ~15713 ~15814 ~15915 ~16007 ~16108 ~16209 ~16310 ~16411 ~16512 ~16613 ~16714 ~16815 ~16916 ~17008 ~17109 ~17210 ~17311 ~17412 ~17513 ~17614 ~17715 ~17816 ~17917 ~18009 ~18110 ~18211 ~18312 ~18413 ~18514 ~18615 ~18716 ~18817 ~18918 ~19010 ~19111 ~19212 ~19313 ~19414 ~19515 ~19616 ~19717 ~19818 ~19919
```
Add a carry bit (the `&0`) as well as the giant lookup table of `<c> <a> <b> <carry of a+b+c> <last digit of a+b+c>`.
## Replacement 4 (repeat = yes)
Regex:
```
(?<=(\d),.*(\d)&)(\d)(?=.*~\3\1\2(.))|(\d)(?=,.*\d&)|(?<=\d,.*)(\d)(?=&)|^(?=.* .*(\d),.*(\d)&(\d).*~\9\7\8.(.))
```
Replacement:
```
$4$10
```
Keep taking the last digits of each number, and find their (sum, carry). Put the sum at the start of the string and replace the carry.
## Replacement 5 (repeat = no)
Regex:
```
^0*| .*
```
Replacement:
```
<empty>
```
Clean up.
# Example run
```
Repl no.        String
(input)         1428,57
1               000057,001428
2                000057, 001428
3                000057, 001428&0 <lookup table>
4               5 00005, 00142&1 <lookup table>
4               85 0000, 0014&0 <lookup table>
4               485 000, 001&0 <lookup table>
4               1485 00, 00&0 <lookup table>
4               01485 0, 0&0 <lookup table>
4               001485 , &0 <lookup table>
5               1485
```
---
(By combining a few of the steps I can get 12, but since it gets pretty messy and won't win anyway I think I'll keep this more elegant version up instead.)
[Answer]
**Score: ~~50~~ ~~40~~ ~~31~~ 21**
Thanks for this excellent challenge. This solution isn't very elegant, but, given the restrictions, I couldn't see any way to handle a digit generically in the output.
This solution features capture groups that sometimes don't match and relies on them being empty when that occurs. This works in Perl, though it normally produces a warning.
```
Regex 1:     (((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0                                            
Modifiers:   g
Replacement: <$1$2$3$4$5$6$7$8$9>             
Repeat:      no
Regex 2:     (.*)<(\d*)>(,.*)<(\d*)>|(.*)<(\d*)>(.*)|(?:(^[^<]*)b(\d*)c)?(b)\d{9}(\d)(\d*)(c)
Modifiers:   none 
Replacement: \8\1\5\3b$9$11\2\6\4c\7$10$12$13 
Repeat:      yes
Regexes 3-12: ,?baaaaaaaaac
Modifiers:    g
Replacement:  9 etc. (one for each digit)
```
Full Perl code sample, with explanation and printing of intermediate results:
```
no warnings;
use 5.16.0;
$_ = '47,987';
#Convert numbers to beans
s/(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0/<$1$2$3$4$5$6$7$8$9>/g;
say;
my $last;
#Combine pairs of digits, starting with least significant.
do {
    $last=$_;
    s/(.*)<(\d*)>(,.*)<(\d*)>|(.*)<(\d*)>(.*)|(?:(^[^<]*)b(\d*)c)?(b)\d{9}(\d)(\d*)(c)/\8\1\5\3b$9$11\2\6\4c\7$10$12$13/;
    say;
}
while ($last ne $_);
#Convert beans back to numbers.
s/,?b\d{9}c/9/g;
s/,?b\d{8}c/8/g;
s/,?b\d{7}c/7/g;
s/,?b\d{6}c/6/g;
s/,?b\d{5}c/5/g;
s/,?b\d{4}c/4/g;
s/,?b\d{3}c/3/g;
s/,?b\d{2}c/2/g;
s/,?b\d{1}c/1/g;
s/,?bc/0/g;
say;
```
*Update: I was able to combine two of the looping regexes together, saving 10.*
*Update 2: I managed to crack the input digit conversion with a single regex.*
*Update 3: I reduced to a single looping regex.*
]