Seeing the queen's lasers

In chess, the queen piece can move arbitrarily far in each cardinal and intercardinal direction. What does this mean? Well, I'll show you with an ASCII drawing:

\..|../
.\.|./.
..\|/..
---Q---
../|\..
./.|.\.
/..|..\


It means the queen (notated as Q) can move along these lines (notated as \, |, /, and -), and cannot reach the other spaces (notated as .). The |s extend from the queen vertically, the -s horizontally, and the \/s diagonally.

However, I've quickly lost interest in chess and am more fixated on the diagram itself;

How many different symbols are contained within the 3x3 region centered on any given square? One way to visualize this would be to replace the symbols with this value, shown below:

2232322
2234322
3356533
2465642
3356533
2234322
2232322


Why? Well, for example:

The queen square has value 5 because the 3x3 region centered on the queen looks like this:

\|/
-Q-
/|\


Where we can see 5 distinct symbols: \|/-Q.

The top left square has value 2 because the 3x3 region around that square looks like this:


\.
.\


Where we can see 2 distinct symbols: \.. Anything beyond the board is not a symbol, so those space characters I've included for visualization purposes don't count.

Challenge:

Given the queen's position on an MxN board, output the number of unique symbols contained within the 3x3 region around each square, based on the queen movement diagram which would be generated. This is , so shortest wins :)

Rules:

• Standard I/O rules apply, any format to represent the grid size and the queen's position is fine in whatever order / format, and output can be plain text or a list of strings or whatever.
• Since any given cell can only see up to 6 different symbols, digits on a line do not need to be delimited in any way. Lines, however, must be clearly delimited, as the board is not necessarily square.
• 0 indexing is allowed.
• Input will always be valid; Board will always be at least 1 unit wide and at least 1 unit tall, and the queen's position will always be on the board.

Examples:

Formatted as

(board width, board height) (queen x, queen y)
image of board

output



Queen x and queen y given as 1 indexed, x being leftmost and y being topmost, output being 1 indexed as well. Your I/O format may differ from this.

Note that your program does not need to use the symbols Q\|/-., nor does it need to generate an image of the board at all. Only the number grid should be output.

(1, 1) (1, 1)
Q

1

(3, 3) (2, 2)
\|/
-Q-
/|\

454
555
454

(6, 3) (2, 2)
\|/...
-Q----
/|\...

455322
556422
455322

(2, 7) (1, 5)
|.
|.
|.
|/
Q-
|\
|.

22
22
33
55
55
55
33

(7, 2) (5, 1)
----Q--
.../|\.

2235553
2235553

(10, 10) (10, 10)
\........|
.\.......|
..\......|
...\.....|
....\....|
.....\...|
......\..|
.......\.|
........\|
---------Q

2221111122
2222111122
2222211122
1222221122
1122222122
1112222222
1111222232
1111122233
2222223355
2222222354

(7, 7) (4, 4)
\..|../
.\.|./.
..\|/..
---Q---
../|\..
./.|.\.
/..|..\

2232322
2234322
3356533
2465642
3356533
2234322
2232322


• I think it would also be an interesting challenge to draw the queen and her lasers in ASCII art Aug 11, 2022 at 18:32
• @Steffan That, and/or have it with multiple queens :P Aug 11, 2022 at 18:58
• @Steffan 25 bytes in Charcoal (i.e. the first 25 bytes of my answer).
– Neil
Aug 11, 2022 at 22:38
• Sometimes I wonder if the powershell coders are prevented from answering because the maximum size of an answer-post is 30,000 characters. :) Aug 13, 2022 at 13:55
• @thejonymyster sorry - that was humour. A coworker spent a day unpicking a thousand line powershell script that could be done in 10 lines of bash. Aug 15, 2022 at 2:54

MATL, 524948 45 bytes

