text:
Digital Hardness of Integers

To find the digital hardness of an integer, take its binary representation, and count the number of times both a leading and trailing 1 can be removed until it either start or ends with a 0. The total number of bits removed is its digital hardness.

That's quite a wordy explanation  - so let's break it down with a worked example.
For this example, we'll use the number 3167. In binary, this is:
110001011111

(Note that, during the conversion to binary, you should make sure to strip leading zeroes)
It doesn't start or end with 0, so we remove 1 pair of bits:
1  1000101111  1

And another:
11  00010111  11

But now there is a 0 at the beginning, so we can't remove anymore 1 pairs. In total, 4 bits we removed, and so 4 is the digital hardness of 3167.
However, for numbers that can be written as 2n-1 for positive n (i.e. contain only 1 in binary representation), 0 will never be reached, and so all the bits can be removed. This means that the hardness is simply the integer's bit length.

The Challenge
You task is to write a program or function which, given a non-negative integer n >= 0, determines its digital hardness.
You can submit a full program which performs I/O, or a function which returns the result. Your submission should work for values of n within your language's standard integer range.

Test Cases
Please notify me if any of these are incorrect, or if you'd like to suggest any edge cases to add.
0     -> 0
1     -> 1
8     -> 0
23    -> 2
31    -> 5
103   -> 4
127   -> 7
1877  -> 2
2015  -> 10

Here's the ungolfed Python solution which I used to generate these test cases (not guaranteed to be bug-less):
def hardness(num) -> int:
    binary = bin(num)[2:]

    if binary.count('0') == 0:
        return num.bit_length()

    revbin = binary[::-1]

    return min(revbin.find('0'), binary.find('0')) * 2

How does 1 return 1 when there is no 0 in it whatsoever? I mean, you can't possibly remove enough 1's from the string to have the it start or end in 0.

@busukxuan Read the paragraph just before the "The Challenge" heading: for numbers that can be written as 2^n-1 (i.e. contain only 1 in binary representation), 0 will never be reached, and so all the bits can be removed. This means that the hardness is simply the integer's bit length.

What I mean is that maybe defining the hardness as "until not both sides start with 1" might be more appropriate.

@busukxuan you can think of it as the number of ones each side is padded with, before zeroes are reached.

To the downvoter who obviously didn't like the edge cases: The hardness is the number of solid (1) bits it is padded with - if the whole thing is solid, then surely it has 100% hardness, its whole bit length?

@FlipTack I don't want to influence too much, it's your challenge. I initially understood "hardness" as the maximum number of pairs of outer ones that can be removed, one from each side. But you may be right, if a single one remains at the end, perhaps it should be counted in

Wouldn't the hardness of 103 be 5, as 103 is 1100111 in binary. (theres 5 1's on the end)

@Cormac read the example - you take the 1s off in pairs, so with 103 you take 4 off before a zero appears at the beginning.

i'm a bit confused - of course the binary representation of "0" is "0", but 0 can also be written as 2^n - 1 for n = 0 ?

@peech Sorry, I meant to include positive for describing n (0 isn't positive). What I meant is numbers where all the binary digits are 1.

Jelly, 11 10 bytes
BµQL××Ṛa\S

Try it online!
How it works
BµQL××Ṛa\S  Main link. Argument: n

B           Binary; convert n to base 2.
 µ          Begin a new, monadic chain. Argument: A (array of binary digits)
  Q         Unique; deduplicate the digits.
   L        Length; count the unique digits.
    ×       Multiply each digit by the result.
     ×Ṛ     Multiply the results by reversed A.
       a\   Cumulative reduce by logical AND.
            This zeroes out all elements after the first zero.
         S  Compute the sum of the result.

Python, 76 69 68 63 62 60 57 bytes
f=lambda n,k=0:n>>k&(n&n>>k>n>>k+1)and(n&n+1>0)-~f(n,k+1)

Try it online!
How it works
This is a recursive solution that takes an input n and keeps incrementing k – starting at 0– while both LSBk(n) (bit at index k from the right) and MSBk(n) (bit at index k from the left) are set. Once finished, it returns k if all of n's bit are set and 2k if not.
Let's start by rewriting the lambda f as a named function F, with an auxiliary variable t.
def F(n, k = 0):
    t = n >> k
    return t & (n & t > t >> 1) and (n & (n + 1) > 0) + 1 + F(n, k + 1)

In each invocation of F, we first bit-shift n a total of k units to the right and store the result in t. This way, LSB0(t) = LSBk(n), so t is odd if and only if LSBk(n) is set.
Determining whether MSBk(n) is set is slightly trickier; this is what n & t > t >> 1 achieves. To illustrate how it works, let's consider an integer n = 1αβγδεζη2 of bit-length 8 and analyze the function call F(n, 3), i.e., k = 3.
We're trying to determine whether MSB3(n) = γ is set by examining the truth value of the comparison (n & t > t >> 1) = (1αβγδεζη2 & 1αβγδ2 > 1αβγ2). Let's examine the involved integers.
MSB-index  012k4567

n          1αβγδεζη
t             1αβγδ

t >> 1         1αβγ

We claim that γ = 1 if and only if n & t > t >> 1.

If γ = 1, then n & t has bit-length 5 while t >> 1 has bit-length 4, so n & t > t >> 1.
This proves that γ = 1 implies n & t > t >> 1.
If n & t > t >> 1, there are two options: either γ = 1 or γ = 0. In the first case, there's nothing left to prove.
In the second case, we have that αβγδ2 ≥ n & t > t >> 1 = 1αβγ2.
Since αβγδ2 > 1αβγ2, we must have MSB0(αβγδ2) ≥ MSB0(1αβγ2), meaning that α = 1.
This way, 1βγδ2 > 11βγ2, so we must have MSB1(1βγδ2) ≥ MSB1(11βγ2), meaning that β = 1.
In turn, this implies that 11γδ2 > 111γ2. Remembering that γ = 0 in the second case, we get the inequality 110δ2 > 11102, which is false since MSB2(110δ2) = 0 < 1 = MSB2(11102).
Thus, only the first case is possible and n & t > t >> 1 implies γ = 1.

Summing up, if both LSBk(n) and MSBk(n) are set, t will be odd and n & t > t >> 1 will be True, so t & (n & t > t >> 1) will yield 1. However, if LSBk(n) or MSBk(n) is unset (or if both are), t will be even or n & t > t >> 1 will be False, so t & (n & t > t >> 1) will yield 0.
Calling F with a single argument initializes k = 0. While the condition we've discussed earlier holds, the code after and is executed, which (among other things) recursively calls F with incremented k.
Once LSBk(n) or MSBk(n) is unset, the condition fails and F(n, k) returns 0. Each of the preceding k function calls adds (n & (n + 1) > 0) + 1 to F(n, k) = 0, so F(n) returns ((n & (n + 1) > 0) + 1)k.
Now, if all bits of n are equal (i.e., if n is either 0 or all of its bits are set), n + 1 will not have any bits in common with n, so n & (n + 1) = 0 and F(n) returns k. However, if n has both set and unset bits, n & (n + 1) > 0 and F(n) returns 2k.

Recursive solutions in Python seems to be scoring really well lately.

At least compared with iterative solutions, they always have. input(), while, and print are already 17 bytes...

Yeah, but I find them so much harder to write.

Fair enough. An straightforward iterative implementation of the same idea would only be 5 bytes longer though. https://tio.run/nexus/python2#@59nm5lXUFqioWmdbWvAVZ6RmZOqkaeWZ2eXbQcitA01wRyrbG1bQ66Cosy8EoVsGxsNsAIDzf//jQwMTQE 2 more bytes could be saved with a few tricks. https://tio.run/nexus/python2#JY1BDsIgFAXX7SnepgUUI1BNm1K4jKVJQ/I1zV@48uqIcTOZ1UxZ04ZNkppzMD6900NwoBizz@cgqefIV6d69uJ0@ZB/HTsx8rJIjkaV7XmAsBOk0bAak4YbNIaq1lSxbqyYxkpn7F3NbfMviO62CnQg3Ta/e/kC

MATL, 13 12 bytes
Btv`6L&)}x@q

Try it online! Or verify all test cases.
Explanation
The code repeats each binary digit, and counts how many times it is possible to remove two outer ones.
B        % Input number (implicit). Horizontal vector of binary digits
tv       % Duplicate and concatenate vertically
`        % Do...while
  6L&)   %   Flatten the array if needed (in column-major order), and split it
         %   into two subarrays: one with the inner entries, and another
         %   with the two outer entries. The latter will be used for deciding
         %   if the loop continues or is exited
}        % Finally (execute before exiting the loop)
  x      %   Delete last subarray of inner entries
  @q     %   Push last iteration index minus 1
         % End (implicit). The next iterarion is executed if the array at the
         % top of the stack is non-empty and only contains nonzero values.
         % Otherwise the loop is exited, executing the "finally" block first
         % Display (implicit)

Python, 82 bytes
I feel like it can still be golfed, but I spent a while trying different methods and this was the shortest.
def f(n):b=bin(n)[2:];x=min(b.find('0'),b[::-1].find('0'));print(x<0)*len(b)or x*2

Try it online
Though this works similarly to the OP's Python program, I created this before the question was posted, after viewing the question in the Sandbox, which did not contain such a program.

Python 2, 66 bytes
s=bin(input())[2:].split('0')
print len(min(s[-1],s[0]))<<1%len(s)

Splits the binary representation of the input into chunks of 1. Counts the number of 1's in the smaller of the first and last chunk, then doubles it, unless there's a single chunk that this would double-count.

Clever, but still easy to understand. I like it!

@mbomb007 Take it as a warm up for understanding Dennis's :)

PowerShell, 109 106 bytes
$a=[convert]::ToString($args[0],2)-split0;(((($b=$a[0].length),$a[-1].length|sort)[0]*2),$b)[$a.count-eq1]

Try it online!
Takes input $args[0], uses the .NET call to convert it toString with base 2 (i.e., make it binary), then -splits that string on 0s, stores that into $a. Important to note: the .NET call does not return leading zeros, so the first digit is always a 1.
There are thus two possibilities -- the binary string is all ones, or there was at least one zero. We differentiate between those with a pseudo-ternary indexed by $a.count-eq1. If the binary has at least one zero, the left case, we take the minimum of the length of the first [0] string of 1s and the last [-1] string (found by |sort and then [0]). The shorter of those is the most pairs we could remove, so we multiply that by 2. Note that if the original binary string ends in a 0, like for input 8, then the [-1].length will also be 0 (since it's an empty string), which when multiplied by 2 is still 0.
Otherwise, with the binary string all ones, we take just $b (which was previously set to be the length of the first [0] string, in this case, the entirety of the binary string).
In either situation, that result is left on the pipeline and output is implicit.

JavaScript (ES6), 57 bytes

f=
n=>n.toString(2).replace(/^(1*)(.*(\1))?$/,'$1$3').length
<input oninput=o.value=1/this.value?f(+this.value):''><input id=o readonly>

Takes the binary and tries to match all 1s or failing that an equal number of leading and trailing 1s.

C, 137 132 122 119 117 114 98 94 92 87 85 Bytes
Time to start golfing B-)
i,j;f(n){for(i=1<<30;i&~n;i/=2);for(j=0;n&i;n/=2,i/=4)j+=~n&1?i=0:2;return j-=n<1*j;}

Here's the proof
main()
{
  printf("%d %d\n", 0, f(0));
  printf("%d %d\n", 1, f(1));
  printf("%d %d\n", 8, f(8));
  printf("%d %d\n", 23, f(23));
  printf("%d %d\n", 31, f(31));
  printf("%d %d\n", 103, f(103));
  printf("%d %d\n", 127, f(127));
  printf("%d %d\n", 1877, f(1877));
  printf("%d %d\n", 2015, f(2015));
  printf("%d %d\n", 3167, f(3167));
}

and the output;
0 0
1 1
8 0
23 2
31 5
103 4
127 7
1877 2
2015 10
3167 4

Retina, 48 bytes
.+
$*
+`(1+)\1
$1o
o1
1
m(+`^1(.*)1$
xx¶$1
x|^1$

Try it online
Explanation:
.+              # Convert to unary
$*
+`(1+)\1        # Convert to binary (but with `o` instead of `0` -- it's shorter)
$1o
o1
1
m(+`^1(.*)1$    # Replace pairs of surrounding ones with `xx`
xx¶$1
x|^1$,          # Count x's, including the possibility of a single remaining `1`

C#, 133 bytes
Function that returns hardness. Takes integer from argument.
int h(int b){var n=Convert.ToString(b,2);for(b=0;;){if(n[0]+n[n.Length-1]==98)n=n.Substring(1,n.Length-2);else break;b+=2;}return b;}

Well, today I found out '1' + '1' = 98 in C#.

That's because '1' is the ASCII char 49, and 49 + 49 = 98.

I literally spent 10 minutes figuring out why my 1 + 1 = 2 didn't work. @FlipTack

C, 89 88 85 bytes
Saved two bytes due to @FlipTack pointing out a useless declaration.
Call f() with the number to test, the output is returned from the function.
t,h;f(l){for(t=l;t&&~t&1<<30;t*=2);for(h=0;t&1<<30&&l&1;t*=2,l/=2)++h;return h<<!!l;}

Try it on ideone.

Jelly, 14 bytes
Eo2
BµŒg.ịṂS×Ç

Try it online!

JavaScript (ES6), 59 58 bytes
f=(n,m=1<<30)=>m>n?f(n,m/2):m>1?n&m&&n&1&&2+f(n/2,m/4):n&1

Test cases

f=(n,m=1<<30)=>m>n?f(n,m/2):m>1?n&m&&n&1&&2+f(n/2,m/4):n&1

