text:
Decomposition of a matrix in \$ SL_2(\mathbb{Z}) \$
Background
The special linear group \$ SL_2(\mathbb{Z}) \$ is a multiplicative group of \$ 2 \times 2 \$ matrices whose elements are integers and determinant is 1.
It is known that every member of \$ SL_2(\mathbb{Z}) \$ is a product of some sequence of the following two matrices \$ S \$ and \$ T \$ (reference pdf):
$$
S=\begin{pmatrix}0 & -1\\1 & 0\end{pmatrix},T=\begin{pmatrix}1 & 1\\0 & 1\end{pmatrix}
$$
Note that \$ S^{-1} \$ and \$ T^{-1} \$ can also be expressed as a product of \$ S \$ and \$ T \$:
$$
S^{-1} = S^3, T^{-1} = S^3 \cdot T \cdot S \cdot T \cdot S
$$
Task
Given a \$ 2 \times 2 \$ integer matrix whose determinant is 1, express it as the product of a sequence of \$ S \$ and \$ T \$.
Note that there are infinitely many possible answers for any valid input. Your code needs to just output one answer for a valid input.
Example algorithm
Here is a sample algorithm to find a decomposition; you may use different algorithms to solve the task.
First, note that
$$
M = \begin{pmatrix} a & b \\ c & d \end{pmatrix} \implies
S^{-1}M = \begin{pmatrix} c & d \\ -a & -b \end{pmatrix},
T^{-1}M = \begin{pmatrix} a-c & b-d \\ c & d \end{pmatrix}
$$
Using these two operations, we can use Euclidean-like algorithm to reduce the given matrix down to \$ I \$, and then construct the chain backwards:

Assume \$ M = \begin{pmatrix} a & b \\ c & d \end{pmatrix} \$.
Left-multiply \$ S^{-1} \$ until both \$ a \$ and \$ c \$ are positive.
Repeat the following until we reach \$ c = 0 \$:

Left-multiply \$ T^{-q} \$ where \$ -c < a - qc \le 0 \$.
Left-multiply \$ S^{-1} \$ (exactly once). Now, \$a\$ and \$c\$ are positive again, and \$c\$ is smaller than the original.

Then the result is \$ \begin{pmatrix} 1 & b \\ 0 & 1 \end{pmatrix} \$, which is simply \$ T^b \$. (If \$ b < 0 \$, we can use \$ (SSSTSTS)^{-b} \$ instead.) Now invert all the left-multiplications to get the representation for the original matrix.

Here is an example for \$ M = \begin{pmatrix}17 & 29\\7 & 12\end{pmatrix} \$.
$$
T^{-3} M = \begin{pmatrix}-4 & -7\\7 & 12\end{pmatrix}
\\ S^{-1} T^{-3} M = \begin{pmatrix}7 & 12\\4 & 7\end{pmatrix}
\\ T^{-2} S^{-1} T^{-3} M = \begin{pmatrix}-1 & -2\\4 & 7\end{pmatrix}
\\ S^{-1} T^{-2} S^{-1} T^{-3} M = \begin{pmatrix}4 & 7\\1 & 2\end{pmatrix}
\\ T^{-4} S^{-1} T^{-2} S^{-1} T^{-3} M = \begin{pmatrix}0 & -1\\1 & 2\end{pmatrix}
\\ S^{-1} T^{-4} S^{-1} T^{-2} S^{-1} T^{-3} M = \begin{pmatrix}1 & 2\\0 & 1\end{pmatrix} = T^2
\\ M = T^3 S T^2 S T^4 S T^2
$$
Input and output
You can take the input matrix in any suitable way, e.g. a matrix, a 4-element vector, two complex numbers, etc. You can assume that the input is always valid, i.e. the four elements are integers and the determinant is 1.
The output is a sequence of two distinct values (or objects) that represent \$ S \$ and \$ T \$ respectively. All of the following are accepted (using an example output \$ STTS \$):
"STTS"  # string
"0110"  # digit string
[0, 1, 1, 0]  # array of 0s and 1s
['S', 'T', 'T', 'S']  # array of characters
[(0,-1,1,0), (1,1,0,1), (1,1,0,1), (0,-1,1,0)]  # array of tuples

Also, by definition of empty product, an empty sequence (e.g. "" or []) is a valid answer when the input is \$ I \$.
Scoring and winning criterion
Standard code-golf rules apply. Shortest code in bytes wins.
Example I/O
Note that every valid input has infinitely many correct answers, so your code's output may differ from the sample outputs shown here.
[[1 0]
 [0 1]] -> empty or SSSS or SSSTSTST or ...

[[0 -1]
 [1  0]] -> S

[[1 10]
 [0  1]] -> TTTTTTTTTT

[[17 29]
 [ 7 12]] -> TTTSTTSTTTTSTT

[[-1  -7]
 [-2 -15]] -> SSTSTTSTSSTTTTSSTTT

I feel like most of the solutions are going to brute force the order rather than follow the given algorithm. Not that that's a bad thing though, and I would be interested to see if the algorithm can be implemented more precisely than that

A harder test case: [ [-5, 14], [16, -45] ] -> STTTTSTTSTTSTTSTTTSTTSTS

What does your example algorithm do if after getting c=0, you have that b is negative, giving a negative power of T?

@Noodle9 1st question: "Left-multiply $ S^{-1} $" is the procedure, the rest is the description of what that step achieves. 2nd question: There are many possible answers, including yours and mine.

@xnor One possible solution would be to put -b copies of SSSTSTS since $ T^{-1} $ is precisely equal to that.

@Noodle9 Look at the worked example and see how the left column reduces from 17, 7 to 7, 4, 4, 1, and then 1, 0. Does it help? (The whole algorithm works like the Euclidean algorithm for finding GCD, just that it works on the left column of the matrix, and hitting a negative number before doing the "recursion".)

@Bubbler I'm also confused. If you start with a=1, c=4, don't you get q=1, giving you (1,4) -> (-3,4) -> (4,3)? I think this requires a particular ordering to count as "smaller", where you first sort by c.

@xnor Yes it does, but the seeming "increase" only happens once: 1,4 (T)-> -3,4 (S)-> 4,3 (T)-> -2,3 (S)-> 3,2 (T)-> -1,2 (S)-> 2,1 (T)-> 0,1 (S)-> 1,0. In general, it may happen at most once because a>c is guaranteed after one step. But you're right about the "smaller"; I'll edit the post to reflect the point.

@Noodle9 I tried to clarify the algorithm in the post. Does it look better for you?

@Bubbler I feel as if a dark and treacherous sky has cleared and bright happy sunshine is once again lighting up the world! Thanks :-)

Python, 67 bytes
g=lambda z,w:(z/w).real>0and'T'+g(z-w,w)or z+w*w and'S'+g(w,-z)or''

Try it online!
Thanks to Bubbler for cutting a byte
Takes input as two complex numbers for the rows. The idea is simple and easy-to-see on a less-golfed version:
def f(a,b,c,d):
 if (a,b,c,d)==(1,0,0,1): return ''
 elif a*c+b*d>0: return 'T'+f(a-c,b-d,c,d)
 else: return 'S'+f(c,d,-a,-b)

From \$ \begin{pmatrix} a & b \\ c & d \end{pmatrix}\$, we choose whether to apply \$S^{-1}\$ or  \$T^{-1}\$ based on a simple condition: whether \$ac+bd>0\$. Repeating this enough times takes any matrix to the identity.

Now that is how to use complex numbers for golfing.

67 bytes.

@Bubbler Nice one, thanks

JavaScript (ES6), 68 bytes
This is using xnor's method -- but obviously without complex numbers.
Takes the input matrix \$\begin{pmatrix}a&b\\c&d\end{pmatrix}\$ as 4 distinct parameters a,b,c,d.
Returns a string of digits (\$0\$ for \$S\$, \$1\$ for \$T\$).
f=(a,b,c,d)=>b|c|a-1|d-1?a*c>-b*d?1+f(a-c,b-d,c,d):0+f(c,d,-a,-b):''

Try it online!

JavaScript (ES6),  114 110  108 bytes
Takes the input matrix \$\begin{pmatrix}a&b\\c&d\end{pmatrix}\$ as a 4-element vector [a,b,c,d].
Returns a string of digits (\$0\$ for \$S\$, \$1\$ for \$T\$).
Brute forces a solution, which is guaranteed to be as short as possible, except for the identity matrix.
f=(M,i=0)=>(F=(a,b,c,d,s='')=>s[i]?a+[,b,c,d]==M&&s:F(a,a+b,c,c+d,s+1)||F(b,-a,d,-c,s+0))(1,0,0,1)||f(M,i+1)

Try it online!
Commented
f = (                      // f = wrapper function taking:
  M,                       //   M[] = input vector
  i = 0                    //   i   = maximum number of iterations (-1)
) => (                     //
  F = (                    // F is a recursive function taking:
    a, b, c, d,            //   the current matrix as 4 distinct parameters
    s = ''                 //   s = output string
  ) =>                     //
    s[i] ?                 // if we've reached the maximum length:
      a + [, b, c, d] == M //   if [a, b, c, d] matches the input matrix:
        && s               //     return s
    :                      // else:
      F(                   //   try a first recursive call
        a,                 //     where the matrix is multiplied by T
        a + b,             //     [ a b ]   [ 1 1 ]   [ a a+b ]
        c,                 //     [ c d ] x [ 0 1 ] = [ c c+d ]
        c + d,             //
        s + 1              //     append '1' to s
      ) ||                 //
      F(                   //   try a second recursive call
        b,                 //     where the matrix is multiplied by S
        -a,                //     [ a b ]   [ 0 -1 ]   [ b -a ]
        d,                 //     [ c d ] x [ 1  0 ] = [ d -c ]
        -c,                //
        s + 0              //     append '0' to s
      )                    //
)(1, 0, 0, 1)              // initial call to F with the identity matrix
|| f(M, i + 1)             // if it fails, try again with i + 1

APL (Dyalog Extended), 47 bytesSBCS
Anonymous tacit prefix function. Gives Boolean list with 0 and 1 meaning \$S\$ and \$T\$ respectively.
{⍺≡⊃+.×/(r←⊤⍵)⊇2 2∘⍴¨(0 ¯1 1)(1 1 0):r⋄⍺∇1+⍵}∘1

Try it online! (Faster edition emulating Extended in Unicode.)
{…}∘1 apply the following function with 1 and the given matrix as right and left arguments:
 (0 ¯1 1)(1 1 0) the list [[0,-1,1],[1,1,0]]
 2 2∘⍴¨ reshape each into a 2-by-2 matrix; [[[0,-1],[1,0]],[[1,1],[0,1]]]
 (…)⊇ select the following elements from that:
  ⊤ convert the right argument To base Two
  r← store that in r (potential result)
 +.×/ reduce using matrix multiplication (this also reduces the number of dimensions from 1 to 0)
 ⊃ disclose (the enclosure necessitated to reduce the number of dimensions)
 ⍺≡…: if the left argument (the target matrix) matches that, then:
  r return the result
 ⋄ else:
  1+⍵ increment the right argument
 ⍺∇ call self with same left argument and new right argument

05AB1E, 48  44  43 40 bytes
Crossed out  44  is no longer 44 :)
9bS[)DðýIk©d#¼vyDÁ0T·Sǝ+y2Å€(}2ôí˜]T¾ã®è

