place_queens.checkAvailablePosition()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 9
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nop 2
dl 0
loc 9
rs 9.95
c 0
b 0
f 0
1
from copy import deepcopy
2
from itertools import combinations
3
4
5
COLS = "abcdefgh"
6
ROWS = "12345678"
7
THREATS = {
8
    c
9
    + r: set(
10
        [c + ROWS[k] for k in range(8)]
11
        + [COLS[k] + r for k in range(8)]
12
        + [COLS[k] + ROWS[i - j + k] for k in range(8) if 0 <= i - j + k < 8]
13
        + [COLS[k] + ROWS[-k + i + j] for k in range(8) if 0 <= -k + i + j < 8]
14
    )
15
    for i, r in enumerate(ROWS)
16
    for j, c in enumerate(COLS)
17
}
18
19
20
def checkAvailablePosition(board, placed):
21
    tempBoard = deepcopy(board)
22
    for i in placed:
23
        if i not in tempBoard:
24
            tempBoard = []
25
            break
26
        threats = sorted(THREATS[i])
27
        tempBoard = [j for j in tempBoard if j not in threats]
28
    return tempBoard
29
30
31
def place_queens(placed):
32
    board = [c + r for c in COLS for r in ROWS]
33
    availablePositions = checkAvailablePosition(board, placed)
34
    # print availablePositions
35
    remainedQueens = 8 - len(placed)
36
    queenPositionCombinations = [
37
        i for i in combinations(availablePositions, remainedQueens)
38
    ]
39
    # print len(queenPositionCombinations)
40
    for position in queenPositionCombinations:
41
        colIndicators = set([i[0] for i in position] + [i[0] for i in placed])
42
        if len(colIndicators) < 8:
43
            continue
44
        rowIndicators = set([i[1] for i in position] + [i[1] for i in placed])
45
        if len(rowIndicators) < 8:
46
            continue
47
        i = list(position)
48
        tempPositions = deepcopy(availablePositions)
49
        while True:
50
            if len(i) == 1 and i[0] not in tempPositions:
51
                break
52
            queen = i.pop()
53
            tempPositions = checkAvailablePosition(tempPositions, [queen])
54
            if not tempPositions:
55
                break
56
        # i is empty means all queen can be positioned
57
        if not i:
58
            return set(list(placed) + list(position))
59
    return set({})
60
61
62
if __name__ == '__main__':
63
    # These "asserts" using only for self-checking and not necessary for
64
    # auto-testing
65
    def check_coordinate(coor):
66
        c, r = coor
67
        return c in COLS and r in ROWS
68
69 View Code Duplication
    def checker(func, placed, is_possible):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
70
        user_set = func(placed.copy())
71
        if not all(
72
            isinstance(c, str) and len(c) == 2 and check_coordinate(c) for c in user_set
73
        ):
74
            print("Wrong Coordinates")
75
            return False
76
        threats = []
77
        for f, s in combinations(user_set.union(placed), 2):
78
            if s in THREATS[f]:
79
                threats.append([f, s])
80
        if not is_possible:
81
            if user_set:
82
                print("Hm, how did you place them?")
83
                return False
84
            else:
85
                return True
86
        if not all(p in user_set for p in placed):
87
            print("You forgot about placed queens.")
88
            return False
89
        if is_possible and threats:
90
            print("I see some problems in this placement.")
91
            return False
92
        return True
93
94
    assert checker(place_queens, {"b2", "c4", "d6", "e8"}, True), "1st Example"
95
    assert checker(
96
        place_queens, {"b2", "c4", "d6", "e8", "a7", "g5"}, False
97
    ), "2nd Example"
98