22
\$\begingroup\$

Goal

You're playing a computerised chess game. The display is in black and white only and the pixels are chunky. White pixels use a lot power compared to black pixels and you're concerned about your carbon footprint.

Given a square and a piece in chess notation, return the number of white pixels displayed in the square.

The solution may be in the form of a function or a complete program.

Input

A 4-character string defining:

  1. One of wb for a white or black piece. (Not part of normal Chess notation, but required for this puzzle.)
  2. One of KQBNRP for a King, Queen, Bishop, kNight, Rook or Pawn.
  3. One of abcdefgh for the piece's file (column).
  4. One of 12345678 for the piece's rank (row).

Output

The number of white pixels used to draw the chess piece and the underlying square.

Requirements

  • Chess squares are 8x8 pixels and are either all white or all black.
  • a1 is a black square.
  • White chess pieces are drawn as white with a black outline. Black pieces are black with a white outline. All pieces have transparent pixels which show the underlying square.
  • Input is case-sensitive.
  • Assume the input is valid.

The chess pieces have sprites as follows.
. is the piece's colour.
# is the inverse of the piece's colour.
/ is the underlying square's colour.

King        Queen       Bishop  
////////    ////////    ////////
///#.#//    /#.#.#.#    ///#.#//
//#...#/    //#...#/    //##..#/
///#.#//    ///###//    //#.#.#/
///###//    //#...#/    ///###//
//#...#/    //#...#/    //#...#/
//#...#/    //#...#/    //#...#/
//#.#.#/    //#.#.#/    //#.#.#/

kNight      Rook        Pawn    
////////    ////////    ////////
////////    /#.#.#.#    ////////
//#..#//    /#.....#    ////////
/#....#/    /##...##    ///#.#//
///#..#/    //#...#/    //#...#/
//#..#//    //#...#/    ///#.#//
//#...#/    //#...#/    //#...#/
//#...#/    //#...#/    //#...#/

The number of pixels in the piece's colour, piece's outline and underlying square for each piece is:

Piece    Fill  Outline  Square
==============================
King     13    16       35
Queen    17    18       29
Bishop   13    18       33
Knight   16    12       36
Rook     23    18       23
Pawn     11    10       43

Test Cases

Input  Output
wRa1   23
bRa1   18
wPc2   54
bKg8   51

Scoring

The shortest code in bytes by Christmas Day gets a little something extra in their stocking.

\$\endgroup\$
0

7 Answers 7

6
\$\begingroup\$

C#6, 107 bytes

Here's my own answer. I don't expect any points being the one who posed the challenge.

I have taken some inspiration from user81655's answer.

long P(string a)=>(a[0]>99?12201284685:11042628752)+(a[2]+a[3])%2*46566348643>>"KQBNRP".IndexOf(a[1])*6&63;