9bS and DÁ0T·Sǝ+ could alternatively be 9Yв/т1ª/тĆS/TºS and D2ôO13Sǝ/DÁ2Å€0}+ for the same byte-count.
Brute-force approach with pretty bad performance (it times out for the last three test cases - the previous 48;44;43 bytes versions only timed out for the last test case).
Input \$\begin{pmatrix}a&b\\c&d\end{pmatrix}\$ as a space-delimited string of four integers "a b c d".
Output as a string of 0s and 1s, where 0 is \$S\$ and 1 is \$T\$.
Try it online or verify a few test cases at once.
Explanation:
9bS                # Push 9, convert it to binary, and then to a digit-list: [1,0,0,1]
   [               # Start an infinite loop:
    )              #  Wrap all lists on the stack into a list
     D             #  Duplicate the current list of lists
      ðý           #  Join each inner list to a string with space delimiter
        Ik         #  Get the index of the input-string in this list
                   #  (the join is a work-around for lack of non-vectorizing index builtin)
          ©        #  Store it in variable `®` (without popping)
           d       #  Check if this index is non-negative (>= 0)
            #      #  And it it is: stop the infinite loop
    ¼              #  Increase the counter variable by 1
      v            #  Loop over each inner [a,b,c,d]-list `y`:
       yD          #   Push the list twice
         Á         #   Rotate the second one once towards the right: [a,b,c,d] → [d,a,b,c]
           T·S     #   Push 10 doubled as digit list: [2,0]
          0   ǝ    #   Insert a 0 at those (0-based) indices: [0,a,0,c]
               +   #   Add it to the earlier list: [a+0,b+a,c+0,d+c] → [a,b+a,c,d+c]
       y           #   Get the initial list [a,b,c,d] again
        2Å€ }      #   Apply to every 0-based 2nd item (so at indices [0,2]):
           (       #    Negate
             2ô    #   Split the list into parts of size 2: [-a,b,-c,d] → [[-a,b],[-c,d]]
               í˜  #   Reverse each, and flatten: → [[b,-a],[d,-c]] → [b,-a,d,-c]
   ]               # Close both the map and infinite loop
    T¾ã            # Take the cartesian product of 10 with the counter variable
                   #  i.e. 3 → ["111","110","101","100","011","010","001","000"]
       ®è          # And index variable `®` into this list
                   # (after which the result is output implicitly)

