Peaceful chess queen armies

From Rosetta Code
Revision as of 17:43, 23 March 2019 by rosettacode>Paddy3118 (New draft task with python example.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Peaceful chess queen armies is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

In chess, a queen attacks positions from where it is, in straight lines up-down and left-right as well as on both its diagonals. It attacks only pieces not of its own colour.

The goal of Peaceful chess queen armies is to arrange m black queens and m white queens on an n-by-n square grid, (the board), so that no queen attacks another of a different colour.

Detail
  1. Create a routine to represent two-colour queens on a 2-D board. (Alternating black/white colours, Unicode chess pieces and other embellishments are not necessary, but may be used at your discretion).
  2. Create a routine to generate at least one solution to placing m equal numbers of black and white queens on an n square board.
  3. Display here results for the m=4, n=5 case.

Python

<lang python>from itertools import combinations, count from functools import lru_cache, reduce


  1. n-by-n board

n = 5

def _2d(n=n):

 for i in range(n):
     print('  '.join(f'{i},{j}' for j in range(n)))

def _1d(n=n):

 for i in range(0, n*n, n):
     print(',  '.join(f'{i+j:2}' for j in range(n)))

_bbullet, _wbullet = '\u2022\u25E6'

  1. _bqueen, _wqueen = 'BW'

_bqueen, _wqueen = '\u265B\u2655' _or = set.__or__


def place(m, n):

   "Place m black and white queens, peacefully, on an n-by-n board"
   
   # 2-D Board as 1-D array:  2D(x, y) == 1D(t%n, t//n)
   board = set(range(n*n))
   #placements = list(combinations(board, m))
   placements = {frozenset(c) for c in combinations(board, m)}
   for blacks in placements:
       black_attacks = reduce(_or, 
                              (queen_attacks_from(pos, n) for pos in blacks), 
                              set())
       #for whites in placements:
       for whites in {frozenset(c) for c in combinations(board - black_attacks, m)}:
           if not black_attacks & whites:
               return blacks, whites
   return set(), set()

@lru_cache(maxsize=None) def queen_attacks_from(pos, n=n):

   a = set([pos])    # Its position
   a.update(range(pos//n*n, pos//n*n+n))    # Its row
   a.update(range(pos%n, n*n, n))           # Its column
   # Diagonals
   x0, y0 = pos%n, pos//n
   for x1 in range(n):
       # l-to-r diag
       y1 = y0 -x0 +x1
       if 0 <= y1 < n: 
           a.add(x1 + y1 * n)
       # r-to-l diag
       y1 = y0 +x0 -x1
       if 0 <= y1 < n: 
           a.add(x1 + y1 * n)
   return a

def pboard( black_white=None, n=n):

   if black_white is None: 
       blk, wht = set(), set()
   else:
       blk, wht = black_white
   print(f"## {len(blk)} black and {len(wht)} white queens "
         f"on a {n}-by-{n} board:", end=)
   for xy in range(n*n):
       if xy %n == 0:
           print()
       ch = ('?' if xy in blk and xy in wht 
             else _bqueen if xy in blk
             else _wqueen if xy in wht
             else _bbullet if (xy%n + xy//n)%2 else _wbullet)
       print('%s' % ch, end=)
   print()

if __name__ == '__main__':

   n=2
   for n in range(2, 7):
       print()
       queen_attacks_from.cache_clear()    # memoization cache
       #
       for m in count(1):
           ans = place(m, n)
           if ans[0]:
               pboard(ans, n)
           else:
               print (f"# Can't place {m}+ queens on a {n}-by-{n} board")
               break
   print('\n')    
   m, n = 5, 7
   queen_attacks_from.cache_clear()
   ans = place(m, n)
   pboard(ans, n)</lang>
Output:
# Can't place 1+ queens on a 2-by-2 board

## 1 black and 1 white queens on a 3-by-3 board:
◦•♛
♕◦•
◦•◦
# Can't place 2+ queens on a 3-by-3 board

## 1 black and 1 white queens on a 4-by-4 board:
◦•♛•
•◦•◦
◦•◦♕
•◦•◦
## 2 black and 2 white queens on a 4-by-4 board:
◦•♛♛
♕◦•◦
◦•◦•
•♕•◦
# Can't place 3+ queens on a 4-by-4 board

## 1 black and 1 white queens on a 5-by-5 board:
◦•◦•◦
•◦•◦•
♛•◦•◦
•◦•◦•
◦•◦♕◦
## 2 black and 2 white queens on a 5-by-5 board:
◦•♛•◦
•◦•♛•
◦♕◦•◦
•◦•◦•
◦•◦•♕
## 3 black and 3 white queens on a 5-by-5 board:
◦•◦♕♕
•◦•◦•
♛•◦•◦
•◦•◦♕
◦♛♛•◦
## 4 black and 4 white queens on a 5-by-5 board:
◦♕◦♕◦
•◦•◦♕
♛•♛•◦
•◦•◦♕
♛•♛•◦
# Can't place 5+ queens on a 5-by-5 board

## 1 black and 1 white queens on a 6-by-6 board:
◦•◦•◦•
•◦•◦•◦
◦•◦•◦•
•◦•◦•◦
◦•◦•♕•
•◦♛◦•◦
## 2 black and 2 white queens on a 6-by-6 board:
◦•◦•♛•
•◦•◦•◦
♕•◦•◦♕
•◦•◦•◦
◦♛◦•◦•
•◦•◦•◦
## 3 black and 3 white queens on a 6-by-6 board:
◦•♛•◦•
•◦•◦•◦
◦•◦•◦•
•♕•◦•◦
◦•◦♛◦♛
♕♕•◦•◦
## 4 black and 4 white queens on a 6-by-6 board:
♕•◦•♕•
•◦♛◦•◦
♕•◦•♕•
•◦♛◦•◦
◦•◦♛◦•
•◦♛◦•◦
## 5 black and 5 white queens on a 6-by-6 board:
♛•◦♛♛•
♛◦•♛•◦
◦•◦•◦•
•◦•◦•◦
◦♕♕•◦♕
•♕♕◦•◦
# Can't place 6+ queens on a 6-by-6 board


## 5 black and 5 white queens on a 7-by-7 board:
♕•◦•♕•◦
•◦•◦•◦♛
◦•◦♛◦•◦
•◦•◦•◦♛
◦♛◦•◦•◦
•◦♛◦•◦•
♕•◦•♕♕◦