console.log(
  [0, 1, 8, 23, 31, 103, 127, 1877, 2015].map(
    n => n + ' -> ' + f(n)
  ).join('\n')
)

APL, 26 bytes
+/∘(∧\≢↑(∊⊢(,∧∧)¨⌽))2⊥⍣¯1⊢

Test cases:
      ( +/∘(∧\≢↑(∊⊢(,∧∧)¨⌽))2⊥⍣¯1⊢ ) ¨ 0 1 8 23 31 103 127 1877 2015
0 1 0 2 5 4 7 2 10

Explanation:

+/∘(∧\≢↑(∊⊢(,∧∧)¨⌽))2⊥⍣¯1⊢

                         ⊢   input
                    2⊥⍣¯1    convert to binary representation
   (               )
        (  ⊢    ¨⌽)          for each bit and its matching bit on the other side
            (  ∧)               take the logical and of both bits,
             ,                  make a list of both bits,
              ∧                 then take the and of the list and the and
         ∊                   flatten the resulting array
      ≢↑                     take only the first N bits, where N is the
                                length of the original list of bits
    ∧\                       take a running logical and (leaving only the
                                starting ones)
+/∘                          sum those

J, 22 bytes
(#<.2*(<.&(#.~)|.))@#:

This is based on the neat trick learned from this challenge.
Try it online!
Explanation
(#<.2*(<.&(#.~)|.))@#:  Input: integer n
                    #:  Binary digits of n
(                 )@    Operate on those digits D
               |.         Reverse D
       <.                 Take the minimum of
         &(#.~)           the "trailing truths" of D and reverse(D)
    2*                    Multiply by 2
 #                        The length of D
  <.                      Minimum of length and the previous result

Java (OpenJDK), 181 156 150 bytes
n->{int i=0;String s=n.toString(n,2);if(s.matches("1*"))i=s.length();else for(;!s.matches("(.*0)|(0.*)");s=s.substring(1,s.length()-1))i+=2;return i;}

Try it online!

Mathematica, 63 56 bytes
(2-Min[l=#~IntegerDigits~2])Min[Tr/@Split[l][[{1,-1}]]]&

Explanation
l=#~IntegerDigits~2

Generate the base-2 representation of the input, wrapped with a List. Store that in l
(2-Min[...])

If the min element of l is 1, output 1. If not, output 2. Multiply this by...
Split[l]

Split l into runs.
... [[{1,-1}]]

Take the first and the last element.
Tr/@ ...

Take the total of both.
Min[ ... ]

Find the smaller between the two.
(Multiply the first result (1 or 2) with this result).

Pyth, 18 bytes
?*FJjQ2lJyhSxR0_BJ

A program that takes input of an integer and prints the result.
Test suite (First line for formatting)
How it works
?*FJjQ2lJyhSxR0_BJ  Program. Input: Q
?                   If
  F                 reducing
    jQ2             the binary representation of Q as a list
   J                (store in J)
 *                  by multiplication is truthy:
       lJ            Yield len(J)
                    Else:
          hS         Yield the minimum
            xR0      of the first index of zero
               _BJ   in J and its reverse
         y           * 2
                    Implicitly print

Octave, 56 54 bytes
 @(n)cummin(d=dec2bin(n)-48)*cummin(flip(d))'*2^!all(d)

Try it Online!
Explanation:
d=dec2bin(n)-48

binary representation of n
cumd= cummin(d);
cumfd = cummin(flip(d));

Take cumulative min of d  and cumulative min of flipped d
res = cumd * cumfd ';

do matrix multiplication
out = res*2^!all(d)

multiply with 2 if all of digits is 1;

PHP, 83 74 bytes
3+6 bytes saved by Jörg
<?=(~$s=decbin($argn))[$a=strspn($s,1)]?min($a,strspn(strrev($s),1))*2:$a;

takes input from STDIN; run with -nR.
breakdown
<?=                     # print ...
(~
    $s=decbin($argn)        # $s = binary representation of input
)[
    $a=strspn($s,1)         # $a = number of leading `1`s
]                           # if $s has more than $a digits,
?   min($a,                     # 2. minimum of $a and
        strspn(strrev($s),1)    # 1. number of trailing `1`s
    )*2                         # 3. *2
:   $a                      # else $a (==strlen)

<?=~($s=decbin($argn))[$a=strspn($s,1)]?2*min($a,strspn(strrev($s),1)):$a;

Perl, 61 bytes
sub f{$_=sprintf('%b',pop);length(/0/?/^(1+).*\1$/&&$1x2:$_)}

The heart of this is the regex /^(1+).*\1$/ where 2 times the length of $1 is the answer.  Rest of the code is overhead and dealing with the all 1's special case.

You can omit the parenthesis around sprintf arguments. Also, using -p flag will allow you to write a full program that will be shorter than your function as you'll be able to omit sub f{...} (instead you'll have to end with $_=... but that's still a 4 bytes improvement). Finally, instead of your length(...), you can do /0/&&s/^(1+).*\1$/$1$1/;$_=y///c. This should get you to 51 bytes.

JavaScript (ES6), 83 Bytes
f=x=>(y=x.toString(2),y.match(/^1*$/)?y:([s,e]=y.match(/^1*|1*$/g),s<e?s:e)).length

Ungolfed:
function f(n) {
    var binStr = n.toString(2);
    if(binStr.match(/^1*$/)) {
        // If binary representation is all 1s, return length of binary
        return binStr.length;
    } else {
        // Grab the starting and ending 1s in the binary representation
        var [start1s, end1s] = binStr.match(/^1*|1*$/g);
        var startHardness = start1s.length;
        var endHardness = end1s.length;
        return Math.min(startHardness, endHardness);
    }
}

Haskell, 94 92 bytes
b 0=[]
b n=mod n 2:b(div n 2)
h n|(c,_:_)<-span(>0)$zipWith(*)n$reverse n=c++c|1<3=n
sum.h.b

Try it online! Usage:
Prelude> sum.h.b $ 3167
4

Explanation:
b converts a number to binary and returns a list of zero and ones with the least significant bit first. In h, this list is reversed and element-wise multiplied with the original list, then span(>0) splits after the initial 1s:
       b 3167 = [1,1,1,1,1,0,1,0,0,0,1,1] = n
    reverse n = [1,1,0,0,0,1,0,1,1,1,1,1] = m
zipWith(*)n m = [1,1,0,0,0,0,0,0,0,0,1,1] = z
   span(>0) z = ([1,1],[0,0,0,0,0,0,0,0,1,1])

The resulting tuple is pattern matched with (c,_:_) where _:_ matches any non-empty list, so c = [1,1]. Because the bytes are removed at front and back, c++c = [1,1,1,1] is returned and finally summed up to yield the digital hardness.
If the second list of the tuple is empty, then the binary representation contains ones only, and the number of ones is the digital hardness. With the pattern matching failed h returns just n, which is again summed up.

Mathematica, 62 bytes
(h=0;#~IntegerDigits~2//.{{1,m___,1}:>(h+=2;{m}),{1}:>h++};h)&

Pure function where # represents the first argument.
(h=0;...;h)& sets h=0, does a bunch of stuff ..., then returns h (the hardness). Let's look at the bunch of stuff:
#~IntegerDigits~2                                     Binary representation of the input
                 //.                                  Apply the following list of rules repeatedly until there is no change
                    {                                 Start of the list of rules
                     {1,m___,1}                       If you see a list starting and ending with 1 with the sequence m (possibly empty) in between
                               :>(h+=2;{m}),            replace it with just {m} after incrementing h twice.
                                            {1}       If you see the singleton list {1}
                                               :>h++    replace it with h, then increment h.
                                                    } End of the list of rules

Thanks to Greg Martin for introducing me to this trick.

PHP, 65 Bytes
<?=strlen(preg_filter('#^(1*)(.*(\1))?$#',"$1$3",decbin($argn)));

Online Version

CJam, 14 bytes
ri2b_0#\W%0#e<

Explanation:
ri e# Read integer:      | 3167
2b e# Convert to binary: | [1 1 0 0 0 1 0 1 1 1 1 1]
_  e# Duplicate:         | [1 1 0 0 0 1 0 1 1 1 1 1] [1 1 0 0 0 1 0 1 1 1 1 1]
0# e# Index of first 0:  | [1 1 0 0 0 1 0 1 1 1 1 1] 2
\  e# Swap:              | 2 [1 1 0 0 0 1 0 1 1 1 1 1]
W% e# Reverse:           | 2 [1 1 1 1 1 0 1 0 0 0 1 1]
0# e# Index of first 0:  | 2 5
e< e# Minimum:           | 2


text:
Combinatory Conundrum!
Introduction: Combinatory Logic
Combinatory logic (CL) is based off of things called combinators, which are basically functions. There are two basic "built-in" combinators, S and K, which will be explained later.
Left-associativity
CL is left-associative, which means brackets (containing stuff) which are at the far-left of anther pair of brackets containing it can be removed, with its stuff released. For example, something like this:
((a b) c)

Can be reduced to
(a b c)

Where the (a b) is on the far-left of the bigger bracket ((a b) c), so it can be removed.
A much bigger example of left-association (square brackets are explanations):
  ((a b) c ((d e) f (((g h) i) j)))
= (a b c ((d e) f (((g h) i) j)))   [((a b) c...) = (a b c...)]
= (a b c (d e f (((g h) i) j)))     [((d e) f...) = (d e f...)]
= (a b c (d e f ((g h i) j)))       [((g h) i) = (g h i)]
= (a b c (d e f (g h i j)))         [((g h i) j) = (g h i j)]

Brackets can also be reduced when more than one pair wrap around the same objects. Examples:
((((a)))) -> a
a ((((b)))) -> a b
a (((b c))) -> a (b c) [(b c) is still a group, and therefore need brackets.
                        Note that this doesn't reduce to `a b c`, because
                        `(b c)` is not on the left.]

Builtins
CL has two "built-in" combinators, S and K, which can switch objects (single combinators, or a group of combinators / groups wrapped around brackets) around like so:
K x y = x
S x y z = x z (y z)

Where x, y and z can be stand-ins for anything.
An example of S and K are as follows:
  (S K K) x [x is a stand-in for anything]
= S K K x   [left-associativity]
= K x (K x) [S combinator]
= x         [K combinator]

Another example:
  S a b c d
= a c (b c) d [combinators only work on the n objects to the right of it,
               where n is the number of "arguments" n is defined to have -
               S takes 3 arguments, so it only works on 3 terms]

The above are examples of normal CL statements, where the statement cannot be evaluated further and achieves an end result in a finite amount of time. There are non-normal statements (which are CL statements that do not terminate and will keep being evaluated forever), but they aren't within the scopes of the challenge and won't need to be covered.
If you want to learn more about CL, read this Wikipedia page.
Task:
Your task is to make extra combinators, given the number of arguments, and what it evaluates to as input, which is given like so:
{amount_of_args} = {evaluated}

Where {amount_of_args} is a positive integer equal to the number of args, and {evaluated} consists of:

arguments up to the amount of args, with 1 being the first argument, 2 being the second, etcetera.

You are guaranteed that argument numbers above the amount of args (so a 4 when {amount_of_args} is only 3) won't appear in {evaluated}.

brackets ()

So examples of inputs are:
3 = 2 3 1
4 = 1 (2 (3 4))

The first input is asking for a combinator (say, R) with three arguments (R 1 2 3), which then evaluates into:
R 1 2 3 -> 2 3 1

The second input asks for this (with a combinator name A):
A 1 2 3 4 -> 1 (2 (3 4))

Given the input in this format, you must return a string of S, K and (), which when substituted with a combinator name and run with arguments, returns the same evaluated statement as the {evaluated} block when the command block is substituted back for that combinator name.
The output combinator statement may have its whitespace removed and the outer brackets removed, so something like (S K K (S S)) can be turned into SKK(SS).
If you want to test your program's outputs, @aditsu has made a combinatory logic parser (which includes S, K, I and even other ones like B and C) here.
Score:
Since this is a metagolf, the aim of this challenge is to achieve the smallest amount of bytes in the output possible, given these 50 test-cases. Please put your results for the 50 test-cases in the answer, or make a pastebin (or something similar) and post a link to that pastebin.
In the event of a tie, the earliest solution wins.
Rules:

Your answer must return CORRECT output - so given an input, it must return the correct output as per the definition in the task.
Your answer must output within an hour on a modern laptop for each test case.
Any hard-coding of solutions is disallowed. However, you are allowed to hard-code up to 10 combinators.
Your program must return the same solution every time for the same input.
Your program must return a valid result for any input given, not just test-cases.

How can you make sure that people won't steal combinators found in other answers?

@Fatalize That shouldn't matter too much, as people can take inspiration from other people's answers and build on that to create better answers.

Speaking of inspiration, I notice that when the desired result does not contain a 1, you can subtract 1 from everything, and then wrap solution for that answer in K(). Example: Solution for 2 -> 1 is K, therefore solution for 3 -> 2 is KK, solution for 4 -> 3 is K(KK) etc.

Haskell, score 5017
This combines the dumbest possible algorithm for abstraction elimination ((λx. x) = I; (λx. y) = Ky; (λx. M N) = S(λx. M)(λx. N)) with a peephole optimizer used after every application.  The most important optimization rule is S(Kx)(Ky) ↦ K(xy), which stops the algorithm from always blowing up exponentially.
The set of rules is configured as a list of string pairs so it’s easy to play around with new rules.  As a special bonus of reusing the input parser for this purpose, S, K, and I are also accepted within the input combinators.
Rules are not applied unconditionally; rather, both the old and new versions are kept, and suboptimal versions are pruned only when their length exceeds that of the best version by more than some constant (currently 3 bytes).
The score is slightly improved by treating I as a fundamental combinator until the output stage rewrites it to SKK.  That way KI = K(SKK) can be shortened by 4 bytes to SK on output without confusing the rest of the optimizations.
{-# LANGUAGE ViewPatterns #-}

import qualified Data.IntMap as I
import qualified Data.List.NonEmpty as N
import System.IO

data Term
  = V Int
  | S
  | K
  | I
  | A (N.NonEmpty (Int, Term, Term))
  deriving (Show, Eq, Ord)

parse :: String -> (Term, String)
parse = parseApp . parse1

parseApp :: (Term, String) -> (Term, String)
parseApp (t, ' ':s) = parseApp (t, s)
parseApp (t, "") = (t, "")
parseApp (t, ')':s) = (t, ')' : s)
parseApp (t1, parse1 -> (t2, s)) =
  parseApp (A (pure (appLen (t1, t2), t1, t2)), s)

parse1 :: String -> (Term, String)
parse1 (' ':s) = parse1 s
parse1 ('(':(parse -> (t, ')':s))) = (t, s)
parse1 ('S':s) = (S, s)
parse1 ('K':s) = (K, s)
parse1 ('I':s) = (I, s)
parse1 (lex -> [(i, s)]) = (V (read i), s)

ruleStrings :: [(String, String)]
ruleStrings =
  [ ("1 3(2 3)", "S1 2 3")
  , ("S(K(S(K1)))(S(K(S(K2)))3)", "S(K(S(K(S(K1)2))))3")
  , ("S(K(S(K1)))(S(K2))", "S(K(S(K1)2))")
  , ("S(K1)(K2)", "K(1 2)")
  , ("S(K1)I", "1")
  , ("S(S(K1)2)(K3)", "S(K(S1(K3)))2")
  , ("S(SI1)I", "S(SSK)1")
  ]

rules :: [(Term, Term)]
rules = [(a, b) | (parse -> (a, ""), parse -> (b, "")) <- ruleStrings]

len :: Term -> Int
len (V _) = 1
len S = 1
len K = 1
len I = 3
len (A ((l, _, _) N.:| _)) = l

appLen :: (Term, Term) -> Int
appLen (t1, S) = len t1 + 1
appLen (t1, K) = len t1 + 1
appLen (K, I) = 2
appLen (t1, t2) = len t1 + len t2 + 2

notA :: Term -> Bool
notA (A _) = False
notA _ = True

alt :: N.NonEmpty Term -> Term
alt ts =
  head $
  N.filter notA ts ++
  [A (N.nub (a N.:| filter (\(l, _, _) -> l <= minLen + 3) aa))]
  where
    a@(minLen, _, _) N.:| aa =
      N.sort $ do
        A b <- ts
        b

match :: Term -> Term -> I.IntMap Term -> [I.IntMap Term]
match (V i) t m =
  case I.lookup i m of
    Just ((/= t) -> True) -> []
    _ -> [I.insert i t m]
match S S m = [m]
match K K m = [m]
match I I m = [m]
match (A a) (A a') m = do
  (_, t1, t2) <- N.toList a
  (_, t1', t2') <- N.toList a'
  m1 <- match t1 t1' m
  match t2 t2' m1
match _ _ _ = []

sub :: I.IntMap Term -> Term -> Term
sub _ S = S
sub _ K = K
sub _ I = I
sub m (V i) = m I.! i
sub m (A a) =
  alt $ do
    (_, t1, t2) <- a
    pure (sub m t1 & sub m t2)

optimize :: Term -> Term
optimize t = alt $ t N.:| [sub m b | (a, b) <- rules, m <- match a t I.empty]

infixl 5 &

(&) :: Term -> Term -> Term
t1 & t2 = optimize (A (pure (appLen (t1, t2), t1, t2)))

elim :: Int -> Term -> Term
elim n (V ((== n) -> True)) = I
elim n (A a) =
  alt $ do
    (_, t1, t2) <- a
    pure (S & elim n t1 & elim n t2)
elim _ t = K & t

paren :: String -> Bool -> String
paren s True = "(" ++ s ++ ")"
paren s False = s

output :: Term -> Bool -> String
output S = const "S"
output K = const "K"
output I = paren "SKK"
output (V i) = \_ -> show i ++ " "
output (A ((_, K, I) N.:| _)) = paren "SK"
output (A ((_, t1, t2) N.:| _)) = paren (output t1 False ++ output t2 True)

convert :: Int -> Term -> Term
convert 0 t = t
convert n t = convert (n - 1) (elim n t)

process :: String -> String
process (lex -> [(n, lex -> [((`elem` ["=", "->"]) -> True, parse -> (t, ""))])]) =
  output (convert (read n) t) False

main :: IO ()
main = do
  line <- getLine
  putStrLn (process line)
  hFlush stdout
  main

Try it online!
Output

S(KS)K
S(K(SS(KK)))(S(KK)S)
S(K(SS))(S(KK)K)
S(K(SS(KK)))(S(KK)(S(KS)(S(K(S(SKK)))K)))
S(K(S(K(SS(SK)))))(S(K(SS(SK)))(S(SKK)(SKK)))
KK
S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)
S(K(SS(K(S(KK)(S(SKK)(SKK))))))(S(SSK(KS))(S(S(KS)(S(KK)(S(KS)K)))(K(S(K(S(SSK)))K))))
S(K(S(KK)))(S(K(S(S(SKK)(SKK))))K)
SK
S(KS)(S(KK)(S(K(SS))(S(KK)K)))
S(K(SS(K(S(KK)K))))(S(KK)(S(KS)(S(SSK(KS))(S(K(SS))(S(KK)K)))))
S(K(S(K(S(K(SS(KK)))(S(KK)S)))))(S(K(SS(KK)))(S(KK)(S(KS)(S(K(S(SKK)))K))))
S(K(S(K(S(K(SS(KK)))(S(KK)S)))))(S(K(S(SKK)))K)
S(K(S(K(S(KS)K))))(S(KS)K)
S(K(S(KS)K))
S(K(S(K(S(K(SS(K(S(S(KS)(S(KK)(SSK)))(K(S(SKK)(SKK)))))))(S(KK)(S(KS)K))))))(S(K(SS(K(SSK))))(S(KK)(S(KS)(S(KK)(SSK)))))
SSS(KK)
KK
S(KK)(S(KK)(S(S(KS)K)(S(K(S(SKK)))(S(K(S(SKK)))K))))
S(S(KS)(S(KK)(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))(K(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)))
S(KK)
S(KS)(S(KK)(S(KS)(S(KK)(S(K(SS))(S(KK)K)))))
S(K(S(K(S(KS)K))))(S(K(S(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))(S(KK)(S(K(SS))(S(KK)K))))
S(KS)(S(KK)(S(KS)K))
S(S(KS)(S(KK)(S(KS)(S(KK)(S(K(S(K(SS(KK)))))(S(KS)(S(KK)(S(SSK(KS))(S(KS)(S(SKK)(SKK)))))))))))(K(S(S(KS)(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(SKK)))K))))))))(S(K(S(SKK)))K)))(S(K(S(K(S(KK)K))))(S(K(S(SKK)))K))))
S(K(S(K(S(K(SS(K(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)))))(S(KK)(S(KS)K))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))
K(S(KK))
S(K(S(K(S(K(S(K(S(KS)K))))(S(K(S(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))K)))))(S(K(S(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))(S(KK)(S(K(SS))(S(KK)K))))
S(KK)(S(K(SSS(KK))))
K(SSS(KK))
S(K(SS(K(S(S(KS)(S(KK)(S(KS)K)))(K(S(K(S(SKK)))K))))))(S(KK)(S(KS)(SS(S(S(KS)(S(KK)(S(KS)(S(K(S(KS)(S(KK)(S(KS)K)))))))))(KK))))
S(K(S(K(S(K(S(K(SS(KK)))(S(KK)S)))))))(S(K(SS(K(S(KK)K))))(S(KK)(SSS(KS))))
S(K(S(K(S(KK)K))))
S(K(S(K(S(K(S(K(SS(K(S(K(S(SKK)))K))))(S(KK)(S(KS)(S(KK)(S(K(SS(K(S(K(S(SKK)))K))))(S(KK)(S(K(SS))(S(KK)K)))))))))))))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K))
S(K(SS(K(S(K(SS(K(S(K(S(SKK)))K))))(S(KK)(S(KS)(SS(S(S(KS)(S(KK)(S(KS)(S(K(S(SKK)))K)))))(KK))))))))(S(KK)(S(KS)(S(KK)(S(K(S(K(S(K(S(K(S(K(SS(KK)))(S(KK)S)))))))))(S(K(SS(KK)))(S(KK)(S(KS)(S(K(S(KS)(S(KK)(S(KS)K))))))))))))
S(KK)(S(K(S(K(S(KK)(S(KK)K)))))(SS(SK)))
K(S(K(SSS(KK))))
S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)))))(S(KK)(S(KS)K))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))
S(K(S(KK)))(S(KS)(S(KK)(S(K(S(KK)(S(KK)K))))))
S(K(SS(K(S(S(KS)(S(KK)(S(KS)K)))(K(S(K(S(SKK)))K))))))(S(KK)(S(KS)(S(KK)(S(K(S(K(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K))))))(S(K(SS(K(S(KK)(S(K(SS))K)))))(S(KK)(S(K(SS))(S(KK)(S(K(S(K(S(KK)(S(KS)K)))))(S(KS)K))))))))))
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)))))(S(KK)(S(KS)K))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))
K(K(K(K(K(S(KK)(S(KK)(S(K(SS(SK)))(SSK))))))))
S(KK)(S(K(S(KK)(S(KK)(S(KK)(S(KK)K))))))
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)))))(S(KK)(S(KS)K))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))
S(K(S(K(S(K(S(K(S(K(SS(K(S(K(SS(K(S(K(SS(KK)))(S(KK)(S(KS)(S(K(S(SKK)))K)))))))(S(KK)(S(KS)(S(KK)(S(SSK(KS))(S(K(SS))(S(KK)K))))))))))(S(KK)(S(KS)(S(KK)(S(K(SS(K(S(KK)(S(KS)(S(KK)(S(K(SS(K(S(KK)(S(KS)K)))))(S(KK)(S(K(SS))(S(KK)(S(K(SS(K(S(KK)K))))(S(KK)S))))))))))))(S(KK)(S(K(SS))K))))))))))(S(K(SS(K(S(KK)(S(K(S(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))(S(KK)(S(K(SS))(S(KK)K))))))))(S(KK)S))))))(S(K(SS(K(S(K(S(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))(S(KK)(S(K(SS))(S(KK)K)))))))(S(KK)(S(KS)(S(KK)(S(K(S(K(S(KS)(S(KK)(S(KS)K))))))(S(KS)(S(KK)(S(K(SS))(S(KK)K)))))))))
S(K(SS(K(SS(S(S(KS)(S(KK)S)))(KK)))))(S(KK)(S(KS)(S(K(S(K(S(KS)(S(KK)(S(KS)(S(KK)(S(K(S(K(S(K(SS(K(S(K(S(S(KS)(S(KK)(S(K(SS))(S(KK)K))))))(S(KK)(S(K(SS))(S(KK)K)))))))(S(KK)(S(KS)K))))))))))))))(S(K(S(S(KS)(S(KK)(S(K(SS))(S(KK)(S(K(S(K(S(KS)K))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)(S(KK)(S(K(SS))(S(KK)K)))))))))))))(S(KK)(S(K(S(K(S(KK)(S(KS)(S(KK)(S(K(SS(K(S(KK)(S(KS)K)))))(S(KK)(S(K(SS))K)))))))))(S(KS)(S(KK)(S(K(SS(K(S(KK)K))))(S(KK)(S(KS)(S(SSK(KS))(S(K(SS(KK)))(S(KK)(S(KS)(S(K(S(SKK)))K))))))))))))))))
K(S(K(S(KK)(S(K(S(KK)(S(K(S(KK)(S(KK)K))))))))))
S(KK)(S(K(S(K(S(KK)(S(K(S(K(S(KK)(S(K(S(K(S(KK)(S(K(S(K(S(KK)(S(K(S(KK)))(S(K(S(SKK)))K))))))(S(K(S(SKK)))K))))))(S(K(S(SKK)))K))))))(S(K(S(SKK)))K))))))(S(K(S(SKK)))K))
S(K(S(K(S(K(S(K(S(K(S(KK)))(S(K(SS(K(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)K)))))))(S(K(SS(K(S(K(SS))(S(KK)K)))))(S(KK)(S(KS)(S(KK)(S(K(S(K(S(KK)(S(KK)(S(KK)(S(KK)K)))))))(S(K(SS))(S(KK)K)))))))

Would it be possible to make the expressions auto-optimize (eg S (K x) (K y) = K (x y))?

@CalculatorFeline I don’t understand your question; S(Kx)(Ky) is automatically optimized to K(xy).

Wait, are these expressions represented as partially applied functions or something else? If partially applied functions, then maybe you could do something like my last comment.

@CalculatorFeline The representation looks like, for example, 3=1(2 3) ↦ 2=S(K1)(S(K2)I) ↦ 2=S(K1)2 ↦ 1=S(S(KS)(S(KK)(K1)))I ↦ 1=S(S(KS)(K(K1)))I ↦ 1=S(K(S(K1)))I ↦ 1=S(K(S(K1)))I ↦ 1=S(K1) ↦ S(KS)(S(KK)I) ↦ S(KS)K. As you can see, we have already used the rule S(Kx)(Ky) ↦ K(xy) many times, along with the others I listed in ruleStrings. If we didn’t, the output would be exponentially longer: for this tiny example, we’d have gotten S(S(KS)(S(S(KS)(S(KK)(KS)))(S(S(KS)(S(KK)(KK)))(S(KK)(SKK)))))(S(S(KS)(S(S(KS)(S(KK)(KS)))(S(S(KS)(S(KK)(KK)))(SK))))(S(KK)(SK))) instead of S(KS)K.

Sum of solution lengths: 12945 8508 5872
Haskell code that takes input lines from stdin and doesn't care if the separator is = or ->:
data E=S|K|V Int|A E E deriving Eq

instance Show E where
  showsPrec _ S = showChar 'S'
  showsPrec _ K = showChar 'K'
  showsPrec _ (V i) = shows i
  showsPrec p (A e f) = showParen (p>0) $ showsPrec 0 e . showsPrec 1 f

type SRead a = String -> (a,String) -- a simpler variation of ReadS

parse :: String -> E
parse s = let (e,"")=parseList (s++")") in e
parseList :: SRead E
parseList s = let (l,s')=parseL s in (foldl1 A l,s')
parseL :: SRead [E]
parseL (c:s) | c==' ' = parseL s
             | c==')' = ([],s)
parseL s = let (p,s')=parseExp s; (l,s'')=parseL s' in (p:l,s'')
parseExp :: SRead E
parseExp ('(':s) = parseList s
parseExp s = let [(n,s')]=reads s in (V n,s')

k e = A K e
s e f = A (A S e) f
i = s K K
s3 e f g = A (s e f) g
sk = A S K
ssk e f = A (s3 S K e) f

n `invars` (A e f) = n `invars` e || n `invars` f
n `invars` (V m)   = n==m
_ `invars` _       = False

comb (A e f) = comb e && comb f
comb (V _)   = False
comb _       = True

abstract _ (A (A S K) _) = sk
abstract n e | not (n `invars` e) = k e
abstract n (A e (V _)) | not (n `invars` e) = e
abstract n (A (A (V i) e) (V j)) | n==i && n==j =
                                   abstract n (ssk (V i) e)
abstract n (A e (A f g)) | comb e && comb f =
                                   abstract n (s3 (abstract n e) f g)
abstract n (A (A e f) g) | comb e && comb g =
                                   abstract n (s3 e (abstract n g) f)
abstract n (A (A e f) (A g h)) | comb e && comb g && f==h =
                                   abstract n (s3 e g f)
abstract n (A e f) = s (abstract n e) (abstract n f)
abstract n _ = i

abstractAll 0 e = e
abstractAll n e = abstractAll (n-1) $ abstract n e

parseLine :: String -> (Int,E)
parseLine s = let [(n,s')] = reads s
                  s''=dropWhile(`elem` " =->") s'
              in (n, parse s'')

solveLine :: String -> E
solveLine s = let (n,e) = parseLine s in abstractAll n e

main = interact $ unlines . map (show . solveLine) . lines

It implements the improved bracket abstraction from section 3.2 of John Tromp: Binary Lambda Calculus and Combinatory Logic which is linked to from the Wikipedia article on combinatory logic. The most useful special cases only use the S combinator to suffle subterms around in order to avoid deep nesting of variables. The case that checks for equality of some subterms is not needed for any of the test cases. While there is no special case for handling the W combinator (see Peter's answer), the rules work together to find the shorter SS(SK) expression. (I first made a mistake by trying to optimize away the inner calls to abstract, then this W optimization did not happen and the overall result was 16 bytes longer.)
And here are the results from the test cases:
S(KS)K
S(K(S(K(SS(KK)))K))S
S(K(S(K(SS))K))K
S(K(S(K(S(K(S(K(SS(KK)))K))S))(S(SKK))))K
S(K(S(K(SS(SK)))))(S(K(SS(SK)))(S(SKK)(SKK)))
KK
S(K(S(K(S(S(K(S(KS)(S(SKK))))K)))K))K
S(K(S(K(SS(K(S(KK)(S(SKK)(SKK))))))(S(KS))))(S(K(S(K(S(K(SS(K(S(K(S(SSK)))K))))K))S))K)
S(K(S(K(S(KK)))(S(S(SKK)(SKK)))))K
SK
S(K(S(K(S(K(S(S(KS)(S(KS)))))K))K))K
S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(KK)K))))K))S))(S(KS))))(SS)))K))K
S(K(S(K(S(K(S(K(SS(KK)))K))S))))(S(K(S(K(S(K(S(K(SS(KK)))K))S))(S(SKK))))K)
S(K(S(K(S(K(S(K(S(K(SS(KK)))K))S))))(S(SKK))))K
S(K(S(K(S(K(S(K(S(K(SS(K(S(KS)K))))K))S))K))S))K
S(K(S(KS)K))
S(S(K(S(KS)(S(K(S(KS)(S(KS)))))))(S(K(S(K(S(K(S(K(S(K(SS(K(S(S(K(S(KS)(S(KS))))(S(K(S(K(S(K(SS(K(S(S(KS)(S(K(SS(K(S(SKK)(SKK)))))K))K))))K))S))K))(S(KK)K)))))K))S))K))S))K))(S(K(S(KK)K))K)
S(KK)(S(KK))
KK
S(K(S(KK)K))(S(S(KS)K)(S(K(S(K(S(SKK)))(S(SKK))))K))
S(K(S(K(S(K(S(S(K(S(K(S(K(S(KS)(S(KS))))(S(S(K(S(KS)(S(SKK))))K))))K))K)))K))K))K
S(KK)
S(K(S(K(S(K(S(K(S(S(KS)(S(K(S(KS)(S(KS))))))))K))K))K))K
S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)K))K))))K))S))(S(K(S(KS)(S(KS)))))))(S(S(KS)(S(KS))))))K))K))K
S(K(S(K(S(KS)K))S))K
S(K(S(K(S(K(S(K(SS(KK)))(S(KS))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(K(S(KS)(S(SKK))))K))))))))(S(SKK))))K)(S(K(S(K(S(K(S(KK)K))))(S(SKK))))K)))))K))S))K))S))K))S))(S(SKK)(SKK)))
S(K(S(K(S(K(S(K(S(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(KS)))))))(S(S(K(S(K(S(K(S(KS)(S(KS))))(S(S(K(S(KS)(S(SKK))))K))))K))K))))K))K))K)))K))K))K))K
K(S(KK))
S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)K))K))))K))S))(S(K(S(KS)(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)K))K))))K))S))(S(K(S(KS)(S(KS)))))))(S(S(KS)(S(KS))))))K))K))K)
S(KK)(S(K(S(KK)(S(KK)))))
K(S(KK)(S(KK)))
S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)))(S(K(S(K(S(K(SS(K(S(K(S(SKK)))K))))K))S))K)))))K))S))K))S))(S(K(S(K(S(K(S(KS)K))S))K)))
S(K(S(K(S(K(S(K(S(K(SS(KK)))K))S))))))(S(K(S(K(S(K(SS(K(S(KK)K))))K))S))(S(KS)))
S(K(S(K(S(KK)K))))
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(S(K(S(K(S(KS)(S(K(S(K(S(KS)(S(SKK))))K)))))(S(SKK))))K)))K))K))K))))))(S(S(K(S(KS)(S(SKK))))K))))K))K
S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(KK)))K))S))))))))))(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)))(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(K(S(KK)))(S(SKK))))K))))K))S))K))S))(S(SKK))))K)))))K))S))K))S))(S(K(S(K(S(K(S(KS)K))S))K))))
S(K(S(KK)(S(K(S(K(S(KK)K))K)))))(SS(SK))
K(S(K(S(KK)(S(KK)))))
S(K(S(K(S(K(S(K(S(K(S(K(S(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))(S(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(KS)))))))(S(S(K(S(K(S(K(S(KS)(S(KS))))(S(S(K(S(KS)(S(SKK))))K))))K))K))))K))K))K))))K))K))K))K))))K))K))K))K))K)))K))K))K))K))K))K
S(K(S(K(S(K(S(KK)(S(K(S(K(S(KK)K))K)))))))S))K
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)K))K))))K))S))(S(K(S(KS)(S(KS)))))))(S(S(K(S(K(S(KS)K))S))K))))K))))(S(K(S(K(S(K(SS(K(S(K(S(SKK)))K))))K))S))K)))))K))S))K))S))K))S))K))S))K))S))K
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))(S(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(KS)))))))(S(S(K(S(K(S(K(S(KS)(S(KS))))(S(S(K(S(KS)(S(SKK))))K))))K))K))))K))K))K))))K))K))K))K))))K))K))K))K))K))))K))K))K))K))K))K)))K))K))K))K))K))K))K
K(K(K(K(K(S(K(S(KK)K))(S(K(SS(SK)))(SSK)))))))
S(KK)(S(K(S(K(S(K(S(K(S(KK)K))K))K))K)))
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))(S(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(KS)))))))(S(S(K(S(K(S(K(S(KS)(S(KS))))(S(S(K(S(KS)(S(SKK))))K))))K))K))))K))K))K))))K))K))K))K))))K))K))K))K))K))))K))K))K))K))K))K))))K))K))K))K))K))K))K)))K))K))K))K))K))K))K))K
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))))))))(S(K(S(K(S(K(S(K(SS(K(S(K(S(K(S(KK)K))K))K))))K))S))(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)K))K))))K))S))(S(K(S(KS)(S(KS)))))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))(S(K(S(K(S(K(S(K(SS(K(S(KK)K))))K))S))(S(KS)))))))(S(S(K(S(KS)(S(KS))))(S(K(S(K(S(K(S(K(SS(KK)))K))S))(S(SKK))))K)))))K))K))K))))K))K))K))K))K))))K))K))K))K))K))K))K)))K))K))K))K))K))K))K))K))K
S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KK)K))K))K))K))K))K))K))))K))S))(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))))))))(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(K(S(K(S(KK)K))K))K))K))))K))S))(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS)))))))))))))(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)K))K))))K))S))(S(K(S(KS)(S(KS)))))))))))))(S(K(S(K(S(K(S(K(SS(K(S(K(S(KK)K))K))))K))S))(S(K(S(KS)(S(KS)))))))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(SS(K(S(K(S(K(S(K(S(K(S(KK)K))))))))(S(K(S(K(SS(KK)))K))S)))))K))S))K))S))K))S))K))S))(S(KS))))(S(K(S(K(S(K(S(K(SS(KK)))K))S))(S(SKK))))K))
K(S(K(S(KK)(S(K(S(KK)(S(K(S(K(S(KK)K))K)))))))))
S(K(S(K(S(KK)(S(K(S(K(S(K(S(KK)(S(K(S(K(S(K(S(KK)(S(K(S(K(S(K(S(KK)(S(K(S(K(S(K(S(KK)(S(KK))))(S(SKK))))K)))))(S(SKK))))K)))))(S(SKK))))K)))))(S(SKK))))K)))))(S(SKK))))K
S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KK)(S(K(S(K(S(K(S(K(S(KK)K))K))K))K)))))))))))(S(S(K(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(K(S(KS)(S(KS))))))))))(S(S(K(S(K(S(K(S(K(S(KS)(S(K(S(KS)(S(KS)))))))(S(S(K(S(K(S(K(S(KS)(S(KS))))(S(S(K(S(KS)(S(SKK))))K))))K))K))))K))K))K))))K))K))K))K))))K))K))K))K))K