MATL, 42 38 32 bytes
`@B"@?FT!tqh}IlhB]]Nq:"Y*]G-z}@B

The code enumerates all finite sequences that begin with S, and stops when a solution is found. It is sufficient to test sequences beginning with S because S*S*S*S equals the identity matrix (inspiration from @Adam's APL solution).
Outputs a binary sequence, where 1 corresponds to matrix S and 0 to matrix T. The produced solution is the first in lexicographical order.
Try it online!

Python 3, 301 \$\cdots\$ 139 129 bytes
def f(a,b,c,d,l=''):
 while c:
  while 0>a or b<0:a,b,c,d=c,d,-a,-b;l+='S'
  if c:q=-a//c;a+=q*c;b+=q*d;l+='T'*-q
 return l+'T'*b

Try it online!
Saved 18 bytes thanks to Arnauld!!!
Takes the 4 matrix elements as separate numbers as input and outputs a string of 'S's and 'T's.

Jelly,  24  22 bytes
⁽¬Pb3’s2$⁺⁸ṃæ×/⁼
0ç1#B

A monadic Link accepting the target matrix which outputs a list containing a single list of 1s (\$S\$) and 0s (\$T\$).
As a full program a Jelly representation of this list is printed.
Always yields a resulting equation with a leading \$S\$ (except for an input of \$T\$ itself).
Note that since \$S^4=I\$ this is always possible.
Try it online! (very slow in general).
How?
Starts with i=0 and increments i while the binary representation of i with digits \$S\$ (1) and \$T\$ (0) does not have a matrix-product equal to the input, then returns the normal binary representation (using 1s and 0s).
⁽¬Pb3’s2$⁺⁸ṃæ×/⁼ - Link 1: integer, i; target matrix, M
⁽¬P              - literal 2831
   b3            - to base three    [1,0,2,1,2,2,1,2]
     ’           - decrement        [0,-1,1,0,1,1,0,1]
      s2$        - split into twos  [[0,-1],[1,0],[1,1],[0,1]]
         ⁺       - repeat that      [[[0,-1],[1,0]],[[1,1],[0,1]]]
          ⁸ṃ     - base-decompression of i
                 -     -> i in binary using digits 1=[[0,-1],[1,0]] and 0=[[1,1],[0,1]]
            æ×/  - reduce by matrix-multiplication
               ⁼ - is equal to M?

0ç1#B            - Main Link: 2-by-2 target matrix with determinant 1, M
0                - initialise the left argument, say i, to 0
  1#             - count up finding the first match under:
 ç               -   last Link (1) as a dyad - i.e. f(i, M)
    B            - convert to binary

Charcoal, 64 bytes
Ｗ∨§η⁰⊖§θ⁰¿‹⁰×§θ⁰§η⁰«TＵＭθ⁻κ§ηλ»«S≔±θι≔ηθ≔ιη»×TΠθ¿›⁰Πθ«SSS×TST±ΠθS

Try it online! Link is to verbose version of code. Based on the provided algorithm. Explanation:
Ｗ∨§η⁰⊖§θ⁰

Repeat while the first column is not [1, 0].
¿‹⁰×§θ⁰§η⁰

If the product of the first column is positive...
«TＵＭθ⁻κ§ηλ»

... then print a T and subtract the second row from the first row...
«S≔±θι≔ηθ≔ιη»

... otherwise print an S, and swap the rows, while negating the second row.
×TΠθ

If the product of the first row is positive then print that many Ts.
¿›⁰Πθ«

But if it is negative, then...
SSS×TST±ΠθS

... print SSS, the appropriate number of TSTs, and a final S.

Ruby, 96 bytes
->m{z=[['',1,0,0,1]];z.find{|a,q,w,e,r|z<<[a+?S,w,-q,r,-e]<<[a+?T,q,q+w,e,e+r];m==[q,w,e,r]}[0]}

Try it online!
Use the (brute) force.

Python 3, 193 192 191 bytes
Takes in a 2D numpy array and returns a string of S and T. Uses the algorithm in the question.
import numpy
def g(m,x=0):
 if m[1,0]==0:y=m[0,1];return['T','SSSTSTS'][y<0]*abs(y)
 while(m[:,0]<[1,0]).any():x+=1;m=[[0,1],[-1,0]]@m
 q=-m[0,0]//m[1,0];return'S'*x+'T'*-q+g([[1,q],[0,1]]@m)

Try it online!


text:
Average number of strings with Levenshtein distance up to 4
This is a version of this question which should not have such a straightforward solution and so should be more of an interesting coding challenge. It seems, for example, very likely there is no easy to find closed form solution, even though we have only increased the bound by one from the previous version. Having said that, you never know...
The Levenshtein distance between two strings is the minimum number of single character insertions, deletions, or substitutions to convert one string into the other one.  Given a binary string \$S\$ of length \$n\$, we are a interested in the number of different strings of length \$n\$ which have distance at most \$4\$ from \$S\$.
For example, if \$S = 0000\$ there are four strings with Levenshtein distance exactly \$3\$ from \$S\$, six with distance exactly \$2\$, four with distance exactly \$1\$ and exactly one with distance \$0\$. This makes a total of \$15\$ distinct strings with distance at most \$3\$ from the string \$0000\$. The only string with distance exactly \$4\$ is \$1111\$.
For this task the input is a value of \$n \geq 4\$. Your code must output the average number of binary strings of length \$n\$ which have Levenshtein distance at most \$4\$ from a uniform and randomly sampled string \$S\$.  Your answer can be output in any standard way you choose but it must be exact.
Examples

n = 4. Average \$16\$.
n = 5. Average 31 \$\frac{11}{16}\$.
n = 6. Average 61 \$\frac{21}{32}\$.
n = 7. Average 116 \$\frac{7}{8}\$.
n = 8. Average 214 \$\frac{43}{128}\$.
n = 9. Average 378 \$\frac{49}{246}\$.
n = 10. Average 640 \$\frac{301}{512}\$.
n = 11. Average 1042 \$\frac{1}{16}\$.
n = 12. Average 1631 \$\frac{1345}{2048}\$.
n = 13. Average 2466 \$\frac{3909}{4096}\$.
n = 14. Average 3614 \$\frac{563}{8192}\$

Score
Your score is the highest value of \$n\$ you can reach in less than a minute on my linux box.  If two answers get the same value then the first posted (or amended) wins. The timing is for each value separately.
My CPU is an Intel(R) Xeon(R) CPU X5460.

less than a minute on my linux box - how are we to access your box for testing? ssh? we'll need an account ...could we come on over to yours? T_T

@Noodle9 :) It's a standard thing for a [tag:fastest-code] competition to say what machine the testing will be done on.  You should also state when you answer what you get on your PC of course.

Doesn't this admit the same type of solution as the previous challenge, with a 25-state NFA instead of a 12-state NFA?

@Nitrodon I am not sure but the person who answered the previous question suggested it wasn't so simple in the comments.

@Nitrodon Hadn't thought about the concrete number before, but yes, 25 states should be correct

I see a DFA with 266 states, and a matrix with complex eigenvalues.

@ChristianSievers Fascinating! But what does it mean?

@Anush Closed formula contains trigonometric functions (or powers of complex numbers), or has to be written as depending on $n \mod k$ for, in this case, $k\in{3,4}$ (maybe not both are needed),

GAP
So my previous approach works indeed when we replace the definition of nfa with this:
nfa := Automaton("epsilon", 25, 5,
      [[[1,6,7],[2,8,9],[3,10,11],4,5,[6,18],
       [7,19],8,9,10,11,[8,22],[9,23],10,11,
       0,0,18,19,22,23,0,0,0,0],
      [[2,6,13],[3,8,15],[4,10,17],5,0,[8,18],
       [13,21],10,15,0,17,[6,22],[15,25],8,17,
       10,0,0,21,0,25,18,0,22,0],
      [[2,12,7],[3,14,9],[4,16,11],5,0,[12,20],
       [9,19],14,11,16,0,[14,24],[7,23],16,9,
       0,11,20,0,24,0,0,19,0,23],
      [[1,12,13],[2,14,15],[3,16,17],4,5,[14,20],
       [15,21],16,17,0,0,[12,24],[13,25],14,15,
       16,17,0,0,0,0,20,21,24,25],
      [0,0,0,0,0,3,3,4,4,5,5,3,3,4,4,5,5,10,
       11,16,17,10,11,16,17] ],
     [1], [1..25] );

This automaton was constructed with a program that I have explained here.
The resulting DFA has 266 states.
We can again compute as much values as we like:
n = 16. Average = 7150 23011/32768.
n = 17. Average = 9714 60059/65536.
n = 18. Average = 12940 42919/131072.
n = 19. Average = 16935 3985/8192.
n = 20. Average = 21817 225447/524288.
n = 21. Average = 27711 716517/1048576.
n = 22. Average = 34752 552357/2097152.
n = 23. Average = 43081 714481/1048576.
n = 24. Average = 52850 7923401/8388608.
n = 25. Average = 64219 9352665/16777216.
n = 50. Average = 1508800 387601224486599/562949953421312.
n = 100. Average = 29267070 38719469213378154341013566355/
633825300114114700748351602688.

The eigenvalues of the matrix are \$4,2,1,0\$ and \$-1\$ as before and additionally two conjugate pairs of complex numbers: \$\pm i\$, and the third root of unity and its conjugate (which is also its square and its inverse).
Usually complex eigenvalues mean that the closed formula contains trigonometric functions, but since there were already terms corresponding to the eigenvector \$1\$ to compensate, I took the liberty to use the periodic functions \$ n \bmod 3\$ and \$ -n \bmod 3\$ to handle the third root of unity.
The imaginary unit does not contribute to the closed formula. Neither does \$4\$, because it comes from the sink state, which is not counted. It can be removed from the automaton, and the resulting matrix no longer has this eigenvalue. The eigenvalue \$-1\$ does contribute, even though it didn't in the distance 3 case.
The resulting closed formula, which is quite long, works for \$n\ge 5\$. (That's an effect of the \$0\$ eigenvalues.) Since the challenge asks for \$n\ge 4\$, the following code has a special case for small values.
Pari/GP
f(n)=if(n>4,168264301/345744-4115011/16464*n+19597/336*n^2-161/24*n^3+17/48*n^4+(-9188617/19208-268724/3087*n-4658/441*n^2+449/81*n^3-515/324*n^4+(-1)^n/72+(56188/194481-824/9261*n+4/3969*n^2)*(n%3)+(-1756/64827+94/27783*n-26/3969*n^2)*(-n%3))*2^-n,2^n)

Try it online!

Wow!  I hope this answer is awarded a prize at some point.  I am really looking forward to the math.SE answer as I would love to fully understand the steps needed. How much can be automated so we can try it with any values of $k$?

source: Stack Exchange

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

sort: votes


text:
99 ways to say "I love you"
Inspired by this blog post.
Write a program that outputs 99 distinct programs (in the same language) that output the string I love you.
How the programs are separated from one another in the output will be defined by you. However, Each byte of output can only belong to at most 1 of the 99 programs.
Constraints for Output Programs

If any string of characters is removed, then the program must not output I love you.
e.g. console.log('I love you');;; is invalid because ;;; can be removed
If any two strings of characters are both removed, then the program must not output I love you. This is to prevent inconsequential application of pairs of characters, that pass rule 1 because removing any single string will break the program.
e.g. print((('I love you'))) is invalid, because (( and )) can be removed

There will be two categories of scoring to participate in.

Standard code golf—smallest source code wins
Combined code golf—smallest source code + output wins

Leaderboard
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

/* Configuration */

var QUESTION_ID = 198052; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 48934; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];

  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '
' + c.body.replace(OVERRIDE_REG, '') + '
';
    });

    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });

  });

  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;

    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    if (/ b.lang) return 1;
    if (a.lang < b.lang) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}

<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">

Leaderboard

	Author	Language	Size

Winners by Language

Language	User	Score

{{PLACE}}	{{NAME}}	{{LANGUAGE}}	{{SIZE}}	Link

{{LANGUAGE}}	{{NAME}}	{{SIZE}}	Link

Does the code have to be pristine (there is no way to produce the same result by removing any number of characters) or just following the constraints you mentioned? e.g. from Benji's program: would print(chr(207%134)) ... be allowed even if taking out 20, %1, and 4 would result in print(chr(73)) ... which yields the same result?

Can we use functions instead of programs?

There must not exist a string of characters that, when removed, does not lead to Could that be rephrased to remove the two negations? I find it very confusing

@Zimonze just the rules above. In your example, it takes the removal of 3 strings of characters to be reduced, so it's still valid.

@LuisMendo I wrestled with the wording for this a decent amount, it seems to really want to be a double negative and that was the best wording I came up with. I'm open to suggestions (from anyone).

These double negatives are killing my chance at understanding this question. Could this be reworded without the double negatives?

Perhaps try: "Your solution must fail to output I love you if you remove any one or two strings of characters. Removal of 3 or more strings of characters is not required to fail.". Then just copy the two examples.

Isn't this a [tag:metagolf] challenge?

I don't understand the rule However, Each byte of output can only belong to at most 1 of the 99 programs.. Can you clarify what you mean by that?

@AdmBorkBork, I guess Mason tried to disallow solutions where there is 1 function declaration + 99 function calls. With the rule you quoted that would be counted 99 function declarations + 99 function calls, cutting the benefit of using such cheatish combination.

"How the programs are separated from one another in the output will be defined by you." Can be we have no separator? The output still contains all programs.

@KevinCruijssen That seems to be how most answers are doing it, so it must be allowed

@KevinCruijssen you can do whatever you want as long as you can show where each program starts and ends

So each output program must consist of only 2.55 distinct bytes, on average? That's less than are in the "I love you" string itself.

@user253751 If you look at the answers that's clearly not the case. Where are you getting that number from?

@Mason I bet that number comes from a misreading of “Each byte of output can only belong to at most 1 of the 99 programs”, and frankly I also have no idea what that rule means. Could you please clarify?

@Lynn It seems to mean that when the output is split up into programs no byte of output can be given to two programs, e.g. abcc cannot have both the programs abc and cc since the third byte belongs to two programs.  It can much more clearly be said as programs do not overlap.

JavaScript (JavaScript shell), 65 bytes
total: (64 + 3366 = 3450) bytes
for(i=99;i++<198;)print(`\\u0${i}="I love you";print(\\u{${i}})`)

\u0100="I love you";print(\u{100})
\u0101="I love you";print(\u{101})
\u0102="I love you";print(\u{102})
\u0103="I love you";print(\u{103})
\u0104="I love you";print(\u{104})
\u0105="I love you";print(\u{105})

It is trivial.
JavaScript allow escape sequence in variable name. console.lo\u0067('Hello world') is prefect valid. I don't think this feature is useful anyway. But...
No TIO link, since the TIO version is out-of-date. You may download JavaScript Shell from https://archive.mozilla.org/pub/firefox/releases/72.0.1/jsshell/ .

JavaScript (SpiderMonkey), 76 bytes
total: (76 + 2475 = 2551) bytes
for(i=99;i++<198;print(v+'="I love you";print('+v+')'))v=eval('"\\u0'+i+'"')

Try it online!
Output:
Ā="I love you";print(Ā)
ā="I love you";print(ā)
Ă="I love you";print(Ă)
ă="I love you";print(ă)
Ą="I love you";print(Ą)
ą="I love you";print(ą)

This one is shorter when counting total length. And it is much more trivial.

JavaScript (SpiderMonkey), 85 bytes
total: (86 + 36927 = 37013) bytes
for(n=99,p="(L='I love you')=>",q="print(L)";n--;p+='x=>')p='('+p,q+=')()',print(p+q)

Try it online!
Output:
((L='I love you')=>print(L))()
(((L='I love you')=>x=>print(L))())()
((((L='I love you')=>x=>x=>print(L))())())()
(((((L='I love you')=>x=>x=>x=>print(L))())())())()
((((((L='I love you')=>x=>x=>x=>x=>print(L))())())())())()

This is my original solution.

TIL SpiderMonkey has a print function

What's wrong with this 56 byter

Note that your 86 bytes solution produces 100 programs, you can cut 1 byte using 99 (and that would remove this horrific longest last line)

@ExpiredData _XY="I love you";print(_XY) can be reduced to _X="I love you";print(_X).

Ah I see thanks @arnauld

What I meant is that the output programs are not pristine because the \ can be removed (e.g. u0100="I love you";print(u0100)).

@Arnauld Ah, nice catch. Fixed by +1 byte (and switching to newer version.

Whitespace, 718 bytes, score: 34180 (33462+718)
[S S S T    N
_Push_1][S S S N
_Push_n=0][T    T   S _Store_1:n][N
S S S N
_Create_Label_LOOP][S S S T N
_Push_1][S N
S _Dupe_1][T    T   T   _Retrieve_1:n][T    S S S _Add][S N
S _Dupe_n+1][S S S T    T   S S T   S S N
_Push_100][T    S S T   _Subtract][N
T   S T T   N
_If_0_Jump_to_Label_EXIT_WITH_PRINT][S S S T    N
_Push_1][S N
T   _Swap][T    T   S _Store_1:n+1][S S S T N
_Push_1_newline][S N
S _Dupe_1_newline][S S S T  S T T   T   N
_Push_23_space][S S S T N
_Push_1_newline][S T    S S T   N
_Copy_0-based_1st_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S S S N
_Push_0_tab][S T    S S T   S N
_Copy_0-based_2nd_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][S T    S S T   N
_Copy_0-based_1st_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][N
S T N
_Call_Subroutine_PUSH_INTEGER][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][N
S T N
_Call_Subroutine_PUSH_INTEGER][S S S T  N
_Push_1_newline][S S S T    S T T   T   N
_Push_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S N
S _Dupe_1_newline][S T  S S T   S N
_Copy_0-based_2nd_23_space][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S T  S S T   S N
_Copy_0-based_2nd_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S T  S S T   S N
_Copy_0-based_2nd_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S T    S S T   N
_Copy_0-based_1st_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][S T    S S T   N
_Copy_0-based_1st_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][S T    S S T   N
_Copy_0-based_1st_23_space][S S S T N
_Push_1_newline][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][S T  S S T   S S N
_Copy_0-based_4th_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S T    S S T   N
_Copy_0-based_1st_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][S T  S S T   S S N
_Copy_0-based_4th_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S T    S S T   N
_Copy_0-based_1st_23_space][S S S N
_Push_0_tab][S T    S S T   N
_Copy_0-based_1st_23_space][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S T  S S T   S N
_Copy_0-based_2nd_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][S T  S S T   S T N
_Copy_0-based_5th_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S T  S S T   S N
_Copy_0-based_2nd_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S T    S S T   N
_Copy_0-based_1st_23_space][S S S N
_Push_0_tab][S T    S S T   N
_Copy_0-based_1st_23_space][S S S N
_Push_0_tab][S T    S S T   N
_Copy_0-based_1st_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S T    S S T   N
_Copy_0-based_1st_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S S S T   N
_Push_1_newline][S T    S S T   N
_Copy_0-based_1st_23_space][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S T  S S T   S N
_Copy_0-based_2nd_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][S T  S S T   T   N
_Copy_0-based_3rd_23_space][S N
S _Dupe_23_space][S S S N
_Push_0_tab][N
S T N
_Call_Subroutine_PUSH_INTEGER][S S S T  N
_Push_1_newline][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][S N
S _Dupe_0_tab][S S S T  S T T   T   N
_Push_23_space][S S S N
_Push_0_tab][S N
S _Dupe_0_tab][S T  S S T   S N
_Copy_0-based_2nd_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][N
S T N
_Call_Subroutine_PUSH_INTEGER][N
S N
S N
_Jump_to_Label_LOOP][N
S S T   T   N
_Create_Label_EXIT_WITH_PRINT][S N
N
_Discard_n][N
S S T   N
_Create_Label_PRINT_LOOP][S S S T   S S T   N
_Push_9][T  S S S _Add][T   N
S S _Print_as_character][N
S N
T   N
_Jump_to_Label_PRINT_LOOP][N
S S N
_Create_Subroutine_PUSH_INTEGER][S S S T    N
_Push_1_newline][S S S N
_Push_0][S S S T    N
_Push_1][T  T   T   _Retrieve_1:n][T    T   S _Store_0:m][N
S S S S N
_Create_Label_TAB_LOOP][S S S N
_Push_0_tab][S N
S _Dupe_0][S N
S _Dupe_0][T    T   T   _Retrieve_0:m][S S S T  N
_Push_1][T  S S T   _Subtract][S N
S _Dupe_m-1][N
T   S S T   N
_If_0_Jump_to_Label_DONE_WITH_TAB_LOOP][T   T   S _Store_0:m-1][N
S N
S S N
_Jump_to_Label_TAB_LOOP][N
S S S T N
_Create_Label_DONE_WITH_TAB_LOOP][S S S T   S T T   T   N
_Push_23_space][S N
S _Dupe_23_space][S N
S _Dupe_23_space][N
T   N
_Return_from_Subroutine_PUSH_INTEGER]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.
Try it online (with raw spaces, tabs and new-lines only).
The output Whitespace programs are output without delimiter. Each program will be as follows, where the x is variable in the range [3,102].
[S S S (x_amount_of_T   )N
_Push_n][S S S T    T   S T T   T   T   N
_Push_constant_111][S S S (x_amount_of_T    )N
_Push_n][T  S S T   ][T T   S _store][S S S T   T   S N
_Push_6_u][S S S N
_Push_0_o][S S S T  S T S N
_Push_10_y][S S T   T   S S T   T   T   T   N
_Push_-79_space][S S T  T   S T S N
_Push_-10_e][S S S T    T   T   N
_Push_7_v][S S S N
_Push_0_o][S S T    T   T   N
_Push_-3_l][S T S S T   S S N
_Copy_0-based_4th_-79_space][S S T  T   S S T   T   S N
_Push_-38_I][N
S S N
_Create_Label_LOOP][S S S (x_amount_of_T    )N
_Push_n][T  T   T   _Retrieve][S S S (x_amount_of_T )N
_Push_n][T  S S S _Add][T   S S S _Add][T   N
S S _Print_as_character][N
S N
N
_Jump_to_Label_LOOP]

In the 1st program, x will be 3, so the four Push n parts will push the integer 7 (binary 111; three 1-bits); in the 15th program, x will be 18, so the four Push n parts will push the integer 262143 (binary 111111111111111111; eighteen 1-bits); etc. up to 5070602400912917605986812821503 (binary with 102 1-bits).
Try it online for the 15th program (with raw spaces, tabs and new-lines only).
I've used this Whitespace tip of mine to print the output I love you. The optimal constant 111 is generated by this Java program. In addition, I use one copy for the space to save bytes.
I've also used this same tip with a constant 9 in the generator program to output the Whitespace sub-programs. After that I've used loads of duplicates, as well as copies for the spaces where possible.
Explanation in pseudo-code:
Generator program:
Store n=0 at heap-address 1
Start LOOP:
  Retrieve n from heap-address 1
  n = n + 1
  If(n == 100):
    Call function EXIT_WITH_PRINT
  Store the updated n+1 at heap-address 1
  Push the codepoints of "NNSNSSNTSSSTSSST" minus 9 for the output program
  Call subroutine PUSH_INTEGER
  Push the codepoints of "TTT" minus 9 for the output program
  Call subroutine PUSH_INTEGER
  Push the codepoints of "NSSNNSTTSSTTSSNSSTSSTSNTTTSSNSSSNTTTSSSNSTSTTSSNTTTTSSTTSSNSTSTSSSNSSSNSTTSSSSTTTSST" minus 9 for the output program
  Call subroutine PUSH_INTEGER
  Push the codepoints of "NTTTTSTTSSS" minus 9 for the output program
  Call subroutine PUSH_INTEGER
  Go to the next iteration of LOOP

Function EXIT_WITH_PRINT:
  Discard n that was still on the top of the stack
  Start PRINT_LOOP:
    Add 9 to the value at the top of the stack
    Pop and print it as character
    (this will fail with an error since there is nothing more to pop, when we're done with
     the final character to stop the program)
    Go to the next iteration of PRINT_LOOP

Subroutine PUSH_INTEGER:
  Push the codepoint of "N" minus 9 for the output program
  Retrieve n from heap-address 1
  Integer m = n
  Store m at heap-address 0
  Start TAB_LOOP:
    Push the codepoint of "T" minus 9 for the output program
    Retrieve m from heap-address 0
    m = m - 1
    If(m == 0):
      Call function DONE_WITH_TAB_LOOP
    Store m-1 at heap-address 0
    Go to next iteration of TAB_LOOP

  Function DONE_WITH_TAB_LOOP:
    Push the codepoints of "SSS" minus 9 for the output program
    Return to the caller of the PUSH_INTEGER subroutine, and continue from there

Sub-program:
Variable as explained before is integer n (which has x amount of binary 1-bits).
Integer t = 111 - n
Store t at heap-address n
Push the codepoints of "uoy evol I" minus 111
Start LOOP:
  Retrieve t from heap-address n
  t = t + n
  Add t (which is 111 again) to the value at the top of the stack
    Pop and print it as character
    (this will fail with an error since there is nothing more to pop, when we're done with
     the final character to stop the program)
    Go to the next iteration of LOOP

Since we use the variable n four times (t = 111-n; store t at heap-address n; retrieve t from heap-address n; t = t+n) with other pieces of relevant code in between the pushes, we need to remove four string-sequences in order to still have a valid I love you output, complying to the rule stating you can't remove one or two string-sequences.

JavaScript (Node.js), 81 bytes
Output: 4275 bytes
for(n=100;--n;)console.log(`console.log('I lo'+Buffer([${n}^${118^n}])+'e you')`)

Try it online!

Batch, 131 + 3564 bytes
@for %%a in (a b c d e f g h i j k)do @for %%b in (. / \ "," ";" [ ] + "=")do @echo @for %%%%%%a in (love)do @echo%%~bI %%%%%%a you

This produces 99 variants of the same code:
@for %%k in (love)do @echo=I %%k you

The for variable (here k) loops over the 11 values a to k, while the other character that changes is the separator after echo, which can usually (as here) be any of 11 characters, but five of them need quoting to use in a for command, so I've omitted space and (. The programs are all irreducible because they need to get the word love to appear in the output.

? @for /L %k in (1 1 99) do @echo @set a%k=I love you^&^&echo %a%k%

@mazzy That doesn't produce irreducible programs.

@mazzy Additionally, the programs don't even work since variable expansion happens at parse time by default.

Python 3, 86 bytes

86 code + 10289 output = 10375 total
x=0
while x<99:print(f"print(chr(len('{(bin(x)[2:8]).zfill(73)}'))+' love you')");x+=1

sample segment of output:

print(chr(len('0000000000000000000000000000000000000000000000000000000000000000000110000'))+' Love you')

@Arnauld It does... I'll see if I can fix that

You might want to look carefully at the first line of your sample segment of output... There are two strings which can be removed to leave 73 in the char().

There is also 100-90 which can be simply 10.

I think I have finally made it so that if any character(s) are removed, it will break.(I'm new to code-golf, so thanks for the help)

This currently outputs only 98 programs. Suggested 77-byte version, with a shorter output.

This solution is expandable all the way until needing to output 9444732965739290427392 different programs. Awesome!

@Arnauld you can save byte in your shortened solution by using x=16 and x<115 which is addition of 2 characters. But you get to remove +16 so you net save 1 character

@Arnauld Another 2 bytes savings by removing the parens around hex(x)

{(bin(x)[2:8]).zfill(73)} -> {bin(x)[2:].zfill(73)} save 3 bytes

Love should not be capitalised

C (clang), 87 \$\cdots\$ 160 120 bytes
Output: 3822 bytes (Total: 3942 bytes)
i;main(j){for(;i<99;printf("main(){printf(\"%%c Love You\",%d^%d);}\n",j,j^73))j=3+i++*4,j=strchr("$,2MOPW]_",i)?6*j:j;}

Try it online!
Fixed pristine-errors kindly pointed out by Expired Data.
Fixed pristine-errors kindly pointed out by Kaddath.
Saved 50 bytes thanks to gastropner!!!
Prints 99 unique lines like:
main(){printf("%c Love You",3^74);}

PHP, 96 bytes
Output: 2516 bytes (total 2612)
<?php for(;($i+=2)<773;)if($i<99||--$i%100>67&&$i>299)echo"I<?=chr(".(33+$i++)."-$i)?>love you";

Try it online!
Example program:
I<?=chr(35-3)?>love you

Still quite new at code golf, hope I get this right. Wanted to encode the space as 32 is the lowest number and wanted to do something else than port an existing answer. Got me into troubles with the 2 strings removing part, but I think this time it passes
(Edit: one line was missing, programs count was 98)
(Edit2: separator is now :, as - was in the code, and total count was wrong)
Edit3: This time I think it's OK (got much more complicated than planned):

I had to remove all the intervals of the form x99-x67 that can be reduced by removing the x's
Had also to remove all the interval of the form 3xx-2xx that can be reduced by removing the xx- and xx
Tried to keep only --$i%100>67&&$i>299 as a condition but unfortunately it goes to 1003-971 and a bit beyond that all can be reduced to the form 103-71
new code is manupulating $i with -- and ++ to avoid to add prenthesis and do ($i-1)%100>67 in test and "-".($i-1).") in display
no separator anymore, as per a question's comment
removed the space after echo (thanks to @Ismael Miguel answer)

05AB1E, 23 bytes (combined score 1688 bytes)
тGN"•«À¢ÒÙΓʒγ•"тN-…O₃BJ

Try it online! or try one of the output programs.
тG                       # for N from 1 to 99:
  N                      #  N
   "•«À¢ÒÙΓʒγ•"          #  string "•«À¢ÒÙΓʒγ•"
               тN-       #  100 - N
                  …O₃B   #  "O₃B"
                      J  #  join the entire stack

Each subprogram looks like:
1                       # 1 (N)
 •«À¢ÒÙΓʒγ•             # compressed integer 11971423964735158206
           99           # 99 (100 - N)
             O          # sum the entire stack
              ₃B        # convert to base 95

@downvoter care to explain what's wrong with this answer?

Keg, 33 bytes
Programs separated by :
Output is 1385 bytes

в&(c|&:&I+,&:&,`- love you:`,⑹

Try it online!
Programs:

ѻв- love you:Ѽг- love you:ѽд- love you:Ѿе- love you:ѿж- love you:Ҁз- love you:ҁи- love you:҂й- love you:҃к- love you:҄л- love you:҅м- love you:҆н- love you:҇о- love you:҈п- love you:҉р- love you:Ҋс- love you:ҋт- love you:Ҍу- love you:ҍф- love you:Ҏх- love you:ҏц- love you:Ґч- love you:ґш- love you:Ғщ- love you:ғъ- love you:Ҕы- love you:ҕь- love you:Җэ- love you:җю- love you:Ҙя- love you:ҙѐ- love you:Қё- love you:қђ- love you:Ҝѓ- love you:ҝє- love you:Ҟѕ- love you:ҟі- love you:Ҡї- love you:ҡј- love you:Ңљ- love you:ңњ- love you:Ҥћ- love you:ҥќ- love you:Ҧѝ- love you:ҧў- love you:Ҩџ- love you:ҩѠ- love you:Ҫѡ- love you:ҫѢ- love you:Ҭѣ- love you:ҭѤ- love you:Үѥ- love you:үѦ- love you:Ұѧ- love you:ұѨ- love you:Ҳѩ- love you:ҳѪ- love you:Ҵѫ- love you:ҵѬ- love you:Ҷѭ- love you:ҷѮ- love you:Ҹѯ- love you:ҹѰ- love you:Һѱ- love you:һѲ- love you:Ҽѳ- love you:ҽѴ- love you:Ҿѵ- love you:ҿѶ- love you:Ӏѷ- love you:ӁѸ- love you:ӂѹ- love you:ӃѺ- love you:ӄѻ- love you:ӅѼ- love you:ӆѽ- love you:ӇѾ- love you:ӈѿ- love you:ӉҀ- love you:ӊҁ- love you:Ӌ҂- love you:ӌ҃- love you:Ӎ҄- love you:ӎ҅- love you:ӏ҆- love you:Ӑ҇- love you:ӑ҈- love you:Ӓ҉- love you:ӓҊ- love you:Ӕҋ- love you:ӕҌ- love you:Ӗҍ- love you:ӗҎ- love you:Әҏ- love you:әҐ- love you:Ӛґ- love you:ӛҒ- love you:Ӝғ- love you:ӝҔ- love you:

To my understanding, separator : isn't count into the byte count. So, output should be count as 1385 bytes.

05AB1E, 34 31 30 28 25 bytes
Combined Score: very very big (25 + no. permutations of "I love you"*20)
-3 bytes thanks to @KevinCruijssen
…I„Î€îœ¦v'"y'""œ{•B‹<•è"J

Try it online!

Optimised for Combined Score
05AB1E, 32 30 27 bytes
Combined Score: 27 + 1980 = 2007
…I„Î€îœт£¦v'"y'""œ{•B‹<•è"J

Try it online!
This may take a while to run...

Explanation
…I„Î€î                       # Compressed string "I love you"
      œ                      # Get the permutations of this string
       ¦                     # Remove the first one ("I love you")
        v                    # loop over these and do...
         '"y'"               # the string with the value in (e.g. "I love yuo"
              "œ{•B‹<•è"     # string literal with œ{•B‹<•è value
                        J    # join these and print e.g. "I love yuo"œ{•B‹<•è

Explanation of the output programs:
"I love yuo"                   # a string which is a permutation of "I love you"
            œ{                 # get the sorted permutations of this string
              •B‹<•è           # get the value at index 750832 which is "I love you"

One of the output can be reduced.

Doesn't the second one produce much more than 99 programs?

I trust you, knowing nothing about 05AB1E, but I get a huge list and "The output exceeded 128 KiB and was truncated" with the TIO link

@Kaddath should be fixed now

still pretty much chinese to me :D (no offense to them) but yep, that works!

@kaddath added an explanation hope that is useful

“€í„Î€î“ can be …I„Î€î (also fixes the lowercase i to uppercase I in the sentence)

^ You may need to fix the index integer, since the sorted permutations might be in a different order due to the uppercase I.

Good point and thanks @KevinCruijssen

The first program is invalid, since 1) it outputs more than 99 programs 2) not all output programs are distinct as required. 1) can be fixed by doing тLè instead of ¦, 2) can be solved by adding Ù after œ. TIO (note that it now loses to the second program in individual score, but beats it in combined score. also the indices are wrong now, my bad).

@Grimmy Well it does output 99 programs.. it just then goes on to output more, as far as I'm concerned that meets the challenge criteria... And yes second one I will fix.

@ExpiredData no it obviously doesn’t meet the spec. If that kind of thing was allowed, you could just enumerate all strings and argue that the answer is somewhere in there. (Also, regardless of spec-compliance, changing it to output only 99 programs gives a better combined score than your current “optimized for combined score” answer).

@Grimmy whatever there's a clear difference between your ridiculous example and this.

Ruby, 200 181 172 165 + 3992 3828 3540 bytes
m="I love you";q=?",?';%w[print $><< puts].map{|e|q.product(q){|c,d|8.times{|i|puts e+c+"#{m.chars.rotate(~i)*""}#{c}.chars.rotate(#{i+1})*#{d*2}"}};puts e+"'#{m}'"}

This combines different ways of printing (print, $stdout <<, puts), different ways of quoting the string ('', ""), and different rotations of the string "I love you" to make (((8 * 4) + 1) * 3) = 99 irreducible programs.
Golfy Tricks

Uses %w[] as a whitespace-separated string array
Use *"" and *'' instead of .join
Use different combinations of quotation marks ("", '') instead of different combination of splitting a string (chars, split(//)), and just use the shorter (chars)
Use puts instead of $stdout<< as the third way of printing (I didn't think it would be allowed because it also appends a newline where the others don't, but maybe this is fine?)

Try it online! for the initial generator code.
Try it online! for the generated code.
This now has some "I love you"s appended with a newline, and some not. I hope this is okay.
EDIT: Saved lots of even more bytes thanks to Value Ink!

Ruby, 53 + 2375 bytes
This is the cheap way of using a unicode range as variable names.
(?ÿ..?š).each{|v|puts"#{v}='I love you';puts #{v}"}

Try it online! for the generator code.
Try it online! for the generated code.

Replace the $stdout<< version of printing with puts for some byte saves; I'm pretty sure the trailing newline isn't a problem for the challenge. Also .join to *"". 2) Use %w notation for your arrays, for example %w(print $><< puts) saves lots of bytes over ['print','$><<','puts']. 3) Use 8.times and modify i as necessary instead of doing if i>0: -i becomes ~i, and #{i} becomes #{i+1}.

I also meant you should change .join to *"" in your array... %w[.join *''] becomes %w[*"" *''] which you can golf further to %w["" ''] if you do *#{d}. Also, map is better than each in 99% of cases

Oh yeah, I didn't think of mixing up the quotation marks!

I can also swap out the %w[chars split(//)] with different quotation marks around the string.

Since it's come to you using the quotation marks for both parts: q=?",?';q.product(q) then *"+d*2 works. Also, you can do puts e+c+"#{m.... instead of interpolating, since they're just basic strings!

PowerShell, 63 + 3167 = 3230
1..99|%{$z=$_%10;"''+(echo you $($_-$z)/10) love $z I)[4,2,0]"}

Try it online!
Sample output:
''+(echo you 0 love 1 I)[4,2,0]
''+(echo you 0 love 2 I)[4,2,0]
...
''+(echo you 1 love 0 I)[4,2,0]
''+(echo you 1 love 1 I)[4,2,0]
''+(echo you 1 love 2 I)[4,2,0]
...
''+(echo you 9 love 8 I)[4,2,0]
''+(echo you 9 love 9 I)[4,2,0]

PowerShell, 2575 = 101 + 2474
Inspired by Jo King's answer for Perl.
Minimal total output for Powershell (84+2153) was written by Andrei Odegov
So make sure to upvote them both as well!
1..99|%{$n=$_
'"I "+("'+-join(0..6|%{[char](($n-shr$_)%2*32+'LOVEYOU'[$_])
' '*!($_-3)})+'"|% *wer)'}

Try it online!
Sample output:
"I "+("lOVE YOU"|% *wer)
"I "+("LoVE YOU"|% *wer)
"I "+("loVE YOU"|% *wer)
"I "+("LOvE YOU"|% *wer)
...
"I "+("loVE You"|% *wer)

PowerShell, 2672 = 99 + 2573, bonus track
1..99|%{$p,$d="0$_"[-2,-1]
$e,$l,$c,$r='I love you'-split"^(.{$p})(.)"
"'$l$d$r'-replace$d,`"$c`""}