9,i:i-]!=E2M+~+4KGY(3HGZ(3M*+^4Y6Z+9_YA!gsIGe


Input order is: board width, queen x, board height, queen y.

The code first generates the board using the numbers 1, 9, …, 59049 (first six powers of 9) instead of the symbols ., /, …, Q. Then 2-dimensional convolution with a 3×3 matrix containing ones is performed. This gives the sum of the 3×3 block centered in each cell. The desired result is the number of non-zero digits in the base-9 expansion of the sum for each cell.

Base 9 is sufficient (rather than base 10) because if the same character (.) appears 9 times in a 3×3 block the base-9 expansion will contain, due to carry, a digit 1 and the rest 0 (instead of a digit 9 and the rest 0 if base 10 were used), but the final result is 1 anyway.

Charcoal, 61 bytes

ＮθＮηＵＯθη.ＪＮＮＰ*⁺θηQＪ⁰¦⁰ＴθηＦηＦθ«Ｊκι≔⊞ＯＫＭＫＫδ⊞υΣＥδ∧Ｌλ⁼μ⌕δλ»⎚⪪⪫υωθ


Try it online! Link is to verbose version of code. 0-indexed. Explanation:

ＮθＮηＵＯθη.


Input the dimensions of the board and draw it.

ＪＮＮＰ*⁺θηQ


Draw the Queen's lasers and then the Queen herself.

Ｊ⁰¦⁰Ｔθη


Trim the lasers to size.

ＦηＦθ«


Loop over each square.

Ｊκι≔⊞ＯＫＭＫＫδ


Get the cell and its eight neighbours.

⊞υΣＥδ∧Ｌλ⁼μ⌕δλ


Save the count of distinct nontrivial neighbours.

»⎚⪪⪫υωθ


Clear the canvas and output the counts.

• the Queen herself :-D Aug 11, 2022 at 17:58
• was waiting for a charcoal answer lol Aug 11, 2022 at 17:59

APL(Dyalog Unicode), 52 bytes SBCS

{2 2↓{≢∪0~⍨,⍵}⌺3 3⊢(-2+⍵)↑2+(≠⍥|⊃×⍥×,2+,⍳=)/¨⍺∘-¨⍳⍵}


Try it on APLgolf!

Takes 0-indexed qy qx as left argument, and height width as the right argument.
Actually drawing the ascii art is a bit simpler (can be seen in the footer).

Python 3, 149 bytes

lambda w,h,x,y:[[len({(I==J,I==-J,I==0,J==0)for I in[i-1,i,i+1]for J in[j-1,j,j+1]if~x<I<w-x>~y<J<h-y})for i in range(-x,w-x)]for j in range(-y,h-y)]


Try it online!

The position of queen is 0-indexed.

Maybe someone may golf many bytes from it, but I'm not sure how to do that.

Python3, 468 bytes

R=range
U=lambda b,x,y:-1<x<len(b)>-1<y<len(b[0])
def V(b,m,x,y):
if r:=U(b,x,y)==1>b[x][y]:b[x][y]=m
return r
def l(x,y,Q):
b=eval('[0]*y,'*x);b[Q[0]][Q[1]]=5;B=eval(str(b));q=[(6,*Q,1,0),(7,*Q,0,1),(8,*Q,-1,1),(9,*Q,1,1)]
while q:m,x,y,X,Y=q.pop(0);q+=[(m,x+i*X,y+i*Y,X,Y)for i in[-1,1]if V(b,m,x+i*X,y+i*Y)]
return b,B
def f(X,Y,Q):
b,B=l(X,Y,Q)
for x in R(X):
for y in R(Y):B[x][y]=len({b[J][K]for J in R(x-1,x+2)for K in R(y-1,y+2)if U(B,J,K)})
return B


Try it online!

• 477 bytes Aug 11, 2022 at 21:32
• @Steffan Thanks, updated Aug 11, 2022 at 21:34
• 468, sorry Aug 11, 2022 at 21:34

05AB1E, 69 68 bytes

θDI¹->©н‚ß®W.ýD¹н‚ß¹н¹ß)vyN4%N8«.Λ}1A0.ΛS¶¡¶δ.ø¬g¶иšĆ2Fø€ü3}εε˜¶KÙg


Inputs as two loose pairs, in the order [queen x,queen y], [board width,board height].

Explanation:

