Revision 56ddcd82-fca7-42fc-b80c-fb3da82393df - Code Golf Stack Exchange
# [MATL](https://github.com/lmendo/MATL), <s>48</s> <s>44</s> <s>42</s> <s>37</s> 33 bytes
t5BQ4B&vX^Z+*ssGt3Y6Z+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#@19i6hRo4qRWFhEXpa1VXOxeYhxpFqVtaKullpZSnhJZqf//f7SBAio0BEMYbahggA1ao@tBpQ2w68OhC68eBUMydBmSYZchhgtxmIzJszbEEgLo6gzRQ9QaFtr49eEKQ5xxgw3GAgA) Or [verify all test cases](https://tio.run/nexus/matl#zVa7DsIwDNz5ik4MdCAnHovFgtg6ITHwUBED4gdAIL6@SJWKaBrbaZpIKENVXRzH57Ody76oHov1dr4eP/fnYz6534vH7LA85lhNxrfr63p4T6vNrjqZrL1Qr@aLzLgW2Tbtr3HbMVaiTYYAKwT4QueGzMndP4KDAXsfbEapYVu24zhkc@Na5egknk59UWPFweIBKAJvBUFrps0zuTPkUkHHmjiWIUSEQJ6HxutVeclRRuP0WxuGRfkOJKNG7V5al8IAlIvXp7JNXL919UPqGCT3L8V7Dxwh@dKyHQnX9RSDHz1/snJ8qnA4rnUXnwmhzQgI8UPwP5Q/JNNvetxPX@n1Y3lh8y@/Ar57SH6/QMShnK/O7Oj67Tmd/w5PVz/x@l/3Ld0/v98d5Qc).
[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 (outdated)
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
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
2X^ % Push 2, take square root
* % Multiply. Diagonal distances are sqrt(2), not 1
+ % Add the two matricrs resulting from the convolutions
ss % Sum of all matrix entries. 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