Try it online!
It generates 10 distinct programs for each char of the input string. The length of string I love you is 10 chars. This is enough for 99 iterations
Sample output:
'1 love you'-replace1,"I"
'2 love you'-replace2,"I"
'3 love you'-replace3,"I"
...
'8 love you'-replace8,"I"
'9 love you'-replace9,"I"
'I0love you'-replace0," "
'I1love you'-replace1," "
...
'I love yo8'-replace8,"u"
'I love yo9'-replace9,"u"

PowerShell, 94 + 2890, bonus track 2
1..99|%{$n=$_;$i=0
'"=I='+-join(' love you'|% t*y|%{$_+'='[1-($n-shr$i++)%2]})+'"-replace"="'}

Try it online!
Sample output:
"=I= =love you"-replace"="
"=I= l=ove you"-replace"="
"=I= =l=ove you"-replace"="
"=I= lo=ve you"-replace"="
"=I= =lo=ve you"-replace"="
...

PowerShell, 96 + 3094
Specially for those who love to turn 99 into 9. ٩(^‿^)۶
2..100|%{"-join('"+-join(('I love you '*$_)[($_+10)..$_])+"'*$(2+($_-$_%10)/10))[$($_+10)..$_]"}

Try it online!
Sample output:
-join(' I uoy evol'*2)[12..2]
-join('l I uoy evo'*2)[13..3]
-join('ol I uoy ev'*2)[14..4]
-join('vol I uoy e'*2)[15..5]
-join('evol I uoy '*2)[16..6]
-join(' evol I uoy'*2)[17..7]
-join('y evol I uo'*2)[18..8]
-join('oy evol I u'*2)[19..9]
-join('uoy evol I '*3)[20..10]
-join(' uoy evol I'*3)[21..11]
-join('I uoy evol '*3)[22..12]
-join(' I uoy evol'*3)[23..13]
...
-join(' uoy evol I'*10)[98..88]
-join('I uoy evol '*10)[99..89]
-join(' I uoy evol'*11)[100..90]
-join('l I uoy evo'*11)[101..91]
-join('ol I uoy ev'*11)[102..92]
-join('vol I uoy e'*11)[103..93]
-join('evol I uoy '*11)[104..94]
-join(' evol I uoy'*11)[105..95]
-join('y evol I uo'*11)[106..96]
-join('oy evol I u'*11)[107..97]
-join('uoy evol I '*11)[108..98]
-join(' uoy evol I'*11)[109..99]
-join('I uoy evol '*12)[110..100]

