Revision 9e9bdb28-6087-4561-a7db-0e6ac920c372 - Code Golf Stack Exchange
# [MATL](https://github.com/lmendo/MATL), <s>48</s> <s>44</s> 42 bytes
tH4hBZ+*zGt5OhBZ+*z2X^*+Gt3Y6Z+1=*&fdwdYy/
This takes the input as a binary matrix, with `;` as row separator. `1` corresponds to hash and `0` to space.
[Try it online!](https://tio.run/nexus/matl#@1/iYZLhFKWtVeVeYuoPYRlFxGlpu5cYR5pFaRvaaqmlpZSnRFbq//8fbaCACg3BEEYbKhhgg9boelBpA@z6cOjCq0fBkAxdhmTYZYjhQhwmY/KsDbGEALo6Q/QQtYaFNn59uMIQZ9xgg7EA) Or [verify all test cases](https://tio.run/nexus/matl#zVY9a8MwEN37Kzx1sIfq5aPL0aVkCHjIkiGJcekQSn@AITR/3oGEhFjS3cmyBEWDbJ5Op3v37qTvXd1368Xv56Eqz3W33Ny@Zruvsqq7@f79UOGjfP05no77v7d@te0bUwwHruM@ozC@QbbNcDZ@O8ZKtCkQYYUIX3BOyOzs/hE8DNjrYDNKd7ZlO45DNje@0b404u40FjVWHCwegSLyVBC0ZoY8kz9DPhU41sSxDCEiRPI8Nd6gysuOMhqn59owLMp3IBk1avfSuhQmoFy8IZVt0vq9Vj@kjkFy/1K8j8ARky8t24lwXU8p@NHzJysnpAqn41p3CbkhtDsCQvwQ/E/lD9n0mx8P01d@/Vhe2PzLr4DHGpLfLxBxKPurd3Zy/Y68nf8dnq9@0vU/9y09Pr@PFe0F).
[Here's](https://tio.run/nexus/matl#tZVBDoMgEEX3nmKSn5R9t249QnetSe9/CRsQlRm@CJiaGM0bGD9/Bly@w/PzmKbhtSxvJ/EC4G/IcblRtjDiLTgNmyiKYRRnI02eTtofPgyYLwb9OKT5dxW3ytVqk4XNw@FLnObGEhFkJMosElxmhhACS7A6pvLAfj0jwOW66vRoArlP0sIFgrRWkahOpUSQEd3ALmuMM2L0sDFVmZM8ocv0jvPDwHWX0xMNxALiUwtiDtdKZVbkntLWqESkN@lWJXvVjtqL0qgeXRXqR9zofle3ucav/CQL0KJw5huUj6LnUnOFCifRn1BftRv6fv91XZizWjj/AA) a format converter that takes inputs as 2D char arrays (again, with `;` as separator) and produces string representations of the corresponding binary matrices.
###Explanation
This was fun! The code uses _three_ two-dimensional convolutions, each for a different purpose:
1. To detect vertical and horizontal neighbours, which contribute a distance of `1`. The mask for that would be
0 1 0
1 0 1
0 1 0
But we only want each _pair_ of neighbours to be detected once. So we take half the mask (and the last row of zeros can be removed):
0 1 0
1 0 0
2. To detect diagonal neighbours, which contribute a distance of `sqrt(2)`. Again, each pair should contribute only once. So the mask
1 0 1
0 0 0
1 0 1
becomes
1 0 1
0 0 0
3. To detect start and end points. These are by definition the points with only one neighbour. Se we convolve with
1 1 1
1 0 1
1 1 1
and see which points give `1` as result.
The first two matrices are generated efficiently from binary expansions of a vector of two numbers. For example, expanding the vector `[2 4]` into binary produces the mask fo the first case (each number gives rise to a row). `[5 0]` produces the second. The third is a predefined literal.
t % Take input matrix implicitly. Duplicate
H4h % Push 2, then 4, concatenate: gives vector `[2 4]`
B % Convert to binary. Gives first mask
Z+ % 2D convolution, maintaining size
* % Multiply, to only keep results corresponding to 1 in the input
z % Number of nonzeros
Gt % Push input again. Duplicate
5Oh % Push 5, then 0, concatenate: gives vector `[5 0]`
B % Convert to binary. Gives second mask
Z+ % 2D convolution, maintaining size
* % Multiply, to only keep results corresponding to 1 in the input
z % Number of nonzeros
2X^ % Push 2, take square root
* % Multiply. Diagonal distances are sqrt(2), not 1
+ % Add. This gives total distance
Gt % Push input again. Duplicate
3Y6 % Predefined literal. This gives third mask
Z+ % 2D convolution, maintaining size
1= % Values different than 1 are set to 0
* % Multiply, to only keep results corresponding to 1 in the input
&f % Push array of row indices and array of column indices of nonzeros
d % Difference. This is the horizontal difference between start and end
wd % Swap, difference. This is the vertical difference between start and end
Yy % Hypothenuse. This gives total distance in straight line
/ % Divide. Display implicitly