(let's call the inputs [x,y] and [w,h] in the explanation below)

Step 1: Use the Canvas builtin to draw the shape (with 0123a instead of |/-\Q):

θ             # Push the last item of the first (implicit) input: y
D             # Duplicate it
I            # Push the second input [w,h]
¹-          # Subtract the first input: [w-x,h-y]
>         # Increase each by 1: [w-x+1,h-y+1]
©        # Store this in variable ® (without popping)
н       # Pop and push its first item: w-x+1
‚      # Pair it with the duplicated y
ß     # Pop the pair, and push its minimum: min(y,w-x+1)
®             # Push pair ® again: [w-x+1,h-y+1]
W            # Push its minimum (without popping): min(w-x+1,h-y+1)
.ý          # Add it to the middle of the pair: [w-x+1,min(w-x+1,h-y+1),h-y+1]
# Pop the triplet and push all three separated to the stack
D             # Duplicate the top h-y+1
¹н           # Push the first item of the first input: x
‚          # Pair them together: [h-y+1,x]
ß         # Pop and push the minimum: min(h-y+1,x)
¹н            # Push the first item of the first input: x
¹ß            # Push the minimum of the first input: min(x,y)
)             # Wrap all eight values on the stack into a list
v             # For-each over these values:
y            #  Push the current value
N           #  Push the 0-based loop-index
4%         #  Modulo-4
N        #  Push the 0-based loop-index again
8«      #  Append an 8
.Λ    #  Use the (modifiable) Canvas builtin with these three options
}             # Close the loop
.Λ        # Use the (modifiable) Canvas builtin again with the options:
1A0          #  1,"abcdefghijklmnopqrstuvwxyz",0


See this 05AB1E tip of mine for an in-depth explanation of the Canvas builtin. But in short, these are the steps it does:

1. Draw $$\y\$$ amount of '0' in direction ↑ (0), then reset back to the origin with 'direction' 8.
2. Draw $$\\min(y,w-x+1)\$$ amount of '1' in direction ↗ (1), and reset back to the origin again with 8.
3. Draw $$\w-x+1\$$ amount of '2' in direction → (2), and reset back to the origin again with 8.
4. Draw $$\\min(w-x+1,h-y+1)\$$ amount of '3' in direction ↘ (3), and reset back to the origin again with 8.
5. Draw $$\h-y+1\$$ amount of '0' in direction ↓ (4), and reset back to the origin again with 8.
6. Draw $$\\min(h-y+1,x)\$$ amount of '1' in direction ↙ (5), and reset back to the origin again with 8.
7. Draw $$\x\$$ amount of '2' in direction ← (6), and reset back to the origin again with 8.
8. Draw $$\\min(x,y)\$$ amount of '3' in direction ↖ (7), and reset back to the origin again with 8.
9. Draw $$\1\$$ character from string "abcdefghijklmnopqrstuvwxyz" (thus 'a') in direction ↑ (0).

Try just step 1 online.

Step 2: Add a no-op border (of newline characters) like a painting frame, and then get all overlapping 3x3 blocks:

S             # Convert it to a list of flattened characters
¶¡           # Split on newlines
δ         # Map over each row of characters:
¶ .ø       #  Surround it with a leading/trailing newline character
¬      # Push the first line (without popping the matrix)
g     # Pop and push its length
и   # Create a list of that many
¶    # newline characters
š  # Prepend it as first row
Ć # Enclose; appending its own head
2F            # Loop 2 times:
ø           #  Zip/transpose; swapping rows/columns
€          #  Map over each row:
ü3        #   Convert it to a list of overlapping triplets
}             # Close the loop


Try just the first two steps online.

Step 3: Remove all painting-frame newline characters, and count how many unique characters each 3x3 block contains, which is our resulting matrix:

εε            # Nested map over each 3x3 block:
˜           #   Flatten it to a list of characters
¶K         #   Remove all newline characters
Ù        #   Uniquify it
g       #   Pop and push its length
# (after which the resulting matrix is output implicitly as result)


JavaScript (ES10), 153 bytes

The position is 0-indexed. The method is similar to the one used by @tsh.

(w,h,x,y)=>(F=X=>Y<h?new Set([-!!X++,0,X<w].flatMap(p=>[-!!Y,0,Y<h-1].map(q=>[(H=X+~x+p)==(q+=Y-y),H==-q]+!H+!q))).size+[
[X-w]]+F(X<w?X:!++Y):'')(Y=0)


Try it online!

PARI/GP, 109 bytes

f(w,h,x,y)=matrix(h,w,i,j,#Set([[k-y==s=l-x,s==t=y-k,!s,!t]|n<-[0..8],(k=i-n%3)>=0&&k<h&&(l=j-n\3)>=0&&l<w]))

Attempt This Online!

A port of @tsh's Python answer. The position is 0-indexed.