PowerShell, 123 + 3141
...and in a normal order. https://coub.com/view/27d6eh
$s='I love you';(2..122|%{"-join('"+-join(("$s "*$_)[-($_+10)..-$_])+"'*$(2+($_-$_%10)/10))[$($_-1)..$($_+9)]"})-notmatch$s

Try it online!
Sample output:
-join('u I love yo'*2)[2..12]
-join('ou I love y'*2)[3..13]
-join('you I love '*2)[4..14]
-join(' you I love'*2)[5..15]
-join('e you I lov'*2)[6..16]
-join('ve you I lo'*2)[7..17]
-join('ove you I l'*2)[8..18]
-join('love you I '*3)[9..19]
-join(' love you I'*3)[10..20]
-join('u I love yo'*3)[13..23]
-join('ou I love y'*3)[14..24]
-join('you I love '*3)[15..25]
...

For your first answer, what's to stop me turning the 99 into 9?

Perl 6, 75 bytes, 2178 + 75 = 2253
unique("'I love you'.tclc.say",{S:x(8)[\w]~^=' 'x 2.rand}...*)[^99+1]>>.say

Try it online!
Outputs variants of:
'I love you'.tclc.say

string part has a randomised unique case. tclc is short for "title case, lowercase", which capitalises the first letter and lowercases the rest.
"..."         # Starting from the base program
     ,{                        }...*  # Generate an infinite series of
       S:x(8)[\w]~^=             # String xor the first 8 letters
                    ' 'x 2.rand  # Randomly space or nothing,
                                 # Essentially flipping the case

unique( ... )                 # From the unique elements
             [^99+1]          # Take 99, skipping the first
                    >>.say    # And print each

The reason I don't include the first unique element is so that a variant with correct casing isn't produced, since that would be reducible.

PowerShell, 85 + 2647 = 2732 83 + 2251 = 2334 79 + 1818 = 1897
0..226|?{[char]::isletterordigit($_)}|%{"`$$([char]$_)"}|%{"($_='I love you')"}

-398 thanks to mazzy
Try it online!
Sample output:
($0='I love you')
...
($â='I love you')

Try it online!

nice. you can remove { and }. Try it online!

You can reduce programs by removing the $0= and ;$0 parts

I'm agree in this case. The constraint 1 violated: If $0= is removed, then the program outputs `I love you'

I thinks this 84+2153 was the best

R, 84 Bytes
for(x in 1:99){cat("assign(intToUtf8(",x,"),'I love you');get(intToUtf8(",x,"))\n")}

I think this doesn't satisfy condition 2. For any values of x > 9 (i.e more than one digit), then you can remove two strings (one digit from both numbers) and it will still print 'I love you'.