8486 using S, K, I, W
Explanation
The standard algorithm (as described e.g. in chapter 18 of To Mock a Mockingbird) uses four cases, corresponding to the combinators S, K, I = SKK, and simple left-association. I think this is what Christian's answer implements. This is sufficient, but not necessarily optimal, and since we're allowed to hard-code up to 10 combinators it leaves 7 options.
Other well-known combinatorial combinators are
B x y z = x (y z)
C x y z = x z y
W x y = x y y

which, together with K, make a complete basis. In SK these are
B = S (K S) K
C = S (S (K (S (K S) K)) S) (K K)
W = S S (S K)

and the SKI rules derive those same expressions for B and C, but for W they derive S S (K (S K K)). I therefore chose to implement W as a special case.
Program (CJam)
e# A tests whether argument is an array
{W=!!}:A;

e# F "flattens" an expression by removing unnecessary parentheses, although if the expression is a primitive
e# it actually wraps it in an array
{
  e# A primitive is already flat, so we only need to process arrays
  _A{
    ee{
      ~
      e# Stack: ... index elt
      e# First recurse to see how far that simplifies the element
      F
      e# If it's an array...
      _A{
        e# ... we can drop a level of nesting if either it's the first one (since combinator application
        e# is left-associative) or if it's a one-element array
        _,1=@!|{
          e# The tricky bit is that it might be a string, so we can't just use ~
          {}/
        }*
      }{
        \;
      }?
    }%
  }{a}?
}:F;

