lambda*a:(S:=sum(D:=-abs(mgrid[:8,:8].T-a).T,0))-(amin([*D//2,S//3,2//S],0)+S&-2)+equal(*D)*(S&-~amin(S)//6==-4)*2
from numpy import*
Attempt This Online!
Example, with arguments 1,2 (a=[1,2]
):
mgrid[:8,:8]
[[[0 0 0 0 0 0 0 0] [[0 1 2 3 4 5 6 7]
[1 1 1 1 1 1 1 1] [0 1 2 3 4 5 6 7]
[2 2 2 2 2 2 2 2] [0 1 2 3 4 5 6 7]
[3 3 3 3 3 3 3 3] [0 1 2 3 4 5 6 7]
[4 4 4 4 4 4 4 4] [0 1 2 3 4 5 6 7]
[5 5 5 5 5 5 5 5] [0 1 2 3 4 5 6 7]
[6 6 6 6 6 6 6 6] [0 1 2 3 4 5 6 7]
[7 7 7 7 7 7 7 7]] [0 1 2 3 4 5 6 7]]]
This produces two matrices that hold the co-ordinates.
D:=-abs(mgrid[:8,:8].T-a).T
[[[-1 -1 -1 -1 -1 -1 -1 -1] [[-2 -1 0 -1 -2 -3 -4 -5]
[ 0 0 0 0 0 0 0 0] [-2 -1 0 -1 -2 -3 -4 -5]
[-1 -1 -1 -1 -1 -1 -1 -1] [-2 -1 0 -1 -2 -3 -4 -5]
[-2 -2 -2 -2 -2 -2 -2 -2] [-2 -1 0 -1 -2 -3 -4 -5]
[-3 -3 -3 -3 -3 -3 -3 -3] [-2 -1 0 -1 -2 -3 -4 -5]
[-4 -4 -4 -4 -4 -4 -4 -4] [-2 -1 0 -1 -2 -3 -4 -5]
[-5 -5 -5 -5 -5 -5 -5 -5] [-2 -1 0 -1 -2 -3 -4 -5]
[-6 -6 -6 -6 -6 -6 -6 -6]] [-2 -1 0 -1 -2 -3 -4 -5]]]
Transpose, subtract a
, and transpose again: this subtracts the arguments from the two matrices, respectively. Also take the absolute value and negate.
This produces the negative vertical and horizontal distances from the given square.
S:=sum(D,0)
[[ -3 -2 -1 -2 -3 -4 -5 -6]
[ -2 -1 0 -1 -2 -3 -4 -5]
[ -3 -2 -1 -2 -3 -4 -5 -6]
[ -4 -3 -2 -3 -4 -5 -6 -7]
[ -5 -4 -3 -4 -5 -6 -7 -8]
[ -6 -5 -4 -5 -6 -7 -8 -9]
[ -7 -6 -5 -6 -7 -8 -9 -10]
[ -8 -7 -6 -7 -8 -9 -10 -11]]
Add the two matrices for the negative taxicab distance from the given square.
The reason for the negation is that we really want rounding-up division,
but only have easy access to rounding-down division with //
.
\$\lfloor\frac{-n}{d}\rfloor = -\lceil\frac{n}{d}\rceil\$
O:=amin([*D//2,S//3,2//S],0)
[[-1 -1 -2 -1 -1 -2 -2 -3]
[-1 -2 0 -2 -1 -2 -2 -3]
[-1 -1 -2 -1 -1 -2 -2 -3]
[-2 -1 -1 -1 -2 -2 -2 -3]
[-2 -2 -2 -2 -2 -2 -3 -3]
[-2 -2 -2 -2 -2 -3 -3 -3]
[-3 -3 -3 -3 -3 -3 -3 -4]
[-3 -3 -3 -3 -3 -3 -4 -4]]
The *D//2,S//3
part produces concentric octagons corresponding to
the furthest points the knight can reach in a number of moves. 2//S
is 0 with a RuntimeWarning for S=0, −2 for S=1, −1 for S≥2; it makes a difference only in the case S=1, changing the values of the squares adjacent to the given square from −1 to −2.
S-(O+S&-2)
[[1 2 3 2 1 2 3 4]
[2 3 0 3 2 3 2 3]
[1 2 3 2 1 2 3 4]
[2 1 2 1 2 3 2 3]
[3 2 3 2 3 2 3 4]
[2 3 2 3 2 3 4 3]
[3 4 3 4 3 4 3 4]
[4 3 4 3 4 3 4 5]]
A correction for parity: the number of moves should have the same parity as the the taxicab distance S
. Add S
, round down to the nearest multiple of 2 (by zeroing the low bit), and subtract S
; also negate and simplify.
Finally, some more adjustments:
+equal(*D)*(S&-~amin(S)//6==-4)*2
The squares two steps away along a diagonal should have value 4 instead of 2.
If the given square is a corner square, the diagonally adjacent square should also have value 4 instead of 2.
equal(*D)
checks for squares sharing a diagonal with the given square.
amin(S)
, the negated highest taxicab distance, is −14 if the given square is a corner square, and otherwise ranges from −8 (for a centre square) to −13.
-~amin(S)
is one higher: −13 for corner squares, −7 to −12 otherwise.
Floor-dividing by 6 produces −3 for corner squares and −2 otherwise.
On the diagonals, S is even. ANDing with −2 = ...11102 leaves it unchanged, whereas ANDing with −3 = ...11012 zeroes the twos bit, mapping both −2 and −4 to −4.
The result:
[[1 2 3 2 1 2 3 4]
[2 3 0 3 2 3 2 3]
[1 2 3 2 1 2 3 4]
[4 1 2 1 4 3 2 3]
[3 2 3 2 3 2 3 4]
[2 3 2 3 2 3 4 3]
[3 4 3 4 3 4 3 4]
[4 3 4 3 4 3 4 5]]
code-golf
. If you really want to accept an answer, you should wait one week or so and pick one that satisfies the winning criterion (i.e. the shortest one). \$\endgroup\$