W n d, 34 bytes
Different programs are separated as different list items. The n flag joins the input with newlines.
•u≡`â!=Ç¡l╪G⌠±×èe↔/.╫ù{¶c×█)←╢k0ôF

Uncompressed
99''a146+C"C'"a73+C"C-C@ love you@+"++++M

Explanation
99                                      M % Map in the range from 1 to 99
  ''                                      % A single quote '
    a146+                                 % Add the current item by 146
         C                                % Convert the current item to a character
          "C'"                            % Add a string C'
              a73+C                       % Add the current item by 73 (creating a difference of 73)
                   "C-C@ love you@+"++++  % Prepend the string and join the whole stack

Program explanation
'ⁿC'JC-              # Create the number 73
       C" love you"+ # Convert to character and append "love you"

Aha! 'I4"#Mpu~!:O&` COPY

C# (Visual C# Interactive Compiler), 70 bytes
for(char i='ÿ';i++<355;Write($"var {i}=\"I love you\";Write({i});"));

Try it online!

Ruby, 123 + 4247 94 90 + 2124 bytes
Heredoc abuse. Takes 49 different alphanumerics (A-Z, _, a-v) and constructs 2 programs that print the text using the appropriate heredoc. That's only 98 programs, though, so it adds one more print at the end. Each program is 3 lines long, except the last one.
This beats IMP1's Ruby solution in the combined code golf score, but falls behind in standard scoring.
l="I love you"
(?A..?v).grep(/\w/){|i|puts"$><<<<"+i,l,i,"puts <<"+i,l,i}
puts"puts'#{l}'"

Try it online!
Generated code
Old solution, 123 + 4247 bytes
Beats out IMP1's (non-Unicode) Ruby solution in the standard code golf department, but falls behind in combined code golf scoring. Unlike their use of multiple output solutions and rotation, I chose to shuffle the string after setting a seed with srand.
99.times{|i|srand i;puts"srand #{i};puts'#{[*0..9].shuffle.zip('I love you'.chars).sort.map(&:last)*''}'.chars.shuffle*''"}

Try it online!
Generated code

Zsh, 74 bytes
Output: 2178 (after removing newline delimiters) for a category 2 score of 2252 bytes
for p (echo print '<<<');for v ({1..7} {a..z})<<<"$v='I love you';$p \$$v"

Try it online!
Uses method from this Ruby answer, setting a unique variable before printing. In zsh, variables must be alphanumeric, so we limit to 33 names and then print out programs using echo, print, and <<< to get our 99.
There is optimization to be done for category 2, this tweak scores 77 + 2145 = 2222 bytes, and more can probably be found.

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


text:
Keta Bracket Autocompletion
 Special thanks to Bubbler and AdmBorkBork for supplying feedback about this challenge