qN%{

e# Parse line of input
"->=()"" [[[]"er']+~
e# Eliminate the appropriate variables in reverse order. E eliminates the variable currently stored in V.
\,:)W%{
  e# Flatten current expression
  F

  e# Identify cases; X holds the eXpression and is guaranteed to be non-primitive
  :X
  [
    XVa=                  e# [V]
    Xe_V&!                e# case V-free expression
    X)_A0{V=}?\e_V&!*     e# case array with exactly one V, which is the last element
    X_e_Ve=~)>[VV]=X,2>*  e# case array with exactly two Vs, which are the last two elements
  ]
  1#
  e# Corresponding combinators
  [
    {;"SKK"}              e# I
    {['K\]}               e# K
    {);}                  e# X (less that final V)
    {););['S 'S "SK"]\a+} e# W special-cased as SS(SK) because the general-case algorithm derives SS(K(SKK))
    {['S\)E\E\]}          e# S (catch-all case)
  ]=~
}:EfV

e# Format for output
F
{
  _A{
    '(\{P}%')
  }*
}:P%

oNo}/

Online test suite
Generated outputs:
S(KS)K
S(S(KS)(S(KK)S))(KK)
S(K(SS))(S(KK)K)
S(S(KS)(S(KK)(S(KS)(S(K(S(SKK)))K))))(KK)
S(K(S(K(SS(SK)))))(S(K(SS(SK)))(S(SKK)(SKK)))
KK
S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)
S(S(KS)(S(K(S(KS)))(S(S(KS)(S(KK)(S(KS)K)))(K(S(S(KS)(S(K(S(SKK)))K))(K(SKK)))))))(K(S(KK)(S(SKK)(SKK))))
S(K(S(KK)))(S(K(S(S(SKK)(SKK))))K)
K(SKK)
S(K(S(S(KS)(S(KS)))))(S(KK)(S(KK)K))
S(S(KS)(S(KK)(S(KS)(S(K(S(KS)))(S(K(SS))(S(KK)K))))))(K(S(KK)K))
S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(S(KS)(S(KK)(S(KS)(S(K(S(SKK)))K))))(KK))))))(K(KK))
S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(K(S(SKK)))K)))))(K(KK))
S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)K)))))(K(S(KS)K))
S(K(S(KS)))(S(KK))
S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)K)))))(K(S(S(KS)(S(K(S(KS)))(S(S(KS)(S(KK)(S(KS)K)))(K(S(S(KS)(S(S(KS)K)(K(S(SKK)(SKK)))))K)))))(S(KK)K)))))))(S(KK)(S(KK)K))
S(KK)(S(KK))
KK
S(KK)(S(KK)(S(S(KS)K)(S(K(S(SKK)))(S(K(S(SKK)))K))))
S(K(S(S(KS)(S(K(S(KS)))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K))))))(S(KK)(S(KK)K))
S(KK)
S(K(S(S(KS)(S(K(S(KS)))(S(K(S(KS))))))))(S(KK)(S(KK)(S(KK)K)))
S(S(KS)(S(KK)(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(KS)))))(S(KK)(S(KK)K))))))))(K(S(KK)(S(KK)K)))
S(KS)(S(KK)(S(KS)K))
S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(SKK)(SKK)))))))))(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(SKK)))))))(S(K(S(K(S(KK)))))(S(K(S(SKK)))K))))))(S(K(S(KK)))(S(K(S(KK)))(S(K(S(SKK)))K))))))))))(K(K(KK)))
S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K))))))(S(KK)(S(KK)K))))))))(S(KK)(S(KK)(S(KK)K)))
K(S(KK))
S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(S(KS)(S(KK)(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(KS)))))(S(KK)(S(KK)K))))))))(K(S(KK)(S(KK)K))))))))))(K(K(S(KK)(S(KK)K))))
S(KK)(S(K(S(KK)))(S(K(S(KK)))))
K(S(KK)(S(KK)))
S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(KK))))))))))(K(S(K(S(KK)))(S(S(KS)(S(KK)(S(KS)K)))(K(S(K(S(SKK)))K)))))
S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(KK)))))(S(K(S(K(S(KS)))))(S(S(KS)(S(KK)(S(KS)(S(KS)))))(K(S(KK)K))))))))(K(K(KK)))
S(K(S(K(S(KK)))))(S(K(S(KK))))
S(K(S(K(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(SKK)))))(S(K(S(KK)))(S(K(S(SKK)))K)))))))))))(S(K(S(K(S(KK)))))(S(K(S(K(S(KK)))))(S(K(S(K(S(KK)))))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K)))))
S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(KK))))))))))(K(S(K(S(KK)))(S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(K(S(SKK)))K))))))(K(S(K(S(KK)))(S(K(S(SKK)))K))))))))))))))(K(K(K(K(KK)))))
S(KK)(S(K(S(KK)))(S(K(S(KK)))(S(K(S(KK)))(SS(SK)))))
K(S(K(S(KK)))(S(K(S(KK)))))
S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K))))))(S(KK)(S(KK)K))))))))(S(KK)(S(KK)(S(KK)K))))))))))(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K)))))
S(K(S(KK)))(S(K(S(K(S(KK)))))(S(K(S(K(S(KK)))))(S(K(S(K(S(KK)))))(S(KS)K))))
S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)K)))))))))))(K(S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(S(KS)(S(KK)(S(KS)K)))))))(S(K(S(KK)))(S(S(KS)(S(KK)(S(KS)K)))(K(S(K(S(SKK)))K)))))))))))(K(K(S(KK)(S(KK)K))))))
S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K))))))(S(KK)(S(KK)K))))))))(S(KK)(S(KK)(S(KK)K))))))))))(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K))))))
K(K(K(K(K(S(KK)(S(KK)(S(S(KS)(SSK))(K(SKK)))))))))
S(KK)(S(K(S(KK)))(S(K(S(KK)))(S(K(S(KK)))(S(K(S(KK)))(S(KK))))))
S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K))))))(S(KK)(S(KK)K))))))))(S(KK)(S(KK)(S(KK)K))))))))))(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K)))))))
S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))))(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(KK)))))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(K(S(KS)))(S(S(KS)(S(KK)(S(KS)(S(K(S(SKK)))K))))(KK))))))(S(KK)(S(KK)K))))))))(K(K(S(KK)K))))))))))(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))(K(K(K(S(KK)(S(KK)K))))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))))))(K(K(K(K(S(KK)(S(KK)(S(KK)K))))))))))))))))))(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K))))))))
S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))))))(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))))(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(K(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))))(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(K(S(K(S(K(S(KS)))))))))(S(K(S(K(S(K(S(K(S(K(S(KS)))))))))))(S(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(KK)(S(KS)(S(K(S(KS)))(S(S(KS)(S(KK)(S(KS)(S(K(S(SKK)))K))))(KK))))))))))))(K(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(KK)))))))(S(S(KS)(S(KK)S))(KK))))))))))))))(K(K(K(K(S(KK)(S(KK)K))))))))))))))))(K(K(K(K(K(S(KK)(S(KK)K))))))))))))))))))(K(K(K(K(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))))))))))))(K(K(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)(S(KK)K)))))))))
K(S(K(S(KK)))(S(K(S(K(S(KK)))))(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(KK))))))))))
S(KK)(S(K(S(KK)))(S(K(S(K(S(KK)))))(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(K(S(KK)))))))))))(S(K(S(K(S(K(S(K(S(K(S(SKK)))))))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(SKK)))))))))(S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(SKK)))))))(S(K(S(K(S(KK)))))(S(K(S(K(S(SKK)))))(S(K(S(KK)))(S(K(S(SKK)))K))))))))))))))
S(K(S(K(S(K(S(KK)))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(K(S(K(S(K(S(KK)))))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(K(S(K(S(KS)))))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(K(S(KS)))))(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(S(KS)(S(K(S(SKK)))K))))(S(KK)K))))))(S(KK)(S(KK)K))))))))(S(KK)(S(KK)(S(KK)K))))))))))(S(KK)(S(KK)(S(KK)(S(KK)K))))))))))