The pixel counts are encoded in 6-bit blocks. The outline or fill is added to the square (if it's white). Finally, the 6-bit block for the appropriate piece is extracted.

Thankfully, operation precedence worked heavily in my favor.

\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 106

As an anonymous function.

x=>(o=+'137999'[p='PNKBQR'.search(x[1])],f=+'262149'[p]+p,(parseInt(x[2]+x[3],19)%2?9:55-f-o)+(x>'w'?f:o))

By now, I'm following the simplest way of find the answer with a calculation - this could be not the best way.

Over a black square, the answer is the size of fill for white pieces and the size of outline for black pieces. Over a white square, you need to add the free space. See the table below (inside the snippet)

I keep the size of fill and outline for each piece, the free space inside the square can be found subtracting from 64. To save space, the outline in stored as a single digit afer subtracing 9. The fill is trickier as the range is wider, check the code (that's way the pieces are sorted by occupied space)

Test snippet:

F=x=>(
  o=+'137999'[p='PNKBQR'.search(x[1])], // get outline - 9
  f=+'262149'[p]+p, // get fill -9
  (
    parseInt(x[2]+x[3],19) // parse with an odd base the differentiate between odd and even rows
    %2?9:55-f-o // black square if odd,, white if even so calc free space
  ) +(x>'w'?f:o) // add fill or outline based on piece color
)

// Test suite

console.log=x=>O.innerHTML+=x+'\n'

for(i=0; z='PNKBQR'[i]; i++)
{
  o = '';
  t = 'w'+z+'c2'; // white piece, white square
  o += t+' '+F(t)+', '
  t = 'b'+z+'c2'; // black piece, white square
  o += t+' '+F(t)+', '
  t = 'w'+z+'a1'; // white piece, black square
  o += t+' '+F(t)+', '
  t = 'b'+z+'a1'; // black piece, black square
  o += t+' '+F(t)
  console.log(o);
}
<pre>
Piece    Fill  Outline  Free  w/w b/w w/b b/b
=============================================
Pawn     11    10       43     54  53  11  10
Knight   16    12       36     52  48  16  12
King     13    16       35     48  51  13  16
Bishop   13    18       33     46  51  13  18
Queen    17    18       29     46  47  17  18
Rook     23    18       23     46  41  23  18
</pre>    
<pre id=O></pre>

\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 135 112 bytes

s=>(c={K:`\u000a\u0010\u0023`,Q:`\u0011\u0012\u001d`,B:`\u000a\u0012\u0021`,N:`\u0010\u000c\u0024`,R:`\u0017\u0012\u0017`,P:`\u000b\u000a\u002b`}[s[1]])[f="charCodeAt"](s<"w")+((s[f](2)-s[3])%2&&c[f](2))

Every \u00xx should be a single one-byte character. They are represented here as codes because Stack Exchange automatically removes unreadable characters from posts.

Explanation

s=>

  // c = string of three (mostly unreadable) characters, the ASCII code of each character
  //     represents the number of pixels in the fill, outline and square respectively
  (c={
    K:`\u000a\u0010\u0023`,
    Q:`\u0011\u0012\u001d`,
    B:`\u000a\u0012\u0021`,
    N:`\u0010\u000c\u0024`,
    R:`\u0017\u0012\u0017`,
    P:`\u000b\u000a\u002b`
  }[s[1]])

  [f="charCodeAt"](s<"w") // if piece is black add outline pixels, else add fill pixels
  +((s[f](2)-s[3])%2      // this returns 1 if the square is white or 0 if black
    &&c[f](2))            // if the square is white add the square's pixels

Test

var solution = s=>(c={K:`\u000a\u0010\u0023`,Q:`\u0011\u0012\u001d`,B:`\u000a\u0012\u0021`,N:`\u0010\u000c\u0024`,R:`\u0017\u0012\u0017`,P:`\u000b\u000a\u002b`}[s[1]])[f="charCodeAt"](s<"w")+((s[f](2)-s[3])%2&&c[f](2))
<input type="text" id="input" value="bKg8" />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>

\$\endgroup\$
0
2
\$\begingroup\$

Pyth, 54 53 bytes

The code contains unprintable characters, so here is a reversible xxd hexdump:

0000000: 732a 562b 5f57 2543 687a 322c 3031 2573  s*V+_W%Chz2,01%s
0000010: 434d 7474 7a32 4063 434d 2e22 0a2b 011e  CMttz2@cCM.".+..
0000020: d699 71d0 c6dc 3db8 eeae 2233 252a 4368  ..q...=..."3%*Ch
0000030: 747a 5433 31                             tzT31

Alternatively, here's a copy-paste friendly version, which you can also try online or use the test suite:

s*V+_W%Chz2,01%sCMttz2@cCM."\n+\x01\x1e\xd6\x99q\xd0\xc6\xdc=\xb8\xee\xae"3%*ChtzT31
\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js), 84 bytes

s=>[a=~"0628"[[C,P,F,R]=Buffer(s),i=P%11%7],b=-"63682"[i]||4][C&1]+(F+R&1?45-a-b:19)

Try it online!

How?

The color, the piece, the file and the rank characters are turned into ASCII codes which are saved into \$C\$, \$P\$, \$F\$ and \$R\$ respectively.

We compute the piece index \$i=(P \bmod 11)\bmod 7\$:

 char. | code | mod 11 | mod 7
-------+------+--------+-------
  'B'  |  66  |    0   |   0        Reordered by index:
  'K'  |  75  |    9   |   2      
  'N'  |  78  |    1   |   1         0 | 1 | 2 | 3 | 4 | 5
  'P'  |  80  |    3   |   3        ---+---+---+---+---+---
  'Q'  |  81  |    4   |   4         B | N | K | P | Q | R
  'R'  |  82  |    5   |   5

We compute \$a\$, which is the number of outline squares for the piece, minus \$19\$:

a = ~"0628"[i]

We compute \$b\$, which is the number of filled squares for the piece, minus \$19\$:

b = -"63682"[i] || 4

We use C & 1 to figure out the color of the piece and F + R & 1 to figure out the color of the square.

The final result is:

[a, b][C & 1]    // use outline squares if the piece is black
+                // or filled squares if the piece is white
(                //
  F + R & 1 ?    // if the square is white:
    45 - a - b   //   add 19 + (64 - ((a + 19) + (b + 19)))
                 //   = 45 - a - b
  :              // else:
    19           //   just add 19
)                //
\$\endgroup\$
1
\$\begingroup\$

Lua, 158 155 Bytes

c,p,l,n=(...):byte(1,4)m="KQBNRP"d={}d[1]={13,17,13,16,23,11}d[0]={16,18,18,12,18,10}p=m:find(string.char(p))print(d[c%2][p]+(l+n)%2*(64-d[0][p]-d[1][p]))

Could probably reduce the byte count by encoding the data, but I kinda like the current table method.

Bases color of the square on the ASCII value of 'w' or 'b' taking advantage of the fact that one is even and one is odd. Assigns integer value of the piece based on the position of the piece's symbol in the m string variable. Whether a square is dark or light is handled by (l+n)%2 taking advantage of ASCII value again.

Ungolfed

c,p,l,n=(...):byte(1,4)   --stores input of all characters into variables
m="KQBNRP"                --piece encoded string
d={}                      --data table
d[1]={13,17,13,16,23,11}  --fill
d[0]={16,18,18,12,18,10}  --outline
p=m:find(string.char(p))  --position in string for position in tables
print(d[c%2][p] +         --takes data element from corresponding table according to color of piece and type of piece
     (l+n)%2  *           --is square black or white? 0 if back, 1 if white
     (64-d[0][p]-d[1][p]) --if white, pixels not used by piece would be area (64) minus pixels used by piece, or corresponding data in the tables
     )

-3 Bytes by removing c=c%2 before the print and using d[c%2][p] instead of d[c][p].

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 41 bytes

Ç`+É•wH˜OÝ•44в*s11%©è•2ĀpakΩÕðβ•₂в2ä+sè®è

Try it online or verify all test cases.

Explanation:

Ç                          # Convert the (implicit) input to a list of codepoint integers
 `                         # Pop and push the four integers separated to the stack
  +                        # Add the top two together (column+row)
   É                       # Check if this is odd (1 if odd/white; 0 if even/black)
    •wH˜OÝ•                # Push compressed integer 245530244740
     44в                   # Convert it to base-44 as list: [33,36,35,43,29,23,0]
        *                  # Multiply each value by the odd-check
         s                 # Swap so the piece is at the top of the stack
          11%              # Modulo-11 on that integer
             ©             # Store it in variable `®` (without popping)
              è            # Index (0-based modulair) it into the list
               •2ĀpakΩÕðβ• # Push compressed integer 45866137874521319810
                ₂в         # Convert it to base-26 as list:
                           #  [18,12,16,10,18,18,0,13,16,13,11,17,23,0]
                  2ä       # Split it into two equal-sized parts:
                           #  [[18,12,16,10,18,18,0],[13,16,13,11,17,23,0]]
                    +      # Add the earlier indexed value to each
                     s     # Swap to get the final integer at the top (square-color)
                      è    # Index (0-based modulair) it into this pair of lists 
                       ®è  # And then index `®` (piece%11) into this list
                           # (after which the result is output implicitly)

See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why •wH˜OÝ• is 245530244740; •wH˜OÝ•44в is [33,36,35,43,29,23,0]; •2ĀpakΩÕðβ• is 45866137874521319810; and •2ĀpakΩÕðβ•₂в is [18,12,16,10,18,18,0,13,16,13,11,17,23,0].

The modulo-11 trick on the piece codepoint was inspired by @Arnauld's JavaScript answer. The trailing 0s in the lists are just fillers, since 05AB1E indexes modulair, so we don't need the modulo-7 that Arnauld uses.

Try it online for a step-by-step output.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.