[Question]
  [
Given a text like this:
```
# #### ## #
## #  ##  #
   ####  ##
```
Output the same text but by connecting the pixels with the characters `─│┌┐└┘├┤┬┴┼`. If a pixel doesn't have any neighbours, don't change it.
So the output of the last text is:
```
│ ─┬── ┌─ │
└─ │  ┌┘  │
   └──┘  ─┘
```
* You can take input as a boolean array.
* The input will always contain at least 1 pixel.
* You can count box-drawing chars as 1 byte.
* You can assume the input is padded with spaces.
## Test cases
```
## #
=>
── #
```
```
###
 #
=>
─┬─
 │
```
```
##### ##
 # #  #
########
=>
─┬─┬─ ┌─
 │ │  │
─┴─┴──┴─
```
```
 # #
#####
 # #
=>
 │ │
─┼─┼─
 │ │
```
```
# # # # #
 # # # #
# # # # #
 # # # #
# # # # #
=>
# # # # #
 # # # #
# # # # #
 # # # #
# # # # #
```
```
#####
#####
#####
#####
#####
=>
┌┬┬┬┐
├┼┼┼┤
├┼┼┼┤
├┼┼┼┤
└┴┴┴┘
```
Since this is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), the shortest code wins.
  
[Answer]
## JavaScript (ES6), ~~155~~ ~~121~~ ~~103~~ 102 characters
```
let f =
    
s=>s.replace(/#/g,(c,p)=>'#│─┘─└─┴││┐┤┌├┬┼'[t=x=>s[p+x]==c,8*t(w=s.search`
`+1)+4*t(1)+2*t(-1)+t(-w)])
console.log(f(
  '# #### ## #\n' +
  '## #  ##  #\n' +
  '   ####  ##'
));
```
*Edit: saved 18 bytes with the help of ETHproductions*  
*Edit: saved 1 byte by using the 1st parameter of replace() as `'#'`*
### How it works
We iterate on all `#` characters found in the input string. For each of them, we test whether its neighbors are also `#` characters using the `t()` function:
```
t = x => s[p + x] == c  // where c = '#'
```
The parameter `x` of the `t()` function is the offset of the neighbor with respect to the current position `p`. We use -1/+1 to test left/right neighbors and -w/+w for top/bottom neighbors (where `w` is the width of a row, i.e. the position of the first line-break + 1).
Each neighbor is assigned a different weight (1, 2, 4 or 8) according to the following compass:
```
  1
2 + 4
  8
```
Each weight combination leads to unique value in [ 0 .. 15 ]. For instance, if both the neighbor at the top and the neighbor on the right are set, the sum will be 1 + 4 = 5, which is translated into `└` using this table:
```
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
#  │  ─  ┘  ─  └  ─  ┴  │  │  ┐  ┤  ┌  ├  ┬  ┼
```
Therefore, `'#│─┘─└─┴││┐┤┌├┬┼'[weight_sum]` leads to the expected character.
[Answer]
# [J](http://jsoftware.com), ~~82~~ ~~72~~ 66 bytes
```
(ucp' #───│┌┐┬│└┘┴│├┤┼'){~]+]*3 3((2#.1 7 3 5{,);._3)0,.~0,.0,~0,]
```
The input is a boolean table of 1's and 0's. The rules state that the box characters each count as one byte, not three, and that has been applied here.
## Usage
```
   f =: (ucp' #───│┌┐┬│└┘┴│├┤┼'){~]+]*3 3((2#.1 7 3 5{,);._3)0,.~0,.0,~0,]
   m =: 1 0 1 1 1 1 0 1 1 0 1 , 1 1 0 1 0 0 1 1 0 0 1 ,: 0 0 0 1 1 1 1 0 0 1 1
   m { ' #'
# #### ## #
## #  ##  #
   ####  ##
   f m
│ ─┬── ┌─ │
└─ │  ┌┘  │
   └──┘  ─┘
   ' #' {~ m =: 5 5 $ 1
   f m
┌┬┬┬┐
├┼┼┼┤
├┼┼┼┤
├┼┼┼┤
└┴┴┴┘
   ' #' {~ m =: 5 9 $ 1 0
# # # # #
 # # # # 
# # # # #
 # # # # 
# # # # #
   f m
# # # # #
 # # # # 
# # # # #
 # # # # 
# # # # #
```
## Explanation
First the input is padded with 0's on all sides.
```
   ] m =: 1 0 1 1 1 1 0 1 1 0 1 , 1 1 0 1 0 0 1 1 0 0 1 ,: 0 0 0 1 1 1 1 0 0 1 1
1 0 1 1 1 1 0 1 1 0 1
1 1 0 1 0 0 1 1 0 0 1
0 0 0 1 1 1 1 0 0 1 1
   (0,.~0,.0,~0,]) m
0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 1 1 1 1 0 1 1 0 1 0
0 1 1 0 1 0 0 1 1 0 0 1 0
0 0 0 0 1 1 1 1 0 0 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0
```
Then each subarray of size 3 is selected
```
   3 3 <;._3 (0,.~0,.0,~0,]) m
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│
│0 1 0│1 0 1│0 1 1│1 1 1│1 1 1│1 1 0│1 0 1│0 1 1│1 1 0│1 0 1│0 1 0│
│0 1 1│1 1 0│1 0 1│0 1 0│1 0 0│0 0 1│0 1 1│1 1 0│1 0 0│0 0 1│0 1 0│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│0 1 0│1 0 1│0 1 1│1 1 1│1 1 1│1 1 0│1 0 1│0 1 1│1 1 0│1 0 1│0 1 0│
│0 1 1│1 1 0│1 0 1│0 1 0│1 0 0│0 0 1│0 1 1│1 1 0│1 0 0│0 0 1│0 1 0│
│0 0 0│0 0 0│0 0 1│0 1 1│1 1 1│1 1 1│1 1 0│1 0 0│0 0 1│0 1 1│1 1 0│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│0 1 1│1 1 0│1 0 1│0 1 0│1 0 0│0 0 1│0 1 1│1 1 0│1 0 0│0 0 1│0 1 0│
│0 0 0│0 0 0│0 0 1│0 1 1│1 1 1│1 1 1│1 1 0│1 0 0│0 0 1│0 1 1│1 1 0│
│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│0 0 0│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
Then only 5 of the values in each subarray is considered
```
┌───┐
│xAx│
│CED│
│xBx│
└───┘
```
The values `ABCD` are selected by flattening each subarray and selecting at indices `1 7 3 5`. Those values are multiplied by `E` which is at index 4. It is then converted from a list of binary digits to a decimal, and incremented by `E`. The `x` values are not needed.
```
   3 3 (4&{([+2#.*)1 7 3 5&{)@,;._3 (0,.~0,.0,~0,]) m
 5 0 2  8 4 3  0  6 3 0  5
10 3 0 13 0 0  6 11 0 0 13
 0 0 0 10 4 4 11  0 0 2 11
```
This is used as an index to select which character to draw according to the table below (reordered a bit for golfing). The last column matches the output value of each subarray to a box character.
```
 0  (space)  0
 1  #        1
 2  ┌        6
 3  ┬        8
 4  ┐        7
 5  ├        14
 6  ┼        16
 7  ┤        15
 8  └        10
 9  ┴        12
10  ┘        11
11  │        5, 9, 13
12  ─        2, 3, 4
```
Also, in J, the string `' #───│┌┐┬│└┘┴│├┤┼'` uses 8-bit characters making it have a length of 47 (for each byte) for the 17 characters needed. The command `ucp` converts it to 16-bit characters which allows it to be length 17.
[Answer]
# [Jelly](http://github.com/DennisMitchell/jelly), ~~60~~ ~~52~~ ~~51~~ ~~50~~ ~~49~~ 48 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
ṖḤ0;+Ḋ×
“µ³Q~E!G⁸ṗṫ\’ḃ61+9471Ọ⁾# j
ZÑ€4×Z++Ñ€ị¢Y
```
Saved a byte thanks to @[Dennis.](https://codegolf.stackexchange.com/users/12012/dennis)
The input is a boolean array of 1's and 0's. Iterates over each column and each row converting the head and tail of each infix of size 3 from a pair of binary digits to a decimal, and multiplies that with the center of each infix. Then it sums it with itself to find the index into `'#───│┌┐┬│└┘┴│├┤┼ '`.
[Try it online!](http://jelly.tryitonline.net/#code=4bmW4bikMDsr4biKw5cK4oCcwrXCs1F-RSFH4oG44bmX4bmrXOKAmeG4gzYxKzk0NzHhu4zigb4jIGoKWsOR4oKsNMOXWisrw5Higqzhu4vColk&input=&args=W1sxLDAsMSwxLDEsMSwwLDEsMSwwLDFdLFsxLDEsMCwxLDAsMCwxLDEsMCwwLDFdLFswLDAsMCwxLDEsMSwxLDAsMCwxLDFdXQ) ([case 2](http://jelly.tryitonline.net/#code=4bmW4bikMDsr4biKw5cK4oCcwrXCs1F-RSFH4oG44bmX4bmrXOKAmeG4gzYxKzk0NzHhu4zigb4jIGoKWsOR4oKsNMOXWisrw5Higqzhu4vColk&input=&args=W1sxLDEsMSwxLDFdLFsxLDEsMSwxLDFdLFsxLDEsMSwxLDFdLFsxLDEsMSwxLDFdLFsxLDEsMSwxLDFdXQ)) ([case 3](http://jelly.tryitonline.net/#code=4bmW4bikMDsr4biKw5cK4oCcwrXCs1F-RSFH4oG44bmX4bmrXOKAmeG4gzYxKzk0NzHhu4zigb4jIGoKWsOR4oKsNMOXWisrw5Higqzhu4vColk&input=&args=W1sxLDAsMSwwLDEsMCwxLDAsMV0sWzAsMSwwLDEsMCwxLDAsMSwwXSxbMSwwLDEsMCwxLDAsMSwwLDFdLFswLDEsMCwxLDAsMSwwLDEsMF0sWzEsMCwxLDAsMSwwLDEsMCwxXV0)) ([case 4](http://jelly.tryitonline.net/#code=4bmW4bikMDsr4biKw5cK4oCcwrXCs1F-RSFH4oG44bmX4bmrXOKAmeG4gzYxKzk0NzHhu4zigb4jIGoKWsOR4oKsNMOXWisrw5Higqzhu4vColk&input=&args=W1sxLDEsMCwxXV0))
## Explanation
This relies on the same idea as my [answer](https://codegolf.stackexchange.com/a/93854/6710) in J but instead of processing on each 3x3 subarray, I process over each row and each column while still obtaining the same table of indices.
Over half of the bytes are spent generating the list of box characters `'#───│┌┐┬│└┘┴│├┤┼ '`. String literals start with `“` in Jelly and have different meanings depending on their terminator. Here the terminator `’` means that the string will be parsed as the code points of each character according to the Jelly [code page](https://github.com/DennisMitchell/jelly/wiki/Code-page), and convert from a list of base 250 digits to a decimal.
```
“µ³Q~E!G⁸ṗṫ\’ => 10041542192416299030874093
(bijective base 61) => [1, 1, 1, 3, 13, 17, 45, 3, 21, 25, 53, 3, 29, 37, 61]
(add 9471 and convert to char) => '───│┌┐┬│└┘┴│├┤┼'
```
Then convert that decimal to a list of digits in bijective base 61 and increment each by 9471 to move it into the range of the box characters and convert each using Python's `chr`. Then prepend it with a character literal `”#` and append a space `⁶`.
```
ṖḤ0;+Ḋ×  Helper link - Input: 1d list A
Ṗ        Get all of A except the last value
 Ḥ       Double each value in it
  0;     Prepend a 0
    +    Add elementwise with
     Ḋ     All of A except the first value
      ×  Multiply elementwise by A
“µ³Q~E!G⁸ṗṫ\’ḃ61+9471Ọ⁾# j  Nilad. Represents '#───│┌┐┬│└┘┴│├┤┼ '
“µ³Q~E!G⁸ṗṫ\’               Get the code points of each char in the string and
                            convert from a list of base 250 digits to decimal
             ḃ61            Convert that to a list of digits in bijective base 61
                +9471       Add 9400 to each
                     Ọ      Convert from ordinals to chars, gets '───│┌┐┬│└┘┴│├┤┼'
                      ⁾#    A pair of chars ['#', ' ']
                         j  Join the pair using the box characters
ZÑ€4×Z++Ñ€ị¢Y  Input: 2d list M
Z              Transpose
 Ñ€            Apply the helper link to each row of the transpose (each column of M)
   4×          Multiply each by 4
     Z         Transpose
      +        Add elementwise with M
       +       Add elementwise with
        Ñ€       The helper link applied to each row of M
          ị¢   Use each result as an index to select into the nilad
            Y  Join using newlines
               Return and print implicitly
```
[Answer]
# Python 2.7, ~~318~~ 315 bytes (~~270~~ 267 chars)
I'm sure this can be golfed further (particularly I'd love to get rid of that annoying first-line comment) but here's my entry:
```
#encoding:utf-8
f=lambda t:(lambda l,s:'\n'.join(''.join((u'┼├┤│┬┌┐│┴└┘│───#'[(s==l[i][j-1])+2*(s==l[i][j+1])+4*(i<1 or s==l[i-1][j])+8*(i>len(l)-2 or s==l[i+1][j])],s)[s==l[i][j]]for j in range(len(l[i])-1))for i in range(len(l))))([l+' 'for l in t.split('\n')],' ')
```
Here's an explanation of how the whole thing works:
```
#encoding:utf-8 # Dammit, Python. This adds an extra 16 bytes!
f=lambda t:( # main lambda function
    lambda l,s: # inner lambda so we can pass it "local constants" (see last line)
        '\n'.join( # join each line
            ''.join( # join each char within the line
                (u'┼├┤│┬┌┐│┴└┘│───#'[ # string of all possible characters, indexed by binary 0-15 based on adjacent chars
                    (s==l[i][j-1])+ # left
                    2*(s==l[i][j+1])+ # right
                    4*(i<1 or s==l[i-1][j])+ # up ('i<1' just yields zero in case this is the first line, so that we don't get index problems)
                    8*(i>len(l)-2 or s==l[i+1][j])], # down ('i>len(l)-2' is same as above)
                s)[s==l[i][j]] # if original is space, choose space, else choose the previously chosen box-drawing char
                for j in range(len(l[i])-1)) # do this process for each char (excluding last, which is a space)
            for i in range(len(l))) # do this for each line
    )([l+' ' for l in t.split('\n')],' ') # call the inner lambda with two parameters: first, the text split into lines; second, a space char (actually makes code shorter)
```
EDIT: Removed some spaces before `for ... in ...`
[Answer]
# JavaScript (ES6), ~~150~~ ~~139~~ ~~133~~ 131 chars
```
a=>a.map((q,y)=>q.replace(/#/g,(c,x)=>"#│─┘─└─┴││┐┤┌├┬┼"[g=(X,Y=0)=>(a[Y+y]||[])[X+x]==c,g(0,1)*8+g(1)*4+g(-1)*2+g(0,-1)])).join`
`
```
Takes input as an array of strings, e.g. `f(["###", " # "])`.
### Test snippet
```
f=a=>a.map((q,y)=>q.replace(/#/g,(c,x)=>"#│─┘─└─┴││┐┤┌├┬┼"[g=(X,Y=0)=>(a[Y+y]||[])[X+x]==c,g(0,1)*8+g(1)*4+g(-1)*2+g(0,-1)])).join`
`
```
```
<textarea id=I rows=6># #### ## #
## #  ##  #
   ####  ##</textarea>
<br>
<button onclick="O.innerHTML=f(I.value.split('\n')).replace(/\n/g,'<br>')">Run</button>
<pre id=O></pre>
```
[Answer]
# Python 3, 149 bytes
```
def f(s):S=' ';w=s.find('\n')+1;t=lambda i:(s+w*S)[i]>S;return[[c,'#│─┘─└─┴││┐┤┌├┬┼'[t(p-w)+2*t(p-1)+4*t(p+1)+8*t(p+w)]][c>S]for p,c in enumerate(s)]
```
Takes input like `##\n #\n` and returns output like `['─', '┐', '\n', ' ', '│', '\n']`.
[Answer]
# [ALPACA](http://catseye.tc/node/ALPACA), 414 + 2 = 416 bytes
```
neighbourhoodV(^ v < >);states" ";statep"#"toA when4inV p,toB when3inV p andvs,toC when3inV p and^s,toD when3inV p and>s,toE when3inV p and<s,toF when2inV p and>s andvs,toG when2inV p andvs and<s,toH when2inV p and<s and^s,toI when2inV p and^s and>s,toJ when^p orvp,toK when<p or>p;stateA"┼";stateB"┴";stateC"┬";stateD"┤";stateE"├";stateF"┘";stateG"└";stateH"┌";stateI"┐";stateJ"│";stateK"─".
```
Requires the `-fI` flags.
This solution uses a very large number of bytes, but it is unique in that it uses a cellular automaton. ALPACA is usually used as a metalanguage, but here I'm using it as a programming language.
Ungolfed version:
```
neighbourhood V (^ v < >);
state s " ";
state p "#" to A when 4 in V p,
to B when 3 in V p and v s,
to C when 3 in V p and ^ s,
to D when 3 in V p and > s,
to E when 3 in V p and < s,
to F when 2 in V p and > s and v s,
to G when 2 in V p and v s and < s,
to H when 2 in V p and < s and ^ s,
to I when 2 in V p and ^ s and > s,
to J when ^ p or v p,
to K when < p or > p;
state A "┼";
state B "┴";
state C "┬";
state D "┤";
state E "├";
state F "┘";
state G "└";
state H "┌";
state I "┐";
state J "│";
state K "─".
```
[Answer]
# PHP, 203 bytes
This can probably be done in a shorter way.
```
while($s=fgets(STDIN))$f[]=$s;foreach($f as$y=>&$s)for($x=strlen($s);$x--;)if($s[$x]>$b=" ")$s[$x]="#───│┘└┴│┐┌┬│┤├┼"[($s[$x-1]>$b)+2*($s[$x+1]>$b)+4*($f[$y-1][$x]>$b)+8*($f[$y+1][$x]>$b)];echo join($f);
```
reads input from STDIN. run with `-r`.
[Answer]
# Perl, ~~89~~ 88 bytes
Includes +2 for `-0p`. The special characters are counted as 1 byte, but to make them actually display as single characters it's best to also add the -C option.
Give input on STDIN with the lines space padded so they all have the same length:
```
perl -C connect.pl
# #### ## #
## #  ##  #
   ####  ##
^D
```
`connect.pl`:
```
#!/usr/bin/perl -0p
/
/;$n=".{@-}";s%#%substr"#───│└┘┴│┌┐┬│├┤┼",/\G##/+2*/#\G/+4*/#$n\G/s+8*/\G#$n#/s,1%eg
```
[Answer]
# R, ~~199~~ 212 bytes
EDIT: It's now a function, rather than a code snippet.
The input is a matrix `m` of 1s and 0s. This is pretty ugly and hacky.
```
function(m){
v=strsplit(" #─│┘│┐│┤──└┴┌┬├┼","")[[1]]
d=dim(m)+1
n=array(0,dim=d+1)
n[2:d[1],2:d[2]]=m
for(i in 0:(d[1]-2)){for(j in 0:(d[2]-2))cat(v[1+(p<-n[2+i,2+j])*sum(2^(0:3)*n[1:3+i,1:3+j][1:4*2])+p]);cat("\n")}
}
```
A couple of tests:
```
> m = matrix(c(1, 1, 1, 0, 1, 0), nrow=2, byrow=TRUE)
> v=strsplit(" #─│┘│┐│┤──└┴┌┬├┼","")[[1]]
> d=dim(m)+1
> n=array(0,dim=d+1)
> n[2:d[1],2:d[2]]=m
> for(i in 0:(d[1]-2)){for(j in 0:(d[2]-2))cat(v[1+(p<-n[2+i,2+j])*sum(2^(0:3)*n[1:3+i,1:3+j][1:4*2])+p]);cat("\n")}
─┬─
 │ 
> m = matrix(rep(1, 16), ncol=4)
> v=strsplit(" #─│┘│┐│┤──└┴┌┬├┼","")[[1]]
> d=dim(m)+1
> n=array(0,dim=d+1)
> n[2:d[1],2:d[2]]=m
> for(i in 0:(d[1]-2)){for(j in 0:(d[2]-2))cat(v[1+(p<-n[2+i,2+j])*sum(2^(0:3)*n[1:3+i,1:3+j][1:4*2])+p]);cat("\n")}
┌┬┬┐
├┼┼┤
├┼┼┤
└┴┴┘
```
[Answer]
# MATL, 102 characters
I assign a neighbour a value (1, 2, 4 or 8); their sum will match a character in a string containing the drawing characters. I think there is still lots of room for improvements, but for a rough draft:
```
' #│││─┌└├─┐┘┤─┬┴┼' % String to be indexed
wt0J1+t4$(          % Get input, and append zeros at end of matrix (solely to avoid
                    %  indexing a non-existent second row/column for small inputs)
ttttt               % Get a whole load of duplicates to work on
3LXHY)              % Select rows 2:end from original matrix (one of the many dupes)
      w4LXIY)       % Select rows 1:end-1 from the 'destination' summing matrix)
             +HY(   % Add the neighbors below, store in 'destination' matrix
tIY)b3LY)2*+IY(     % +2* the neighbors above    +-------------------------------+
tHZ)b4LZ)4*+HZ(     % +4* the neighbors right    |(note: H and I contain 1:end-1 |
tIZ)b3LZ)8*+IZ(     % +8* the neighbors left     |  and 2:end respectively)      |
HH3$)               % Select the original matrix +-------------------------------+
*                % Make sure only cells that originally had a # get replaced
  1+)            % Add one because the original string is one-indexed. Index using ).
```
Improvements to be made:
* Possibly replace the whole summing part with some kind of loop working on rotated copies of the matrix
* Ditch the entire thing and make something based on a single loop working through the matrix
* *Use modular indexing to work on a flattened vector from the original array* **(?)**
[Try it Online!](http://matl.tryitonline.net/#code=JyAj4pSC4pSC4pSC4pSA4pSM4pSU4pSc4pSA4pSQ4pSY4pSk4pSA4pSs4pS04pS8J3d0MEoxK3Q0JCh0dHR0dDNMWEhZKXc0TFhJWSkrSFkodElZKWJIWSkyKitJWSh0SFopYklaKTQqK0haKHRJWiliSFopOCorSVooSEgzJCkqMSsp&input=WzEgMSAxOzAgMSAwOyAxIDAgMV0) (may not have box drawing characters support)
[Answer]
# [APL (Dyalog Extended)](https://github.com/abrudz/dyalog-apl-extended), 9 bytes
```
'#'⌂draw⊢
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT9dNrShJzUtJTfn/X11Z/VFPU0pRYvmjrkX/0x61TXjU2/eoq/nQeuNHbRMf9U0NDnIGkiEensH/04Gy1UAOWNFWhUfdLQoQnpHBo94t6rrqSEJpCjAlMMlarnQFQwUTEEdZWUFZHcgF2qAOZCqD@CAhBbCMAogD5ikoQCSBJFy5MlhCWQFJAKwdIgrVqAwFMEUKyghhqEIk@yEQZgBUKSFhoHZTBVOwb9QB "APL (Dyalog Extended) – Try It Online")
A built-in that solves the challenge (except that it accepts the `'*'` symbol as the default, so `'#'` needs to be supplied as an explicit argument). ¯\\_(⍨)\_/¯
Documentation is [here](http://dfns.dyalog.com/n_draw.htm).
---
A non-built-in solution, because a built-in is boring:
# [APL (Dyalog Extended)](https://github.com/abrudz/dyalog-apl-extended), 43 bytes
```
' #│─┌─┐─┬││└├┘┤┴┼'⊇⍨⊢×0 0{1+⊥⊢/4 2⍴⍵}⌺3 3⊢
```
[Try it online!](https://tio.run/##hU89S8NQFN39FRfucIcSTJt2dHJpp4L1DxSSZinq4KCUglipEJvSwhMdnETBQXBpF3HSf3L@SHpzk2g233sc3vm47/CGZ2MvvByOT2MvujiPTsIozLC87/UxX/mZEMNdw13BLQxXhu8m6nFwT3CPcC9wG7gvQXKL9A3J88@DT/6k2UDyqmy/TS2kG6TbKRafAQWqZSOtQLpEMvv@CDBfa@3g6FDxuNsbZLG6EyUW2hLubqhgLV9fEk9q0oiE5aCKVYHpXkxNaueEmViUaovolXOeS2QO5cQYUWEq/sbZDKaaYOOFWg5yuaoQ8Z9cBmv9xa4eKKP/yTreoY79RnY "APL (Dyalog Extended) – Try It Online")
An anonymous function that takes the boolean matrix as its argument. Incidentally it wins over Jelly even without the built-in.
The approach is pretty similar to many other answers (base-2 conversion from the four neighbors and index into the target string).
One interesting thing to note is that the box-drawing characters are [already part of the SBCS](https://tio.run/##SyzI0U2pTMzJT/8PBI/6pjqGcYHJR72b1RWUH01pejSl4dGUHjA5AUyuAQsC0ZRHU@Y8mjLj0ZQlj6ZseTRljzoA), so it is completely fine to use them in the code.
### How it works
```
' #│─┌─┐─┬││└├┘┤┴┼'⊇⍨⊢×0 0{1+⊥⊢/4 2⍴⍵}⌺3 3⊢
  0 0{          }⌺3 3⊢  ⍝ Map over 3×3 submatrices, with zero padding...
           4 2⍴⍵        ⍝ Reshape 3×3 to 4×2:
                        ⍝ . A .   . A
                        ⍝ B . C → . B
                        ⍝ . D .   . C
                        ⍝         . D
         ⊢/  ⍝ Take the last column
        ⊥    ⍝ Convert base 2 to integer
      1+     ⍝ Offset 1 to distinguish between ' ' and '#'
⊢×  ⍝ Mask the places for blanks
' #│─┌─┐─┬││└├┘┤┴┼'⊇⍨  ⍝ Convert each value in the matrix to the char at that index
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 45 bytes
```
ＷＳ⊞υιＰ⪫υ⸿Ｆ⪫υ⸿≡ι#§”y#─│┐──┌┬│┘│┤└┴├┼”↨ＥＫＶ›κ ²ι
```
[Try it online!](https://tio.run/##XU@xSgUxEOzvK5Zcs4GzsdRKG3nCkwPByibc2@eFd@aOXOITRBBrC4stLCwtLS39mvxI3JzYuAzDMAO7s11vfDeaIed9bwcCXLkphsvgrbtBraGNc4@xAauPq3Ucgp0kCXg@Wldsde2Vlmg7evhnwry3oesBrYaHqjMzgarVEbTLgpOwchu6R1Unfkr8nPh1EYKXxJ@L87bwR2JO/JX4PfG3auBUNuHaTNgS7a5Gd0Hx1jiHuoEzTyaQx510AKnQwKEu7Ta0NdL973b55THnGmoZKKgKQZGiAX4D4Sof3A0/ "Charcoal – Try It Online") Link is to verbose version of code. Takes input as a newline-terminated list of strings. Scored using 15 1-byte box drawing characters (normally 3 bytes each). Explanation:
```
ＷＳ⊞υι
```
Read in the text.
```
Ｐ⪫υ⸿
```
Print it without moving the cursor.
```
Ｆ⪫υ⸿
```
Loop over the text again.
```
≡ι#
```
If the current character is a `#`...
```
§”y#─│┐──┌┬│┘│┤└┴├┼”↨ＥＫＶ›κ ²
```
... then look up the box drawing character based on the presence of neighbours.
```
ι
```
Otherwise just print the current character.
]