source: Stack Exchange

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

sort: votes


text:
Output N in base -10
Challenge:
In the programming language of your choice, accept an integer  as input in base 10, and output it in the negadecimal notation, which is also known as base -10
Example algorithm:
This is an algorithm taken from Wikipedia to convert base 10 to any negative base in VB.NET:
Function toNegativeBase(Number As Integer , base As Integer) As System.Collections.Generic.List(Of Integer)

    Dim digits As New System.Collections.Generic.List(Of Integer)
    while Number <> 0
        Dim remainder As Integer= Number Mod base
        Number = CInt(Number / base)

        if remainder < 0 then
            remainder += system.math.abs(base)
            Number+=1
        end if

        digits.Insert(0, remainder)
    end while

    return digits
end function

Obviously, you can use any algorithm, as long as it fulfills the challenge
Example inputs / outputs:
Input:
12

Output:
192

Another example:
Input:
2048

Output:
18168

Rule:
You must not use any built-in methods that solve this problem that exist in your programming language
This is a code-golf, so shortest code wins!

I think you only want to forbit built-ins that solve this specifiic problem and not all existing builltins.

Related OEIS: A039723

Whoops you are right @DenkerAffe , fixed.

Must we handle negative integers as well as positive ones?

Yup, otherwise I woud say whole numbers @KritixiLithos

@P.Ktinos Negative whole numbers are as much whole numbers as positive whole numbers.

@P.Ktinos I just looked up the definition of “whole number”. It seems that some people refer to (so-called) natural numbers when they say whole numbers while others (including me) refer to integers when they say whole numbers. I guess it is a matter of perspective. I've always been taught that “integer” is a synonym of “whole number”.

@Toothbrush I guess you are right. I'll edit the question to avoid confusion.

You should add a negative test case.

Would [0, 1, 8, 1, 6, 8] be an acceptable output for input 2048?

@Dennis No, sorry. You should join the digits and output it as an integer.

That might be worth mentioning in the spec. Your VB code looks like it returns a list.

@Dennis It's an example of an algorithm used to do the conversion, as some people may not know the way to convert decimal to negadecimal. It's not meant to showcase the way it should be done, and it is not mine, it is taken from wikipedia.

Does this answer your question? Convert negadecimal to decimal (and back)

JavaScript (ES6), 51 45 37 bytes
f=n=>n&&n%10+((k=n<0)+f(k-n/10|0))*10

Test cases

f=n=>n&&n%10+((k=n<0)+f(k-n/10|0))*10

console.log("12 -> " + f(12))
console.log("2048 -> " + f(2048))

Is there a reference for this algorithm?

@dfernan I don't really know. This is the result of several golfing iterations, starting with the suggested algorithm.

Jelly, 9 bytes
Dḅ-10=ð1#

This is a brute-force inverse of negadecimal-to-integer conversion.
Try it online!
How it works
Dḅ-10=ð1#  Main link. Argument: n

      ð    Combine the links to the left into a chain and start a new, dyadic
           chain with left and right argument n.
       1#  Repeatedly execute the chain with left argument k = n, n + 1, ... and
           right argument n until the first match is found.
D          Convert k to decimal.
 ḅ-10      Convert the result from base -10 to integer.
     =     Compare the result with n.

Japt, 11 bytes
_ì ìAn)¥U}a

Test it online!
Explanation
_ì ìAn)¥U}a  // Implicit: U = input integer, A = 10
_        }a  // Return the smallest non-negative integer Z that returns a truthy value
             // when run through this function:
 ì           //   Convert Z to a list of its base 10 digits.
   ìAn)      //   Interpret this as a list of base -10 digits and convert to a base 10 integer.
       ¥U    //   Return (the result == U).
             // Implicit: output result of last expression

Batch, 82 bytes
@set/a"d=%1%%10,n=%1/-10-(a=d>>4),d-=a*10
@if %n% neq 0 %0 %n% %d%%2
@echo %d%%2

Batch's division truncates to zero, so if the remainder is negative I need to add 1 (and also add 10 to the remainder) to compensate. The digits are then accumulated in %2 until the result becomes zero.

Pyth - 9 bytes
Lel it has the crying emoji in it.
fqQijT;_;

Test Suite.

Why are you crying?? You are on par!

Because he has the crying emoji on Pyth answer.

