Part 2 - Scala infrastructure source code (and two encoder/decoder implementations)
Part 3 - Scala solution source code (and interim encoder/decoder implementations)
The final solution encoder/decoder, HuffmanSimpleKingsPawnOptimal, described in a human readable pseudo-code format.
At a very high level, the number of pawns and their ability to be promoted are the primary constraint of the problem domain. So, a layered approach is used to contextually select an optimal encoding strategy which is then leveraged by the next layer down.
At a very high level, the number of pawns and their ability to be promoted are the primary constraint of the problem domain. So, a layered approach is used to contextually select an optimal encoding strategy which is then leveraged by the next layer down.
Details:
Here are the assumptions which were leveraged in the final solution:
- Both kings are always present in any valid board encoding - even the checkmate state is shown as the final board position prior to the capture of the king
- Of the 16 pawns present at the start of a game, a maximum of 12 may be promoted
- Due to the forced pawn promotion rule, there are never any pawns present on the first and last rows of the board
As this is not a description of the journey with which the solution was derived, I will jump straight into describing the decoder.
Decoding the header:
- UseRowDecoder: The first bit the decoder reads is used to select between two pawn decoding strategies; either by row (true) or by column (false)
- WhiteKing: The next 6 bits encode the position of the white king as a linear coordinate value; a value 0-63 inclusive
- BlackKing: The next 6 bits encode the position of the black king as a linear coordinate value; a value 0-63 inclusive
- PawnsToDecode: The next n bits (either 6 or 8 determined by UseRowDecoder) encode for each slice (either row or column) whether one or more pawns are present
Decoding each particular square:
- Index: set to 0 - this is the board squares index which will contain a single integer value of 0 to 63 (inclusive), decode guided by information captured in the header
- StartOfLoop: will decode guided by information captured in the header
- If Index is not equal to WhiteKing, goto IsBlackKing
- Mark the square at the current Index as White King
- Increment Index
- If Index less than 64, goto StartOfLoop else goto EndOfLoop
- IsBlackKing: If Index is not equal to BlackKing, goto IsPiece
- Mark the square at the current Index as Black King
- Increment Index
- If Index less than 64, goto StartOfLoop else goto EndOfLoop
- IsPiece: read a single bit
- If IsPiece is true, goto PieceColor
- Mark the square at the current Index as Empty
- Increment Index
- If Index less than 64, goto StartOfLoop else goto EndOfLoop
- PieceColor: read a single bit - black (0) or white (1)
- SegmentContainsPawns: using both UseRowDecoder and PawnsToDecode from header, figure out if segment for Index must decode for the presence of pawns (true) or not (false)
- If SegmentContainsPawns is false, goto Qbkr
- IsPawn: read a single bit
- If IsPawn is false, goto Qbkr
- Mark the square at the current Index as a PieceColor Pawn
- Increment Index
- If Index less than 64, goto StartOfLoop else goto EndOfLoop
- Qbkr: read two bits
- Mark the square at the current Index as a PieceColor Rook (00), Bishop (01), Knight (10) or Queen (11)
- Increment Index
- If Index less than 64, goto StartOfLoop
- EndOfLoop: input stream should be completely consumed
I know this would be quite a bit easier if I had some images to assist with seeing some of the data and logic. However, those take lots of extra time to generate. So, if/when I get some extra time (and motivation), I will come back and augment this post. Until then, please enjoy the human readable pseudo-code explanation above. :)
No comments:
Post a Comment