1
$\begingroup$

This is a problem inspired by a video game that I've been thinking about for a long while, and I haven't convinced myself that I can do any better than brute force + pruning techniques, which would still take way too long to solve.

Is there anything better? Any class of algorithm I should look into more?

Problem description

  • You are on a checkerboard. Let's say 8x8 for now, but interested in general solutions too.
    ┌───┬───┬───┬───┬───┬───┬───┬───┐
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    └───┴───┴───┴───┴───┴───┴───┴───┘
    
  • There is a "start square" on the board, somewhere along the edge.
    ┌───┬───┬───┬───┬───┬───┬───┬───┐
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │ S │   │   │   │
    └───┴───┴───┴───┴───┴───┴───┴───┘
    
  • You may place checkers onto the board anywhere you like, with the following restrictions:
    • You cannot place a checker on the start square.
    • Each square may contain 0 or 1 checker; you can't place multiple in one square.
    • All checkers must be "reachable" (described further in the next bullet).
  • From the start square, you are able to traverse the board, using up/down/left/right movements to adjacent squares (diagonals are not considered adjacent).
    • You cannot "traverse" into a square that is occupied by a checker.
    • You must remain on the board.
    • To "reach" a given checker, you must be able to traverse to a square adjacent to the square that checker is placed on.
  • What is the maximum amount of checkers you can place on the board?

Examples

  • Valid (but not the maximum solution: this has 36, I've found 38 by hand for this start square configuration):
    ┌───┬───┬───┬───┬───┬───┬───┬───┐
    │ ● │ ● │ ● │ ● │ ● │ ● │ ● │ ● │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │ ● │ ● │ ● │ ● │ ● │ ● │ ● │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │ ● │ ● │ ● │ ● │ ● │ ● │ ● │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │ ● │ ● │ ● │ ● │ ● │ ● │ ● │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │ ● │ ● │ ● │ ● │ ● │ ● │ ● │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │ S │   │   │   │
    └───┴───┴───┴───┴───┴───┴───┴───┘
    
  • Valid (but definitely not the maximum):
    ┌───┬───┬───┬───┬───┬───┬───┬───┐
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │ ● │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │ ● │ S │ ● │   │   │
    └───┴───┴───┴───┴───┴───┴───┴───┘
    
  • Invalid (corner checker is not "reachable"):
    ┌───┬───┬───┬───┬───┬───┬───┬───┐
    │ ● │ ● │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │ ● │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │   │   │   │   │
    ├───┼───┼───┼───┼───┼───┼───┼───┤
    │   │   │   │   │ S │   │   │   │
    └───┴───┴───┴───┴───┴───┴───┴───┘
    

My current approach

My current approach is just brute force, unfortunately:

  • Generate a 2d bool array (for an 8x8 checkerboard, I'd just use a 64-bit int)
  • Flood-fill from the start square for "reachability"
  • Check every checker and make sure it's "reachable"
  • As you find valid boards with n checkers, you can stop trying any board that has <= n checkers.

Obviously, for an n by m board (with one start square), you'd have to check 2^(n*m-1) different combinations to be sure you found the maximum. Not great.

One realization I've had is that if a given checker configuration is invalid, adding more checkers to it won't magically make it valid. So, there's some opportunity to prune the problem space that way, but I'm not sure if there's an efficient way to implement it. Turning this into a recursive problem ("if you have a valid board, try adding one more checker to it in all available locations, and recurse for any of those boards that are valid") would end up either:

  • trying certain configurations much more than once (depth-first), or
  • turning the problem into a 2^(n*m-1) memory complexity problem to prevent that, I think? (breadth-first).
$\endgroup$

1 Answer 1

0
$\begingroup$

One approach would be to express this as an instance of SAT, and use an off-the-shelf SAT solver. See Boolean constraints for a connected component of a graph for a technique for encoding reachability and thus enforcing all of your constraints via a CNF formula.

In particular, you can use SAT to check whether there exists a solution with (for example) at least 37 checkers. Then, you can use binary search to vary the number 37 and find the largest number such that there exists a valid solution.

Alternatively, you could encode it as an instance of integer linear programming, where the goal is to maximize the number of checkers (which is a linear objective function), and then solve it with an off-the-shelf ILP solver. See also Express boolean logic operations in zero-one integer linear programming (ILP) for how to convert logical constraints to ILP.

$\endgroup$
1
  • $\begingroup$ Nice! I've never worked with a SAT solver before, that was very enjoyable to learn how to use. The first link was very helpful for wrapping my head around how to write connected component constraints. $\endgroup$
    – crs
    Commented Nov 14, 2023 at 20:25

Your Answer

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

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