Python 3, 35 bytes
f=lambda n:n and n%10+f(0-n//10)*10

Python port of Arnauld's algorithm.
Alternatively, for 102 bytes a generic function using the algorithm of the original post:
def f(n,b,r=0):
 if n:
  r,n=n%b,n//b
  if r<0:r+=abs(b);n+=1
  return f(n,b,r)+str(r)
 else:return ""

Python doesn't let you declare a default input that depends on another input.

@xnor It works on my Python installation: Python 3.5.1 (v3.5.1:37a07cee5969, Dec  5 2015, 21:12:44).

How are you calling it? I'm doing this (in 3.5.2). Might you be declaring k or n elsewhere in the code?

You were right. I had an n previously declared. For some reason, anyway, k is not needed as per the current solution. Can you try it?

Looks good, nice improvement! You don't need the parens around the function call any more.

Not sure how it comes to work, though, as per Arnauld's algorithm. Why is that 0-n needs 0 too (-n only yields wrong results)?

The last one I can explain as operator precedence. -n//10 does -(n//10): negate n, then floor-divide by 10, which rounds down towards negative infinity, not 0. In contrast, 0-n//10 does 0-(n//10), which first floor-divides by 10, then negates. For whatever reason, Python treats unary negation with a higher precedence than binary minus. See this precedence table. I've run into this same situation before in golfing.

PHP, 71 67 bytes
for(;$n=&$argn;$n=$g-$n/10|0)$d=($r=$n%10)+10*($g=$r<0).$d;echo+$d;

or 62 bytes for a port of Arnauld´s answer:
function n($n){return$n?$n%10+(($k=$n<0)+f($k-$n/10|0))*10:0;}

Jelly, 10 bytes
:⁵NµÐĿ%⁵ṚḌ

Try it online!
Background
Converting a list of non-negative from base b to integer can be achieved by left-folding by the function x, y ↦ bx + y. To convert and integer to base b, we must simply reverse that function, i.e., find an expression for bx + y ↦ x, y.
In Python (and, by extension, Jelly), the result of the modulo operator is always non-negative, so (bx + y) % |b| = y.
Also, integer division always rounds down, making sure that if q = n / d and r = n % d, the equality n = qd + r holds. If s is the sign of b, then (sx)|b| + y = bx + y, so sx = (bx + y) / |b| and, therefore, s((bx + y) / |b|) = x.
How it works
:⁵NµÐĿ%⁵ṚḌ  Main link. Argument: n

   µ        Combine the links to the left into a monadic chain.
    ÐĿ      Iteratively apply the chain until the results are no longer unique.
            Collect all unique results in an array.
:⁵            Divide the previous return value (initially n) by 10.
  N           Negate; multiply the result by -1.
      %⁵    Take all results modulo 10.
        Ṛ   Reverse the results.
         Ḍ  Convert from base 10 to integer.

SimpleTemplate, 147 bytes
This is a template language I've been working on.
By no means it is meant to be for golfing.
It even lacks complete basic math, but it allows to write tiny snippets of PHP directly.
This works around that issue.
{@setN argv.0}{@whileN}{@setM N}{@php$DATA[N]=($DATA[M]/-10)|0;$DATA[R]=$DATA[M]%-10}{@ifR is lower0}{@incby10 R}{@incN}{@/}{@setD R,D}{@/}{@echoD}

This throws a bunch of warnings.
The code is "compiled" into PHP.
Ungolfed, with trash whitespace:
{@set no argv.0}
{@while no}
    {@set temp_no no}
    {@php $DATA["no"] = ($DATA["temp_no"] / -10) | 0}
    {@php $DATA["remainder"] = $DATA["temp_no"] % 10}

    {@if remainder is lower than 0}
        {@inc by 10 remainder}
        {@inc no}
    {@/}
    {@set digits remainder, digits}
{@/}
{@echo digits}

If required, a set-by-step explanation can be added, but I believe that it is pretty straightforward.

Disclaimer:
The last commit, as of the time of writting this answer, was on 2017-01-07 20:36 UTC+00:00.
This works on commit 140e56ff38f45fa4fd40fd3ec382094e707b1bad from 2017-01-06 23:27 UTC+00:00.
That is the version used to run this answer.
The PHP code is available on https://raw.githubusercontent.com/ismael-miguel/SimpleTemplate/140e56ff38f45fa4fd40fd3ec382094e707b1bad/SimpleTemplate.php
I do recommend running this with the last version, but that one works fine for this question.

How to run?
Create a file with the code and run it like this:
<?php

    include 'path/to/SimpleTemplate.php';

    $template = new SimpleTemplate('<code>');

    $template->render(<number>);

The value will then be displayed on the screen.

Mathematica, 49 bytes
d@0="";d@n_:=d[-Floor[n/10]]<>ToString[n~Mod~10];

Defines a function d taking one integer argument, and returning a string. A recursive algorithm—looks like the same algorithm in Arnauld's answer. It does work on negative numbers as well. (It returns the empty string intsead of "0" if the input is 0.) Note for Mathematica golfers: using ± requires one extra set of parentheses and thus seems not to be any shorter.

05AB1E, 3 bytes
T(в

Try it online! This is not a builtin. It uses builtin base conversion, but not builtin negadecimal conversion.
T(в  # full program
  в  # base-10 digits of...
     # implicit input...
  в  # in base...
 (   # negative...
T    # 10
     # implicit output

Vyxal, 4 bytes
₀Nτṅ

Try it Online!
Explanation:
  τ   # From base 10 to base
₀     # Ten
 N    # Negated
   ṅ  # Join by nothing
      # Implicitly print

C, 68 bytes
main(f,a){f&&scanf("%d",&a);f=a?a%10+((f=a<0)+main(0,f-a/10))*10:0;}

Instead of printing the resulting number the program just returns it. Obviously this is Arnauld's answer, the only difference is that since C isn't an interpreted language I felt like I should make it a full program as opposed to just a function.

How is it returning it? f goes out of scope when the function returns unless I'm being really dumb.

@abligh You aren't being really dumb, it's just GCC being really dumb. If a non-void function terminates without a return it'll simply use the last assignment.

Rust, 88 bytes
fn g(mut n:i32)->i32{let mut r=n%10;n/=-10;if r<0{r+=10;n+=1;}if n==0{r}else{r+g(n)*10}}

This is just a recursive version of the algorithm provided in the question.

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

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


text:
Recreate the ASCII-table as an ASCII-table
Frequently while I'm code-golfing, I'll want to know what the ASCII value of a certain character is. One of my favorite resources for quickly looking up all of the printable ASCII characters is ASCIItable.com. This has a really nice image that not only shows the printable ASCII characters and their values, but also the unprintable and extended characters, and the values in hexadecimal, octal, and HTML:

Today's challenge is to recreate that ASCII table as an ASCII table instead of an image. To keep things simpler, we will not use control-characters (characters below 32) and we'll only show the decimal value and the character. In other words, your challenge is to write either a full-program or a function that prints or returns the following text:
Dec  Chr   | Dec  Chr   | Dec  Chr
----------------------------------
32   Space | 64   @     | 96   `
33   !     | 65   A     | 97   a
34   "     | 66   B     | 98   b
35   #     | 67   C     | 99   c
36   $     | 68   D     | 100  d
37   %     | 69   E     | 101  e
38   &     | 70   F     | 102  f
39   '     | 71   G     | 103  g
40   (     | 72   H     | 104  h
41   )     | 73   I     | 105  i
42   *     | 74   J     | 106  j
43   +     | 75   K     | 107  k
44   ,     | 76   L     | 108  l
45   -     | 77   M     | 109  m
46   .     | 78   N     | 110  n
47   /     | 79   O     | 111  o
48   0     | 80   P     | 112  p
49   1     | 81   Q     | 113  q
50   2     | 82   R     | 114  r
51   3     | 83   S     | 115  s
52   4     | 84   T     | 116  t
53   5     | 85   U     | 117  u
54   6     | 86   V     | 118  v
55   7     | 87   W     | 119  w
56   8     | 88   X     | 120  x
57   9     | 89   Y     | 121  y
58   :     | 90   Z     | 122  z
59   ;     | 91   [     | 123  {
60   <     | 92   \     | 124  |
61   =     | 93   ]     | 125  }
62   >     | 94   ^     | 126  ~
63   ?     | 95   _     | 127  DEL

Trailing spaces on each line, and a trailing newline are permitted. Since this is a kolmogorov-complexity challenge, your submission may not take any input, or access any external resources (such as a file or the web), and your goal is to compress the code to output this text as much as possible.
Standard loopholes apply, and the shortest answer in bytes wins. Happy golfing!

I have that exact ASCII table image stuck on my wall... Anyway, can a list of lines be returned?

@fliptack Of course you can. Why wouldn't I allow something perfectly reasonable like that?

I wouldn't say this is a dupe - the other one requires hex values, names of unprintables, and is a different table format. This sticks to visible ASCII and allow golfier code by not asking for the 3-letter codes of all the unprintables.

@FlipTack It still has Space and DEL

@gurka yes, but the other one has every single control character.

ascii on linux systems also does this

Python 2 3.6, 185 183 175 159 156 bytes
Saved 8 bytes thanks to FlipTack!
Still quite new to golfing in Python.
for a in["Dec  Chr   | "*3,"-"*39]+["".join(f"{l:<5}{('Space',chr(l),'DEL')[(l>32)+(l>126)]:<6}| "for l in(i,32+i,64+i))for i in range(32,64)]:print(a[:-5])

Uses a nested list comprehension to generate the table body.
Ungolfed:
lines =   \
  ["Dec  Chr   | "*3, "-"*39] +                      # first two lines
    ["".join(                                        # join 3 parts of each line
      f"{l:<5}{('Space',chr(l),'DEL')[(l>32)+(l>126)]:<6}| "
        for l in (i,32+i,64+i)                       # generate 3 parts of a line
      )
      for i in range(32,64)]

for line in lines: print line[:-5]

Update: apparently using f-string here is shorter than the % operator.

Old attempt, 185 183 175 bytes
print("Dec  Chr   | "*3)[:-5]+"\n"+"-"*34
a=lambda x:('Space',chr(x),'DEL')[(x>32)+(x>126)]
for l in range(32,64):print("%-5d%-6s| "*3%(l,a(l),l+32,a(l+32),l+64,a(l+64)))[:-5]

Ungolfed:
print ("Dec  Chr   | "*3)[:-5] + "\n" + "-"*34
def a(x):
    return "Space" if x==32 else "DEL" if x==127 else chr(x)
for line in range(32,64):
    print ("%-5d%-6s| "*3 % (line, a(line), line+32, a(line+32),
      line+64, a(line+64))) [:-5]

I see a space at  for l in(i,32+i,64+i)]), could be removed to save one byte.

Befunge, 176 172 bytes
<v"Dec  Chr   "0
^>:#,_$1+:2`#v_" |",,
\:#->#1_55+,v>55+,"!-":>,#:
+2*,:"_"`#@_v>1+:8-#v_$1+:3%!:7g,!29+*5
*84+1%3\/3::<^,gg00:<`"c"p00+5+`"~"\`*84::p62:.:+*
  Space

| DEL

Try it online!

Pyth, 89 85 79 77 bytes
PP*"Dec  Chr   | "3*\-34V32PPsm++.[`=+N32;5.[?qN32"Space"?qN127"DEL"CN;6"| "3

Try it online!

JavaScript (ES6), 179 173 bytes

f=n=>n?(n>>6?' | ':`
`)+n+(99<n?'  ':'   ')+(126<n?'DEL':String.fromCharCode(n)+'    '+f(n>95?n-63:n+32)):`${x='Dec  Chr   '}| ${x}| ${x}
${'-'.repeat(34)}
32   Space`+f(64)

console.log(f())

Nice answer! You can save one more byte by replacing \${x='Dec  Chr   '}| ${x}| ${x}at the end of line 2 by(x='Dec  Chr   ')+(' |'+x)*2+``

@L.Serné I don't know of any version of ECMAScript that would repeat a string with the * operator. Or am I somehow misunderstanding your suggestion?

Oops, my bad. That's what you get for trying to golf a python solution and then javascript.

F#, 222 bytes
let c,p=String.concat" | ",printfn"%s"
Seq.replicate 3"Dec  Chr  "|>c|>p
p(String.replicate 34"-")
for i=32 to 63 do[for j in[i;i+32;i+64]->sprintf"%-5d%-5s"j (match j with 32->"Space"|127->"DEL"|_->string(char j))]|>c|>p

Try it online!

Can I ask for an ungolfed version of this please? I'm really new to learning F#, and I'd love to understand properly how you did this!

The first line aliases two functions to single-character names. Now if you do ["ab"; "cd"] |> c |> p it concatenates with "|" characters and prints them, like "ab  | cd" which is the basic idea for printing the table. The rest is fairly straightforward, just avoiding whitespace wherever possible.

V, 98, 96, 94 bytes
i32 | 64 | 9631ñÙl.l.ñÍä«/&   &
ÎéiD@"
bsDELF 27kdH5lRSpaceÄÒ-Ä3RDec  Chr³ | Î35|D

Try it online!
Just barely squeaking in under a hundred. I'm gonna see if I can beat Pyth, but I won't make any promises.
Here is a hexdump:
00000000: 6933 3220 7c20 3634 207c 2039 361b 3331  i32 | 64 | 96.31
00000010: f1d9 016c 2e6c 2ef1 cde4 ab2f 2620 2020  ...l.l...../&
00000020: 1616 2620 2020 200a cee9 6944 4022 0a62  ..&    ...iD@".b
00000030: 7344 454c 1b46 2016 3237 6b64 4835 6c52  sDEL.F .27kdH5lR
00000040: 5370 6163 651b c4d2 2dc4 3352 4465 6320  Space...-.3RDec
00000050: 2043 6872 b320 7c20 1bce 3335 7c44        Chr. | ..35|D

And here's how it works:
i32 | 64 | 96<esc>      " Insert some starting text
31ñ          ñ          " 31 times:
   Ù                    "   Duplicate this line
    <C-a>               "   Increment the first number on this line
         l.             "   Increment the next number
           l.           "   Increment the next number

Here is where it get's interesting. First, let me explain a vim-trick. While in insert mode, certain characters are inserted (all printable ASCII-characters, most unmapped characters above 0x7f, and a few others), but other characters have a side-effect. For example, 0x1b (<esc>) will escape to normal mode. 0x01 (<C-a>) will re-insert the last inserted text, etc. Sometimes, we want to insert these characters literally. So to insert a literal escape character, you must type <C-v><esc>. This works for all characters that have a side effect. So essentially, <C-v> is the equivalent of a backslash in languages with string literals that allow you to escape certain characters in a string.
The other useful trick with <C-v> in insert mode, is that it can be used to insert characters by code-point, in either Decimal, Hexadecimal, Octal, or Hexadecimal Unicode. Since we already have the numbers that correspond to certain ASCII values, we just need to put a <C-v> before those characters, and run the corresponding text as vim-keystrokes. This can be achieved with a regex command, and a "Do 'x' on every line" command. So we:
Í                       " Substitute globally:
 ä«                     "   One or more digits
   /                    " With:
    &                   "   The matched number + some spaces
        <C-v><C-v>&     "   A ctrl-v character, then the matched number again
                        "   Since ctrl-v is like a backslash, we need two to enter a literal ctrl-v character
Î                       " On every line:
 éi                     "   Insert an 'i'
   D                    "   Delete this line
    @"                  "   Run it as vim keystrokes

At this point, the buffer looks like this
32         | 64   @     | 96   `
33   !     | 65   A     | 97   a
34   "     | 66   B     | 98   b
35   #     | 67   C     | 99   c
36   $     | 68   D     | 100   d
37   %     | 69   E     | 101   e
38   &     | 70   F     | 102   f
39   '     | 71   G     | 103   g
40   (     | 72   H     | 104   h
41   )     | 73   I     | 105   i
42   *     | 74   J     | 106   j
43   +     | 75   K     | 107   k
44   ,     | 76   L     | 108   l
45   -     | 77   M     | 109   m
46   .     | 78   N     | 110   n
47   /     | 79   O     | 111   o
48   0     | 80   P     | 112   p
49   1     | 81   Q     | 113   q
50   2     | 82   R     | 114   r
51   3     | 83   S     | 115   s
52   4     | 84   T     | 116   t
53   5     | 85   U     | 117   u
54   6     | 86   V     | 118   v
55   7     | 87   W     | 119   w
56   8     | 88   X     | 120   x
57   9     | 89   Y     | 121   y
58   :     | 90   Z     | 122   z
59   ;     | 91   [     | 123   {
60   <     | 92   \     | 124   |
61   =     | 93   ]     | 125   }
62   >     | 94   ^     | 126   ~
63   ?     | 95   _     | 127

Now we just need some general clean up, which accounts for most of the bytes in this answer
bsDEL<esc>              " Change the literal 0x7f character to "DEL"
          F <C-v>27kd   " Remove a space from the lines that have too many
H5l                     " Move to the first space character
   RSpace<esc>          " And replace it with "Space"
Ä                       " Duplicate this line
 Ò-                     " And replace it with '-'s
   Ä                    " Duplicate this line
    3R                  " And replace it with three copies of the following string:
      Dec  Chr³ | <esc> " 'Dec  Chr   | '

Î35|D                   " Remove all but the first 35 characters of each line

dc, 167 bytes
[[Space]nq]sp[[DEL]nq]sq[[ ]n]sc[Dec  Chr]dsen[   | ]dsfnlenlfnlen10P34[[-]n1-d0<a]dsax10P0[[32+dndZ2=c[  ]ndd32=pd127=qP[    ]n]dswx[ | ]nlwx[ | ]nlwx10P95-d32>b]dsbx

Try it online!
How it works:
[[Space]nq]sp     # p is a macro that prints "Space" and then quits from the call one level up
[[DEL]nq]sq       # q is a macro that prints "DEL" and then quits from the call one level up
[[ ]n]sc          # c is a macro that prints a space
[Dec  Chr]dsen    # Save the string "Dec  Chr" in register e, and print it.
[   | ]dsfn       # Save the string "   | " in register f, and print it.
len               # Print "Dec  Chr" again.
lfn               # Print "   | " again.
len               # Print "Dec  Chr" again.
10P               # Print a newline.
34                # Push 34 on the stack.

[[-]n1-d0<a]dsa   # a is a macro that repeatedly prints "-" and decrements the top of the stack, while the top of the stack is positive.

x10P              # Execute macro a, followed by a newline. (This prints the line of hyphens.)

0                 # Push 0 on the stack.

[                 # Starting a large macro (which will be stored in register b) for printing the table row by row.

[32+dndZ2=c[  ]ndd32=pd127=qP[    ]n]dsw

                  # w is a macro which:
                        (1) adds 32 to the top of the stack;
                        (2) prints it as a number;
                        (3) uses Z to compute the number of characters the number required to print that number;
                        (4) if it required 2 characters to print the number, calls the macro c to print an extra space
                        (5) prints the string "Space" (for ASCII code 32) or the string "DEL" (for ASCII code 127) or the appropriate character, followed by the right number of spaces

x                 # Execute macro w to print an entry in column 1.
[ | ]n            # Print a column divider.
lwx               # Execute macro w to print an entry in column 2 (ASCII code 32 higher than the previous entry).
[ | ]n            # Print a column divider.
lwx               # Execute macro w to print an entry in column 3 (ASCII code 32 higher than the previous entry).

10P               # Print a newline.
95-               # Subtract 95 to adjust to go to the beginning of the next line.

d32>b             # If the top of stack is <= 32, execute macro b again, effectively looping to print all the rows of the table.

]dsb              # End the definition of the large macro, and store it in register b.

x                 # Execute the macro that's in b (with 0 at the top of the stack initially).

Perl, 120 bytes
$,="| ";say+("Dec  Chr   ")x3;say"-"x32;say map{sprintf"%-5s%-6s",$_,$_-32?$_-127?chr:DEL:Space}$_,$_+32,$_+64for 32..63

Run with -E flag:
perl -E '$,="| ";say+("Dec  Chr   ")x3;say"-"x32;say map{sprintf"%-5s%-6s",$_,$_-32?$_-127?chr:DEL:Space}$_,$_+32,$_+64for 32..63'

-2 bytes thanks to @G B.

If I understand a little Perl, maybe you can cut 2 spaces by using "%-5s" instead of "%-3s" (incidentally, that's what I do in ruby)

C, 179 bytes
i;f(){for(;i++<37;)printf(i<4?"Dec  Chr%s":"-",i<3?"   | ":"\n");printf("\n32   Space | ");for(i=64;i<127;i+=i>95?-63:32)printf("%-5d%-6c%s",i,i,i>95?"\n":"| ");puts("127  DEL");}

Try it online!
Semi-ungolfed:
i;
f() {
  for(;i++<37;) printf(i<4?"Dec  Chr%s":"-",i<3?"   | ":"\n");

  printf("\n32   Space | ");
  for(i=64;i<127;i+=i>95?-63:32) printf("%-5d%-6c%s",i,i,i>95?"\n":"| ");
  puts("127  DEL");
}

V, 151 150 148 136 135 130 129 125 bytes
12 bytes saved thanks to @nmjcman101 for using <C-v>g<C-a> for the numbers instead of line('.')
2 byte saved thanks to @DJMcMayhem for removing lines with leading spaces using ÇÓ/d and by using dê to remove extra spaces and rearranging stuff
This answer is in competition with @nmjcman101's V answer (which uses :set ve=all). But now, I found a way to remove those A ^[s and saved some bytes and we are at an even bytecount
iSpace
¬!~Ó./&ò
iDELí^/31
HlgGo| 63ÙkGld/Sp
$p/`
G$d/@
$p/64
G$d/S
$pÇÓ/d
/d
hdê/32
O34é-O!| !| !Ó!/Dec  Chr
Try it online!
Hexdump:
00000000: 6953 7061 6365 200a 1bac 217e d32e 2f26  iSpace ...!~../&
00000010: f20a 6944 454c 1bed 5e2f 3331 2020 200a  ..iDEL..^/31   .
00000020: 1648 6c67 0147 6f7c 201b 3633 d96b 1647  .Hlg.Go| .63.k.G
00000030: 6c64 2f53 700a 2470 2f60 0a16 4724 642f  ld/Sp.$p/`..G$d/
00000040: 400a 2470 2f36 340a 1647 2464 2f53 0a24  @.$p/64..G$d/S.$
00000050: 70c7 d32f 640a 2f64 0a68 64ea 2f33 320a  p../d./d.hd./32.
00000060: 4f1b 3334 e92d 4f21 7c20 217c 2021 1bd3  O.34.-O!| !| !..
00000070: 212f 4465 6320 2043 6872 2020 20         !/Dec  Chr

Explanation (uncomplete and outdated)
The strategy here is that I'm using the line numbers to generate the ASCII code points.
Note: ^[ is 0x1b, ^V is C-v
First we generate all the characters.
iSpace             " insert Space
^[¬!~              " insert every character between ! and ~

The current buffer looks like
Space
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Now we insert a newline between these characters
     Ó./&ò         " insert a newline before every character (:s/./&\r/g)

Here's a drop in replacement for the 32   SPACE ... 127   DEL part of your code: Try it online!  It uses that neat thing where you can highlight a bunch of numbers, and then g^A makes it an increasing sequence (new in Vim 8?)

@nmjmcman101 Yeah, it was added in 7.4.something, but officially added in 8. Even better would be to use the norm command Try it online!

Either way, once you get that you can do a :set ve=all and then the cursor will move into places that there is no text, letting you insert the pipes easier and copy/paste in the places you need to without sprinkling A <esc> everywhere

@nmjcman101 Re g^A thanks, it saved me 12 bytes :)

@DJMcMayhem For some reason, using norm and then incrementing the numbers doesn't work

@nmjcman101 Re :set ve=all, it is a few bytes longer than just using A <esc> https://tio.run/nexus/v#@58ZXJCYnMolfWiNYt3hyXr6aoc3cWW6uPpIH16rp29sqKCgoMYl5pGTzmhVnFqiUJZqm5iTw5WerpKTk1kjXZljZnx4Y1ZGweGN@glcNWLuKhX6DlwqOQX6KVwZhzdVZB3epG9mwgUWT@UyBoobG3H5SxubHF6p669YowBC0ocnK@q7pCYrKDhnFAGt4zq8Nu7w5kOrwfS6//8B

You could replace those last two substitute commands with ÇÓ/d (Equivalent to :g!/\S/norm dd, e.g. delete every line not matching a non-whitespace character)

@DJMcMayhem Oh thanks, I didn't know there was a shortcut for the global command

Ruby, 124 bytes
 puts [["Dec  Chr   "]*3*"| ",?-*34,(0..31).map{|d|(1..3).map{|x|"%-5s%-6s"%[y=x*32+d,y<33?"Space":y>126?"DEL":y.chr]}*"| "}]

V, 130 120 99 bytes
Sub 100 club.  I'm no longer convinced that :se ve=all is the best way of doing this.  It's an extra... 11 bytes just for writing the |'s!  But that's what I have.
I'm posting this almost in competition with @KritixiLuthos answer using :se ve=all to avoid some A <esc>'s.  I'm not convinced that either method is better yet, so hopefully this can inspire some golfing on both parties and see which method takes the cake.
I'm also half expecting @DJMcMayhem to kick both our pants
iSpace
¬!~Ó./&ò
iDELí^/31
Hlg:se ve=all
12|êr|2ñ031j$x)PñHd)ÄÒ-Ä3RDec  Chr³ | /d
hdêÎ35|D

Try it online!
Hexdump for the curious (if there's interest I'll just change this to a vim-style hidden character block)
00000000: 6953 7061 6365 0a1b ac21 7ed3 2e2f 26f2  iSpace...!~../&.
00000010: 0a69 4445 4c1b ed5e 2f33 3120 2020 0a16  .iDEL..^/31   ..
00000020: 486c 6701 3a73 6520 7665 3d61 6c6c 0a31  Hlg.:se ve=all.1
00000030: 327c 16ea 727c 32f1 3016 3331 6a24 7829  2|..r|2.0.31j$x)
00000040: 50f1 4864 29c4 d22d c433 5244 6563 2020  P.Hd)..-.3RDec
00000050: 4368 72b3 207c 201b 2f64 0a68 64ea ce33  Chr. | ./d.hd..3
00000060: 357c 44                                  5|D

The global command could be shortened by quite a but. For one, the dd is implicit if you just do d. You can also do <M-s> which is always equivalent to \s in regex. So you could shorten it to: ç^ó*/d. But if you switch out the global command for the inverse :g! you could search for every line not matching a non-whitespace character. ÇÓ/d which is equivalent to :g!/\S/normal dd

AWK, 200 bytes
BEGIN{b="-----------";a="Dec  Chr   ";print a"|",a"|",a"\n-"b b b;for(a=31;a++<63;){printf"%-5d%-6s| %-5d%-6c| %-5d%-5s\n",a,a<33?"Space":sprintf("%c",a),a+32,a+32,a+64,a<63?sprintf("%c",a+64):"DEL"}}

Formatted:
BEGIN {
  b="-----------"
  a="Dec  Chr   "
  print a"|",a"|",a"\n-"b b b
  for(a=31;a++<63;) {
    printf "%-5d%-6s| %-5d%-6c| %-5d%-5s\n",
      a,    a<33 ? "Space" : sprintf("%c", a),
      a+32, a+32,
      a+64, a<63 ? sprintf("%c", a+64) : "DEL"
  }
}

Try it online!

Tcl, 233 bytes
lassign {"Dec  Chr" "   | " 31} h S i
set H $h$S$h$S$h\n[string repe - 34]
proc p x {format %-5d%c $x $x}
time {set H "$H
[p [incr i]]  $S[p [expr $i+32]]  $S[p [expr $i+64]]"} 32
puts [regsub {\ {8}} [regsub \177 $H DEL] "   Space"]

Try it online!

I ran this and I get 32  for example (a ' ' instead of Space), and 33! (no space in-between 33 and !).

@SeeOneRhino: You are clearly not paying attention to the code. I modified the code of the link after pasting here, in attempt to golf it even more, but I did not succeed yet. I just went to page now and commented my failed attempt and repasted the code from here;If you go there now, you will see code exactly equal and you will see it print things right!

I am sorry, I didn't see your edit to the link. I assumed that the code was the same as what you had posted here.

No problem, it was my fault

@SeeOneRhino: I achieved it! I outgolfed myself!

Got the same 233 bytes on https://tio.run/##ZY6/CoMwGMT3PMUR4lQ6aGx9gFpw6OaoGSRNNeCfkKQg2Dy7tdhOPe4O7hs@fl7269o3zul2xEJzJYFLZykogNfWPA7oUEITpzwKsI6Ve@qxct7qsYVVRuEIngpi7CRhMGN5THZoPKLj6R5JsHlzIF4PCsv@ibKCVAaVHqWFFgJg5Wer2VgwfeDJ/@2cCkEDeELM0zv8AIbGbPD4aocvTSMVRR1nGfLrLYAVYl3f

C 188 Bytes
f(){i=31;printf("Dec Chr | Dec Chr | Dec Chr");printf("\n--------------------------");for(;i<63;i++)printf("\n%d%4c  | %d%4c  | %d%4c",(i+1),(i+1),(i+33),(i+33),(i+65),(i+65));puts("DEL");

Normally looks like this:
f()
{
    int  i=31;
    printf("Dec Chr | Dec Chr | Dec Chr");
    printf("\n--------------------------");
    for(;i<63;i++)
      printf("\n%d%4c  | %d%4c  | %d%4c", (i+1),(i+1),(i+33),(i+33),  (i+65),(i+65));
    puts("DEL");
}

C (249 bytes)
Newlines added for clarity.
#define L(s,e)for(i=s;i<e;++i)
#define P printf
main(i){L(0,3)P("Dec  Chr  %s",i<2?" | ":"\n");
L(0,34)P("-");P("\n");L(32,64){P("%-5d", i);
i==32?P("Space"):P("%-5c",i);
P(" | %-5d%-5c | %-5d ",i+32,i+32,i+64);
i==63?P("DEL"):P("%-5c",i+64);P("\n");}}

You can definitely save some bytes by making P be printf(, as shown here: https://repl.it/JBRD

And by removing the space on your fourth line.

229 bytes

Java, 434 422 321 bytes
class A{public static void main(String[]a){
    int k=1,r,s=32;
    for(;k<4;k++)
        o("Dec   Chr  ",k);
    for(;k<37;k++)
        o("-",k==36?3:4);
    for(k=r=s;!(k==64&&r==-63);r=k>95?-63:s,k+=r)
        o(k+"   "+((k>99)?"":" ")+(k==s?"Space":k==127?"DEL  ":((char)k+"    ")),k/s);
    }
    static void o(String s,int j){
        System.out.print(s+(j==4?"":j==3?"\n":"|"));
    }
}

Java is probably not the best language for this as there is the overhead of classes and main method...
You can eliminate main method using a static declaration, reducing the byte count down further:
class A{
    static{...}

but this results in an error (after otherwise successfully running):
Exception in thread "main" java.lang.NoSuchMethodException: A.main([Ljava.lang.String;)
    at java.lang.Class.getMethod(Class.java:1786)
    ...

The byte count does int include newlines or indentation.

I don't think you need a space after void main(){, and neither between while(s.length()<5) and s+=" ". (Unless you didn't count that in your byte count). And you can save a few bytes by changing d="Dec",c="Chr" to d=p("Dec"),c=p("Chr") and making changing your calls p(d) and p(c) to d and c.

The 434 was removing all unnecessary whitespace. Your suggestion brings it down to 425. Thanks!

Might want to add a note about the 434 being w/o unneeded whitespace into the answer

Done. Note: program has significantly changed since (reduced further) so comments above may no longer be relevant

PHP, 163 149 147 bytes
<?=($p=str_pad)(D,31,"ec Chr   | D"),$p("
",32,"-");whhile($i<96)printf("%s%-4d%-6s",$i%3?"| ":"
",$o=$i%3*32+32+$i/3,$i++?$i<96?chr($o):DEL:Space);

breakdown
                        # print header
<?=($p=str_pad)(D,31,"ec Chr   | D"),$p("\n",32,"-");
while($i<96)            # loop $i from 0 to 96
    printf("%s%-4d%-6s",    # print formatted:
                            # string, 4 space decimal leftbound, 6 space string leftbound
        $i%3?"| ":"\n",                 # linebreak for 1st column, pipe+space else
        $o=$i%3*32+32+$i/3,             # ($i mapped to) ASCII value
        $i++?$i<96?chr($o):DEL:Space    # character
    );

Using %-N is worth the byte that rightbound numbers and character would save.

Looks better in my opinion with the same byte count Try it online!

R, 235 228 221 212 bytes
y=apply(rbind(rep("Dec  Chr  ",3),1,matrix(sapply(1:96,function(i)paste(i+31,rep(" ",i<69),"if"(i<2,"Space","if"(i>95,"DEL",intToUtf8(c(i+31,rep(32,4))))))),nrow=32)),1,paste,collapse=" | ")
y[2]=strrep("-",34)
y

Try it online!
I tried really hard to get under 200 bytes but these paste and collapse are killing me.
Returns a list of lines.

Stax, 53 bytes
éV ►Γ┐º╬¼1N_◄╒0└♀α→┴♂┐Y♣╟n»┤3°k⌡{═╥I⌂╜<─W}íè7Y♠Σ▲ÿb#√

Run and debug it

Python 2, 1564 218 bytes
My first golf, sorry for obvious mistakes
print("Dec  Chr   | "*3)[:-2]+"\n"+"-"*34+"\n32   Space | 64   @     | 96   `"
for n in range(33,63):print"| ".join([str(n+x).ljust(5)+chr(n+x).ljust(6)for x in [0,32,64]])
print"63   ?     | 95   _     | 127  DEL"

Try it online!
Incase you're wondering, the first version was a base64 encoded string.

@FlipTack Changed it to an actual solution

Unrequired whitespace at ljust(6) for.

Another at x in [. And IIRC the square brackets inside join can deleted.

Perl, 165 155 bytes
$s='Dec  Chr   ';$_=join"\n",("$s| $s| $s","-"x34,map{join"| ",map{sprintf'%1$-5d%1$-6c',$_}($_,$_+32,$_+64)}32..63);s/ {8}/   Space/;s/\x7f.*/DEL\n/;print

JavaScript (ES6), 258 bytes
a="Dec  Chr   | ".repeat(2)+"Dec  Chr\n"+"-".repeat(34);for(b=32;64>b;b++)a+="\n"+b+"   "+(32==b?"Space  ":String.fromCharCode(b)+"      ")+"| "+(b+32)+"   "+String.fromCharCode(b+32)+"     | "+(b+64)+(35<b?"  ":"   ")+(63==b?"DEL":String.fromCharCode(b+64))

console.log(a)

PowerShell, 159 bytes
,'Dec  Chr'*3-join'   | '
'-'*34
32..63|%{($_,($_+32),($_+64)|%{"$_".PadRight(5)+"$(([char]$_,('Space','DEL')[$_-ne32])[$_-in32,127])".padRight(5)})-join' | '}

Try it online!
The first two lines are just creating literal strings and leaving them on the pipeline. The first uses the comma operator , to create an array, and then -joins that array together to create the headers. The second is just a straight string multiplication.
The third line loops over 32..63 and each iteration sends three values $_, ($_+32), and ($_+64) into an inner loop. The inner loop does a PadRight on the value (adds the appropriate spaces to pad to 5 characters). That is then string concatenated + with the result of a nested pseudo-ternary ( )[ ]. The pseudo-ternary selects either the char representation of that number, or else Space or DEL if it's the appropriate value. Again, we PadRight the appropriate characters.
Those three strings (for example, 32   Space, 64   @, 96   `) are encapsulated in parens and -joined with the column markers into a single string. Each of those 32 strings are then left on the pipeline. At the end of execution, an implicit Write-Output inserts a newline between elements on the pipeline, so we get that for free.

05AB1E, 82 76 bytes
žQSDÇƵQ¸«.Bsð”‡²”:"DEL"¸«.B)øvyð2×ý})3äøvy… | ©ý}®”†…  Chr  ÿ”3×¨¨'-34×.Á.Á»

Try it online!
Still golfing, this can be improved a lot.

žQSDÇƵQ¸«.Bsð”‡²”:"DEL"¸«.B)ø pushes padded numbers with text equivalent:
[['32 ', 'Space'], ['33 ', '!    '], ['34 ', '"    '], ['35 ', '#    '], ['36 ', '$    '], ['37 ', '%    '], ['38 ', '&    '], ['39 ', "'    "], ['40 ', '(    '], ['41 ', ')    '], ['42 ', '*    '], ['43 ', '+    '], ['44 ', ',    '], ['45 ', '-    '], ['46 ', '.    '], ['47 ', '/    '], ['48 ', '0    '], ['49 ', '1    '], ['50 ', '2    '], ['51 ', '3    '], ['52 ', '4    '], ['53 ', '5    '], ['54 ', '6    '], ['55 ', '7    '], ['56 ', '8    '], ['57 ', '9    '], ['58 ', ':    '], ['59 ', ';    '], ['60 ', '<    '], ['61 ', '=    '], ['62 ', '>    '], ['63 ', '?    '], ['64 ', '@    '], ['65 ', 'A    '], ['66 ', 'B    '], ['67 ', 'C    '], ['68 ', 'D    '], ['69 ', 'E    '], ['70 ', 'F    '], ['71 ', 'G    '], ['72 ', 'H    '], ['73 ', 'I    '], ['74 ', 'J    '], ['75 ', 'K    '], ['76 ', 'L    '], ['77 ', 'M    '], ['78 ', 'N    '], ['79 ', 'O    '], ['80 ', 'P    '], ['81 ', 'Q    '], ['82 ', 'R    '], ['83 ', 'S    '], ['84 ', 'T    '], ['85 ', 'U    '], ['86 ', 'V    '], ['87 ', 'W    '], ['88 ', 'X    '], ['89 ', 'Y    '], ['90 ', 'Z    '], ['91 ', '[    '], ['92 ', '\\    '], ['93 ', ']    '], ['94 ', '^    '], ['95 ', '_    '], ['96 ', '`    '], ['97 ', 'a    '], ['98 ', 'b    '], ['99 ', 'c    '], ['100', 'd    '], ['101', 'e    '], ['102', 'f    '], ['103', 'g    '], ['104', 'h    '], ['105', 'i    '], ['106', 'j    '], ['107', 'k    '], ['108', 'l    '], ['109', 'm    '], ['110', 'n    '], ['111', 'o    '], ['112', 'p    '], ['113', 'q    '], ['114', 'r    '], ['115', 's    '], ['116', 't    '], ['117', 'u    '], ['118', 'v    '], ['119', 'w    '], ['120', 'x    '], ['121', 'y    '], ['122', 'z    '], ['123', '{    '], ['124', '|    '], ['125', '}    '], ['126', '~    '], ['127', 'DEL  ']]

vyð2×ý})3äøvy… | ©ý} joins 'em together into the table:
['32   Space | 64   @     | 96   `    ', '33   !     | 65   A     | 97   a    ', '34   "     | 66   B     | 98   b    ', '35   #     | 67   C     | 99   c    ', '36   $     | 68   D     | 100  d    ', '37   %     | 69   E     | 101  e    ', '38   &     | 70   F     | 102  f    ', "39   '     | 71   G     | 103  g    ", '40   (     | 72   H     | 104  h    ', '41   )     | 73   I     | 105  i    ', '42   *     | 74   J     | 106  j    ', '43   +     | 75   K     | 107  k    ', '44   ,     | 76   L     | 108  l    ', '45   -     | 77   M     | 109  m    ', '46   .     | 78   N     | 110  n    ', '47   /     | 79   O     | 111  o    ', '48   0     | 80   P     | 112  p    ', '49   1     | 81   Q     | 113  q    ', '50   2     | 82   R     | 114  r    ', '51   3     | 83   S     | 115  s    ', '52   4     | 84   T     | 116  t    ', '53   5     | 85   U     | 117  u    ', '54   6     | 86   V     | 118  v    ', '55   7     | 87   W     | 119  w    ', '56   8     | 88   X     | 120  x    ', '57   9     | 89   Y     | 121  y    ', '58   :     | 90   Z     | 122  z    ', '59   ;     | 91   [     | 123  {    ', '60   <     | 92   \\     | 124  |    ', '61   =     | 93   ]     | 125  }    ', '62   >     | 94   ^     | 126  ~    ', '63   ?     | 95   _     | 127  DEL  ']

®”†…  Chr  ÿ”3×¨¨'-34×.Á.Á» takes care of the header portion of the table:
Dec  Chr   | Dec  Chr   | Dec  Chr
----------------------------------
32   Space | 64   @     | 96   `
33   !     | 65   A     | 97   a
34   "     | 66   B     | 98   b
35   #     | 67   C     | 99   c
36   $     | 68   D     | 100  d
37   %     | 69   E     | 101  e
38   &     | 70   F     | 102  f
39   '     | 71   G     | 103  g
40   (     | 72   H     | 104  h
41   )     | 73   I     | 105  i
42   *     | 74   J     | 106  j
43   +     | 75   K     | 107  k
44   ,     | 76   L     | 108  l
45   -     | 77   M     | 109  m
46   .     | 78   N     | 110  n
47   /     | 79   O     | 111  o
48   0     | 80   P     | 112  p
49   1     | 81   Q     | 113  q
50   2     | 82   R     | 114  r
51   3     | 83   S     | 115  s
52   4     | 84   T     | 116  t
53   5     | 85   U     | 117  u
54   6     | 86   V     | 118  v
55   7     | 87   W     | 119  w
56   8     | 88   X     | 120  x
57   9     | 89   Y     | 121  y
58   :     | 90   Z     | 122  z
59   ;     | 91   [     | 123  {
60   <     | 92   \     | 124  |
61   =     | 93   ]     | 125  }
62   >     | 94   ^     | 126  ~
63   ?     | 95   _     | 127  DEL

T-SQL, 242 bytes
DECLARE @ INT=32PRINT'Dec  Chr   | Dec  Chr   | Dec  Chr
'+REPLICATE('-',34)L:PRINT CONCAT(@,'   ',IIF(@=32,'Space | ',CHAR(@)+'     | '),@+32,'   ',CHAR(@+32),'     | ',@+64,SPACE(5-LEN(@+64)),IIF(@=63,'DEL',CHAR(@+64)))SET @+=1IF @<64GOTO L

Formatted:
DECLARE @ INT=32
PRINT'Dec  Chr   | Dec  Chr   | Dec  Chr
' + REPLICATE('-',34)
L:
    PRINT CONCAT(@,'   ',IIF(@=32,'Space | ',CHAR(@)+'     | ')
                ,@+32,'   ',CHAR(@+32),'     | ',
                 @+64,SPACE(5-LEN(@+64)),IIF(@=63,'DEL',CHAR(@+64)))
    SET @+=1
IF @<64 GOTO L

Tried a few variations, including replacing various common strings with other variables, but this was the shortest version I found.

Python 3, 154 bytes
for l in[['Dec  Chr  ']*3,['-'*35]]+[[f"{x:<5}{['Space',chr(x),'DEL'][(x>32)+(x>126)]:5}"for x in(c,c+32,c+64)]for c in range(32,64)]:print(' | '.join(l))

Try it online!

Attache, 144 bytes
(p:=PadRight)["",37,"Dec  Chr   | "]'(34*"-")'(Join&"| "=>Tr@ChopInto&3<|{p&11<|p&5@Repr@_+(<~32->$Space,127->$DEL~>@_or Char!_)}=>32:127)|Print

Try it online!