Keta (Keyboard tacit — clever naming, I know!) is a golfing language I’ve been working on recently. One of it’s features is it’s most probably unique bracket autocompletion system, which will hopefully allow for shorter programs.
There are two types of brackets in Keta: grouping brackets ([] and {}) and list brackets (()). This challenge only involves completing grouping brackets.
Much like it’s predecessor Keg, Keta will automatically close any open brackets within your program. For example:
[3+H

Will be turned into
[3+H]

And:
{0L100R3

Will be turned into:
{0L100R3}

Obviously, matched brackets won’t be autocompleted, as they are already fully closed.
Now, this may seem like a very trivial challenge, but I ain’t done yet. Keta will also close open closing brackets as well. More specifically:
H+4}

Turns into
{H+4}

But what happens if two bracket types are mixed together? For example:
P[DD+s}S3

In cases like this, the opening bracket will complete up until a non-matching closing bracket. The closing bracket will then complete up until the start of the string. This means our above example will turn into:
{P[DD+s]}S3

More concisely:

[S]can left to right, maintaining a stack of open brackets. If I meet a non-matching closing bracket, close the open one(s) until they match or stack is empty. If the stack is empty, put a matching open bracket at the beginning instead. If the stack is nonempty at the end of the string, close all of them. ~ Bubbler

The Challenge
Given a string of potentially unmatched brackets, autocomplete the brackets as described above.
Test Cases
Input -> Output
[3+H --> [3+H]
{0L100R3 --> {0L100R3}
H+4} --> {H+4}
P[DD+s}S3 --> {P[DD+s]}S3
3+HH} --> {3+HH}
{abc --> {abc}
(3..12)S4] --> [(3..12)S4]
[0L100 --> [0L100]
A[BC}D --> {A[BC]}D
x{yz]a --> [x{yz}]a
[AbC] --> [AbC]
{12345678} --> {12345678}
A[bc} --> {A[bc]}
X{yz] --> [X{yz}]
'Hello, World!' --> 'Hello, World!'
AB(CD{EF]GH --> [AB(CD{EF}]GH
AB(CD}EF]GH --> [{AB(CD}EF]GH
AB[CD{EF]GH --> AB[CD{EF}]GH
AB[CD[EF}GH --> {AB[CD[EF]]}GH
AB{CD]EF]GH --> [[AB{CD}]EF]GH
A[bc --> A[bc]
A{bc --> A{bc}
[ --> []
{ --> {}
] --> []
} --> {}
 -->

Note that the last test case represents a literally empty string.
Rules

Input can be taken in any convenient and reasonable format.
Output can be given in any convenient and reasonable format.
The input string will be limited to printable ASCII characters, although it may be empty.
An ungolfed reference program can be found here

Scoring
Of course, this is code golf, so the answer in each language consisting of the fewest number of bytes wins. Happy golfings!
Leaderboards
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:
# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:
# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the leaderboard snippet:
# [><>](http://esolangs.org/wiki/Fish), 121 bytes

var QUESTION_ID=198087;
var OVERRIDE_USER=78850;
var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;function answersUrl(d){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+d+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(d,e){return"https://api.stackexchange.com/2.2/answers/"+e.join(";")+"/comments?page="+d+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){answers.push.apply(answers,d.items),answers_hash=[],answer_ids=[],d.items.forEach(function(e){e.comments=[];var f=+e.share_link.match(/\d+/);answer_ids.push(f),answers_hash[f]=e}),d.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){d.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),d.has_more?getComments():more_answers?getAnswers():process()}})}getAnswers();var SCORE_REG=function(){var d=String.raw`h\d`,e=String.raw`\-?\d+\.?\d*`,f=String.raw`[^\n<>]*`,g=String.raw`<s>${f}</s>|<strike>${f}</strike>|<del>${f}</del>`,h=String.raw`[^\n\d<>]*`,j=String.raw`<[^\n<>]+>`;return new RegExp(String.raw`<${d}>`+String.raw`\s*([^\n,]*[^\s,]),.*?`+String.raw`(${e})`+String.raw`(?=`+String.raw`${h}`+String.raw`(?:(?:${g}|${j})${h})*`+String.raw`</${d}>`+String.raw`)`)}(),OVERRIDE_REG=/^Override\s*header:\s*/i;function getAuthorName(d){return d.owner.display_name}function process(){var d=[];answers.forEach(function(n){var o=n.body;n.comments.forEach(function(q){OVERRIDE_REG.test(q.body)&&(o="
"+q.body.replace(OVERRIDE_REG,"")+"
")});var p=o.match(SCORE_REG);p&&d.push({user:getAuthorName(n),size:+p[2],language:p[1],link:n.share_link})}),d.sort(function(n,o){var p=n.size,q=o.size;return p-q});var e={},f=1,g=null,h=1;d.forEach(function(n){n.size!=g&&(h=f),g=n.size,++f;var o=jQuery("#answer-template").html();o=o.replace("{{PLACE}}",h+".").replace("{{NAME}}",n.user).replace("{{LANGUAGE}}",n.language).replace("{{SIZE}}",n.size).replace("{{LINK}}",n.link),o=jQuery(o),jQuery("#answers").append(o);var p=n.language;p=jQuery(""+n.language+"").text().toLowerCase(),e[p]=e[p]||{lang:n.language,user:n.user,size:n.size,link:n.link,uniq:p}});var j=[];for(var k in e)e.hasOwnProperty(k)&&j.push(e[k]);j.sort(function(n,o){return n.uniq>o.uniq?1:n.uniq<o.uniq?-1:0});for(var l=0;l<j.length;++l){var m=jQuery("#language-template").html(),k=j[l];m=m.replace("{{LANGUAGE}}",k.lang).replace("{{NAME}}",k.user).replace("{{SIZE}}",k.size).replace("{{LINK}}",k.link),m=jQuery(m),jQuery("#languages").append(m)}}
body{text-align:left!important}#answer-list{padding:10px;float:left}#language-list{padding:10px;float:left}table thead{font-weight:700}table td{padding:5px}
#language-list h2{color:#215F06}
 <link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/primary.css?v=f52df912b654">

Winners by Language

Language	User	Score

Leaderboard

	Author	Language	Size

{{PLACE}}	{{NAME}}	{{LANGUAGE}}	{{SIZE}}

{{LANGUAGE}}	{{NAME}}	{{SIZE}}

So, in AB(CD{EF]GH, the opening parenthesis is left unbalanced?

Yes, as we are only focusing on [] and {}

Charcoal, 74 68 bytes
ＦＳ«Ｗ∧υ›№]}ι⁼§υ±¹ι≔⁺ω⊟υω≔⁺ωιω≡ι]Ｆ¬∧υ⊟υ≔⁺[ωω}Ｆ¬∧υ⊟υ≔⁺{ωω[⊞υ]¦{⊞υ}»ω↑⮌υ

Try it online! Link is to verbose version of code. Explanation:
ＦＳ«

Loop over the characters of the input.
Ｗ∧υ›№]}ι⁼§υ±¹ι≔⁺ω⊟υω

If the current character is a closing bracket and we're expecting the other sort of closing bracket then append that bracket now. Keep doing this until we run out of other closing brackets to insert.
≔⁺ωιω

Append the current character.
≡ι]Ｆ¬∧υ⊟υ≔⁺[ωω}Ｆ¬∧υ⊟υ≔⁺{ωω[⊞υ]¦{⊞υ}

Switch on the current character. If it's a closing bracket, then remove the (now) matching closing bracket, but if that can't be done then prepend the desired matching opening bracket. If it's an opening bracket, then just save the desired matching closing bracket.
»ω↑⮌υ

After all the characters have been processed, output the processed characters (now including autocompleted missing opening brackets and wrong closing brackets), and then any remaining missing closing brackets.

JavaScript (ES6),  145  142 bytes
s=>[...s].map(c=>o+=(i=(S='[]{}').indexOf(c)^1)&1?(s=S[i]+s,c):i<0?c:(g=_=>s?(C=s[s=s.slice(1),0])==c?c:C+g():(p=S[i]+p,c))(),s=o=p='')&&p+o+s

Try it online!

Retina 0.8.2, 269 bytes
\[(\[(?=.*(]))|\{(?=.*(?<2>}))|[^][}{]|(?<-2>\2))*(?(2)(?!))(?=}|$)
$&]
\{(\[(?=.*(]))|\{(?=.*(?<2>}))|[^][}{]|(?<-2>\2))*(?(2)(?!))(?=]|$)
$&}
^(\[(?=.*(]))|\{(?=.*(?<2>}))|[^][}{]|(?<-2>\2))*(?(2)$)]
[$&
}`^(\[(?=.*(]))|\{(?=.*(?<2>}))|[^][}{]|(?<-2>\2))*(?(2)$)}
{$&

Try it online! Link includes test suite. Explanation: In .NET, the regex (\[(?=.*(]))|\{(?=.*(?<2>}))|[^][}{]|(?<-2>\2))*(?(2)(?!)) matches a string containing only balanced brackets. This is broken down into four alternatives, which are repeated, and then the capture group is checked for emptiness (this can be done more golfily in the latter cases), proving that all brackets have been balanced. It then remains to match the appropriate mismatched brackets and/or start/end and insert the correct matching bracket. Finally, the whole script is repeated using }` until all mismatched brackets have been autocompleted.
\[(?=.*(]))

Match a [ and capture a ] (which happens to be capture group 2).
\{(?=.*(?<2>}))

Match a { and capture a }, but name this capture group 2 as well.
[^][}{]

Match anything that isn't a bracket (under this question's definition).
(?<-2>\2)

Match the last closing bracket that we captured earlier, and then forget that bracket, so that the previous closing bracket becomes the next potential match.

Prolog (SWI), 246 bytes
Input is taken as a list of ASCII character codes while ouput is printed to stdout. The approach is a straightforward translation of the algorithm described in the post into Prolog.
\T:-T+D+[],maplist(put_code,D).
[]+[]+[].
X+[D|U]+S:-X=[],S=[O|Z],D is O+2,X+U+Z;X=[H|T],(D=H,(\+H^`[]{}`,T+U+S;H^`]}`,O is H-2,(S=[O|Z],T+U+Z;S=[],put_code(O),T+U+S);H^`[{`,T+U+[H|S]);S=[O|V],H^`}]`,D^`}]`,H\=D,O is D-2,X+U+V).
A^B:-member(A,B).

Try it online!
Prolog has a special syntax for literal lists of character codes so, invoking the predicate is easy.
?- \`A[bc}`.
{A[bc]}
true .


text:
Spotify Shuffle (music playlist shuffle algorithm)
Background
Perfect shuffle algorithms like Fisher-Yates shuffle don't produce great results when it comes to music playlist shuffling, because it often produces clusters of songs from the same album. In an attempt to solve this problem, Spotify introduced an interesting shuffle algorithm in 2014. At the end of the article, they claimed (emphasis mine):

All in all the algorithm is very simple and it can be implemented in just a couple of lines. It’s also very fast and produces decent results.

Let's see if this is indeed the case.
Task
Implement the modified Spotify shuffle. The algorithm described in the article has some gaps in its specification, so I present a refined one here.
The algorithm
Let's assume we have a list of items grouped into categories, e.g.:
[['A', 'AA', 'AAA'], ['B'], ['C', 'CC'], ['D'], ['E', 'EE', 'EEE', 'EEEE']]

Shuffle items within each category.

You may use any shuffle algorithm that can produce every possible permutation with nonzero probability.

[['AAA', 'A', 'AA'], ['B'], ['C', 'CC'], ['D'], ['EEE', 'EEEE', 'EE', 'E']]

Assign each item a "positional value". Items in one category should be uniformly spaced, but with some randomness. To achieve this, do the following operations on each category having n items:
Initialize the positional value vector v of length n with the values v[k] = k/n for 0 <= k < n (i.e. 0-indexed), so that the items have default spacing of 1/n.
Generate an initial random offset io within the range of 0 <= io <= 1/n, and add it to every v[k].
Generate n individual random offsets o[k] within the range of -1/10n <= o[k] <= 1/10n, and apply v[k] += o[k] for each k. So the positional value of k-th item (0-indexed) within an n-item category will be v[k] = k/n + io + o[k].

The random offsets io and o[k] should ideally be picked from a uniform random variable, but can be approximated by picking from a discrete distribution with at least 5 distinct equally-spaced outcomes, including both lower and upper bounds. (e.g. you can choose to randomly pick io from [0, 1/4n, 2/4n, 3/4n, 1/n].)
Don't do extra processing even if v[k] < 0 or v[k] > 1.

[['AAA' -> 0.1, 'A' -> 0.41, 'AA' -> 0.79],
 ['B' -> 0.2],
 ['C' -> 0.49, 'CC' -> 1.01],
 ['D' -> 0.03],
 ['EEE' -> 0.12, 'EEEE' -> 0.37, 'EE' -> 0.6, 'E' -> 0.88]]

Sort all items by the positional values.

['D', 'AAA', 'EEE', 'B', 'EEEE', 'A', 'C', 'EE', 'AA', 'E', 'CC']

The shuffled result roughly looks like this (from the article):

(source: wordpress.com)
Here is Python-like pseudocode of the above algorithm:
x = nested array of items
uniform(a,b) = uniformly generate a random value between a and b
items = []
v = []
for i in range(len(x)):  # for each category
    shuffle(x[i])  # shuffle items within category in place
    items += x[i]
    n = len(x[i])  # size of the current category
    io = uniform(0, 1/n)  # initial offset
    o = [uniform(-0.1/n, 0.1/n) for k in range(n)]  # individual offsets
    v += [k/n + io + o[k] for k in range(n)]  # resulting positional values
sort items by v
print items

Input and output
The input is a list of groups of items (i.e. a nested list) as shown in the example above. An item is a string made of only uppercase letters (or only lowercase if you want). You can assume that all items are distinct, within and across categories.
The output is a shuffled list including all items in the input, which is produced by the algorithm described above.
The randomness requirements are covered in the algorithm description.
Scoring and winning criterion
Standard code-golf rules apply. Shortest code in bytes wins.

"You may use any shuffle algorithm that can produce every possible permutation with nonzero probability." - does this make the assumption that you have a true randomness source? Because it's important to note that the number of possible permutations is limited by the period of the random number generator in use.

That minimum bound of 5 was so convenient for my answer - it lets me generate a random number from 0 to 4, halve it, decrement it, and divide by 10, to give me a random number from -0.1 to 0.1. Thanks!

@Beefster I'm aware of it, so it's OK to assume the underlying source of randomness for your language is perfect (i.e. true random).

May we assume no duplicates in the groups?

@Jitse You can assume that all items are distinct, so yes.

JavaScript (Node.js),  125  124 bytes
Saved 1 byte thanks to @KevinCruijssen
a=>a.flatMap(a=>a.sort(_=>R()-.5).map(v=>[(o++-.1+R()/5)/a.length,v],o=R()),R=Math.random).sort(([a],[b])=>a-b).map(a=>a[1])

Try it online!
Commented
a =>                          // a[] = input
  a.flatMap(a =>              // for each category a[] in a[]:
    a.sort(_ => R() - .5)     //   shuffle a[]
    .map(v =>                 //   for each value v in a[]:
      [                       //     build a pair [position, value]:
        ( o++                 //       increment o
          - .1                //       subtract 1/10
          + R() / 5           //       add 2/10 * random value in [0,1)
        ) / a.length,         //       divide the result by the length of a[]
        v                     //       use v as the 2nd element
      ],                      //     end of pair
      o = R()                 //     start with o in [0,1)
    ),                        //   end of map()
    R = Math.random           //   R = alias for Math.random
  )                           // end of flatMap()
  .sort(([a], [b]) => a - b)  // sort by first element, in ascending order
  .map(a => a[1])             // keep only the 2nd element

I honestly had no idea they added flat() and flatMap(), I suppose I'm way behind the curve now :P

Python 3, 244 218 200 bytes
from random import*
l,r,u=len,range,uniform
def f(x):
 I,v=[],[]
 for i in r(l(x)):shuffle(x[i]);I+=x[i];n=l(x[i]);t=0.1/n;v+=[k/n+u(0,1/n)+u(-t,t)for k in r(n)]
 return[s[1]for s in sorted(zip(v,I))]

Try it online!
Literally just a golfed version of the algorithm in the challenge. I mean, someone had to do it!
Thanks to ValueInk for golfing suggestions!

Methinks [s[1]for s in sorted(zip(v,I))] is better because you don't need your key parameter (Python will sort by comparing the first elements, then second elements, etc.). Also, have you considered the fact that your offset initialization uses the same kind of loop as the value generation? That means that you can remove the offset assignment code and put the relevant randomization straight in the value array part.

Hmmm not quite. I was actually thinking k/n+u(0,1/n)+u(-t,t)for k in r(n). No indices, no arrays, only a quick grabbing of a random number.

Jelly, 28 bytes
‘9xX€’÷8Ḣ__.÷5ƊƊ_@Ẋ÷
ẈÇ€FỤịẎ

Try it online!
A pair of links that is called monadically with input and output as described in the question. Jelly doesn’t generate random uniform numbers so a random rational number between 0 and 1 in increments of 0.125 is used instead.
Incidentally, per the question’s quote, I’ve implemented it in a couple of lines.
Explanation
Helper link, generates scores for each collection
Argument is the length of the collection
‘                    | Increment by 1
 9x                  | 9 repeated that many times
   X€                | Generate a random number from 1..9 for each
     ’               | Decrement by 1
      ÷8             | Divide by 8
               Ɗ     | Following as a monad:
        Ḣ            | - Head
         _     Ɗ     | - Subtract following as a monad:
          _.         |   - (Remainder of list) subtract 0.5
            ÷5       |   - Divide by 5
                _@Ẋ  | Subtract this from shuffled list from 1..original argument (subtracted to get zero-based number)
                   ÷ | Divide by original argument

Main link
Ẉ       | Lengths of collections
 Ç€     | Call helper link for each
   F    | Flatten
    Ụ   | Sort indices by values
     ịẎ | Index into original argument joined into one list of strings

It's official... Spotify uses Jelly! :P

J, 52 42 32 bytes
/:&;(%~_.1+?~+?@0+5%~?@#&0)@#&.>

Try it online!

05AB1E, 37 bytes
ε.rDg©т*ÝΩVεN®/тD(ŸΩY‚₄/O+‚]˜2ôΣθ}€¨

Port of @Arnauld's JavaScript answer, so make sure to upvote him as well!
Try it online (feel free to remove the last 2 or 3 bytes (}€¨) to see the resulting \$v[k]\$ values it sorts on).
Explanation:
ε             # Map each group of the (implicit) 2D integer-list to:
 .r           #  Randomly shuffle the group
   Dg         #  Duplicate, and pop and push the length: n
     U        #  Pop and store this length in variable `X`
   ₄Ý         #  Push a list in the range [0,1000]
     ₄/       #  Divide each value by 1000 to make the range [0,1] in increments of 0.001
       ©      #  Store this list in variable `®` (without popping)
        Ω     #  Pop and push a random value from this list
         V    #  Pop and store that random value in variable `Y`
    ε         #  Map over each value in this shuffled group:
     Y        #   Push the random value from variable `Y`
      N+      #   Add the 0-based loop index to it
     Tz-      #   Subtract 1/10 from it
     ®        #   Push the [0,1] list from variable `®` again
      Ω       #   Pop and push a random value r from this list
       5/     #   Divide it by 5
         +    #   Add it to the earlier Y-0.1
          X/  #   And divide it all by the length of the group from variable `X`
     ‚        #   And pair this v[k] with the value name
]             # After both maps:
 ˜            # Flatten the entire list of list of value,key pairs
  2ô          # And then split it into parts of size 2
              # (so we now have a flattened value,key paired list)
    Σ }       # Sort these key-value pairs by:
     θ        #  The last item (so by the key v[k])
       €¨     # And then remove the last item (so the key v[k]) from each pair
              # (after which the resulting list of (wrapped) values is output implicitly)

This doesn't look correct. If I got this right, your io is uniform(0, 0.1 * n) when it should be
uniform(0, 1 / n), and your o[k] is uniform(-0.1, 0.1) when it should be
uniform(-0.1 / n, 0.1 / n).

@Grimmy Ported Arnauld's JS answer as fix (+1 byte). I have the feeling this can be golfed substantially, though.. >.>

Ruby, 93 bytes
Another straightforward implementation. -9 bytes from borrowing ideas from Arnauld's value generation code, which I saw right before I posted my answer.
->a{v=a.flat_map{|e|i=rand-1;e.shuffle.map{|s|[(rand/5-0.1+i+=1)/e.size,s]}}.sort.map &:last}

Try it online!

Red, 180 bytes
func[b][random/seed now extract next sort/skip collect[forall
b[i: random 1.0 /(d: length? t: random b/1)repeat n
d[keep n - 1.0 / d + i +(0.1 / d - random 0.2 / d)keep t/:n]]]2 2]

Try it online!
Just a straightforward implementation of the algorithm

R, 104 101 bytes
function(x,`!`=unlist,`+`=runif)(!x)[order(!lapply(lengths(x),function(l)(sample(l)-+1--+l/5-.1)/l))]

Try it online!
A function taking a list of character vectors and returning a character vector.
Thanks to @RobinRyder for saving 3 bytes!

100 bytes by rearranging and redefining runif.

@RobinRyder thanks. Unfortunately doesn’t work because of the very low operator precedence for ?. I’ve managed to shave 2 bytes off though with inspiration from your answer.

Right, sorry. I think this works for 101 bytes: unary + has high precedence, and you can use -- when you need actual addition.

Charcoal, 60 bytes
Ｆθ«≔⟦⟧ηＷ⁻ιη⊞η‽κ≔∕‽⁵¦⁴ιＦＥη⟦∕⁺λ⁺ι∕⊖⊘‽⁵χＬηκ⟧⊞υκ»Ｗ⌊υ«≔Φυ¬⁼ικυ⟦⊟ι

Try it online! Link is to verbose version of code. Uses 5 distinct equally-spaced random numbers each time as allowed by the question. Explanation:
Ｆθ«

Loop over each category.
≔⟦⟧η

Start with no shuffled items.
Ｗ⁻ιη

Repeat until the set difference between the items and shuffled items is empty.
⊞η‽κ

Randomly pick one element of the difference to append to the shuffled items.
≔∕‽⁵¦⁴ι

Pick a random number between 0 and 1 which represents io*n.
∕⁺λ⁺ι∕⊖⊘‽⁵χＬη

For each item, add its index within its category v*n to io*n and a randomly generated offset o*n between -0.1 and 0.1, then divide the sum by n to get the final positional value.
ＦＥη⟦...κ⟧⊞υκ»

Save each random value and item in a separate list.
Ｗ⌊υ«

Repeat while the (minimum of) the list of random values and items is not empty.
≔Φυ¬⁼ικυ

Filter out the minimum value from the list.
⟦⊟ι

Output the item with that value.

Python 3, 147 bytes
lambda a:[*zip(*sorted(((j+l.index(k)+random()/5-.1)/len(l),k)for j,l in((random(),sample(m,len(m)))for m in a)for k in l))][1]
from random import*

Try it online!
Assumes no duplicates


text:
Move my liquid to make me equal
You are given 4 positive integers: volume of the first container (v1), volume of the second container (v2), volume of the liquid in the first container (l1), and volume of the liquid in the second container (l2). Your task is to move some of the liquid from container 1 to container 2, making the amount of empty space in the containers equal to each other, outputting how much liquid should be moved.
An example
Here is an example of some possible input (formatted for the ease of test cases. The input isn't formatted.):
8 11
6  5

Here, you need to make sure that the differences between the volumes and the containers are equal. Currently the difference is not equal:
  8 11
- 6  5
======
   6 2

So we need to try to make them equal, by taking some of the values in one container to another container:
  8 11
- 4  7
======
  4  4

After you have succeeded, output how much liquid you need to take from container 1 to container 2. Therefore the above example should output 2.
Test cases
15 16
 9  2

We move into this state:
 15 16
- 5  6
======
 10 10

Therefore 4 is the expected result.
Test case #2
16 12
13  1

We move into this state:
 16 12
- 9  5
======
  7  7

Therefore 4 is the expected output.
Test case #3
20 12
10 2

Moved:
 20 12
-10 2
======
 10 10

Therefore 0 is the expected output.
More test cases
(They don't have explanations as this should be quite clear)
12 5
9  0 -> 1

9 11
7  3 -> 3

Rules

The test cases will be made so that the result is always possible as a positive integer. The result will never be a decimal.
Input can be taken in any convenient and reasonable format.
Output can be given in any convenient and reasonable format.
The input string will be made so that a moving is always possible without involving decimals or negative numbers. Also there will not be more liquid than how much a container can hold.
Of course, this is code-golf, so the answer in each language consisting of the fewest number of bytes wins. Happy golfing!
An extra restriction for the test cases: you can assume that there is always going to be space available in the second container. So a test case like this:

10 2
 2 2

is not going to be a valid testcase.

JavaScript (ES6) / C#, 21 bytes
(v,V,q,Q)=>V-Q-v+q>>1

Try it online! (JS)
Try it online! (C#)

@KevinCruijssen Nice catch. :)

Apart from the => vs -> it's also a polyglot with Java 8 and CoffeeScript 2 (your >>1 also saved a byte in my answer). :)

05AB1E, 3 bytes
®β;

Try it online!
Input is an array of volumes in the order [first liquid, first container, second container, second liquid].
Alternative 3-byter:
ÆÆ;

Try it online!
Input is a nested array: [[first container, first liquid], [second container, second liquid]].

Jelly, 3 bytes
ISH

Try it online!
A monadic link taking as its argument [[l1, v1], [v2, l2]] and returning the volume needed to move.
A relatively rare ASCII-only Jelly answer!
Explanation
I   | Increments
 S  | Sum
  H | Half

Well, it's ASCII-ISH...

Keg, 14 13 bytes
-±¿-¿+½:0<[±]

Try it online!
A port of Arnauld's original javascript answer. Takes input in form of:
volume1
container1
volume2
container2

-1 byte by utilising implicit input correctly.

Perl 6 Raku, 12 11 bytes
(*-*-*+*)/2

Try it online!
Edit: I realized that I could take the parameters in any order. Four parameters are: liquid in container 1, liquid in container 2, volume of container 1, volume of container 2.

Excel, 16 bytes
=(B1-D1-A1+C1)/2

Same approach as others

Python 3, 27 26 25 bytes
Saved a bytes thanks to meetaig!!!
lambda a,b,c,d:b-d-a+c>>1

Try it online!

lambda a,b,c,d:b-d-a+c>>1  would save 1 character=1byte

@meetaig Thanks! Forgot right-shift had lower precedence than addition/subtraction. :-)

C (clang), 29 28 bytes
Saved a bytes thanks to meetaig!!!
#define f(a,b,c,d)b-d-a+c>>1

Try it online!

C (gcc), 39 25 bytes
f(a,b,c,d){a=b-d-a+c>>1;}

Wrote a testing framework for possible future testcases.
Takes as input 4 integers:

a: capacity of first container
b: capacity of second container
c: amount of liquid in first container
d: amount of liquid in second container

Explanation:
f(a,b,c,d)

Function implicitly returning int with four arguments of type int.
a=

A sort of return that exploits GCC's code generation when compiling without optimization.
b-d-a+c>>1

The main algorithm. There's several steps involved here:

b-d: Subtract the amount of liquid in the second container from the capacity in the second container to get the free space in the second container.
-a+c: Subtract the capacity of the first container and add back the amount of liquid in the second container to get the total free space in both.
>>1 After that, divide the amount of free space in both by 2 to get the amount of liquid to move from container one to container two. This is a binary right shift and binary is base 2, so it is equivalent to division by 2 but removes the need for parentheses as the operator precedence of >> is lower than that of + and -. The operator precedence for / is higher than that of + and - so it would require extra parentheses.

Try it online!

Java 8 / CoffeeScript 2, 22 21 bytes
(V,v,L,l)->v-l-V+L>>1

Port of @Grimmy's second 05AB1E answer.
-1 byte by porting @Arnauld's approach, golfing the (...)/2 I had to ...>>1.
Try it online in Java 8.
Try it online in CoffeeScript 2.
Explanation:
(V,v,L,l)->    // Method with four integer parameters and integer return-type
   v-l         //  Calculate the difference between the volume and liquid of container 1
      -V+L     //  Subtract the difference between the volume and liquid of container 2
          >>1  //  Divide that result by 2 (by bit-shifting once towards the right)

Coffescript polyglot. (Not a JavaScript polyglot because of -> vs =>).

@Grimmy Added. :)

Whitespace, 79 bytes
[S S S N
_Push_0][S N
S _Dupe_0][T    N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input_vol1][S N
S _Dupe_input_vol1][S N
S _Dupe_input_vol1][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input_liq1][T S S T   _Subtract_vol1-liq1][S N
S _Dupe_vol1-liq1][S N
S _Dupe_vol1-liq1][T    N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input_vol2][S N
S _Dupe_input_vol2][S N
S _Dupe_input_vol2][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input_liq2][T S S T   _Subtract_vol2-liq2][T  S S T   _Subtract_(vol1-liq1)-(vol2-liq2)][S S S T  S N
_Push_2][T  S T S _Integer_divide_((vol1-liq1)-(vol2-liq2))/2][T    N
S T _Print_as_integer]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.
Try it online (with raw spaces, tabs and new-lines only).
Explanation in pseudo-code:
Integer vol1 = STDIN as integer
Integer liq1 = STDIN as integer
Integer vol2 = STDIN as integer
Integer liq2 = STDIN as integer
Integer diff1 = vol1 - liq1
Integer diff2 = vol2 - liq2
Integer diffOfDiff = diff1 - diff2
Integer result = diffOfDiff / 2
Print result as integer to STDOUT

Since the integers are guaranteed to be positive, it uses them as heap-address for the next input in line with some duplicates, saving bytes.

AWK, 21 20 bytes
1,$0=($2-$4-$1+$3)/2

Try it online!

Retina 0.8.2, 19 bytes
\d+;?
$*
+`1,1
,
11

Try it online! Link includes test cases. Explanation:
\d+;?
$*

Convert to unary and sum the middle two numbers.
+`1,1
,

Subtract the outer numbers from that sum.
11

Divide by 2 and convert to decimal.

TI-BASIC, 26 21 bytes
Prompt A,B,C,D:.5abs(A-C-B+D

Input is a series of prompts for each value.
A = volume1
B = volume2
C = liquid1
D = liquid2
Output is the amount of liquid that needs to be moved from the fuller container to the emptier one.
Explantion:
Prompt A,B,C,D     ;Prompt the user to input the values
.5abs(A-C-B+D      ;Compute the amount of liquid needed, convert it
                   ;  to a positive number if need be and leave the
                   ;  result in Ans
                   ;Implicit print of Ans

Examples:
prgmCDGF21

A=?15
B=?16
C=?9
D=?2
                   4
prgmCDGF21

A=?11
B=?10
C=?6
D=?7
                   1

Note:  TI-BASIC is a tokenized language.  Character count does not equal byte count.

I'm pretty sure just taking the 4 numbers as 4 different variables would be shorter.

@randomdude999 looks like that's the case, but only by 7 bytes.  this is code golf after all, i guess

Brainf*ck, 39 bytes
Try it online!
,>,>,<[->+<]<[->>-<<]>,[->-<]>[-->+<]>.

The input/output are the ASCII values of characters. Using "aaz0" gives "%" as output, as it corresponds to the case
97 122

97  48

which is solved by moving 37 units of liquid, the % symbol.
Could shave a couple of bytes if the input order could be rearranged, but not sure if that would be acceptable.

J-uby, 13 bytes
Port of Nick Kennedy's Jelly answer. Takes input in format [[v1, l1], [l2, v2]].
+:-**:+|~:/&2

Attempt This Online!
Explanation
+:- ** :+ | ~:/ & 2

    **               # Map arguments with...
+:-                  #   Splat pair of elements onto :- (subtract)

       :+ |          # Add, then
            ~:/ & 2  # Divide by 2