public
Description: Some random scripts
Homepage: http://blog.paulbonser.com/
Clone URL: git://github.com/pib/scripts.git
pib (author)
Sun Nov 30 13:55:30 -0800 2008
commit  60b2a76e0e77a34a2d144d0e9682db353dac9c5e
tree    af883412b8465fc0baa4b0b5d42bca26228a9223
parent  3568c045182f25fe32b997365a3dc150779e2411
scripts / knight.py
100644 69 lines (59 sloc) 2.311 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class chessboard:
    cps = ((-2,-1),(-2,1),(-1,2),(1,2),(2,1),(2,-1),(1,-2),(-1,-2))
    def __init__(self,n,m,i,j):
        self.size = (n, m)
        self.pos = self.start = (i,j)
        self.board = [[0]*m for i in range(n)]
        self.move_board = [[0]*m for i in range(n)]
        self.set_weights()
        self.moves = [(i, j)]
    
    def on_board(self, i, j):
        return (i>=0) and (j>=0) and (i<(self.size[0])) and (j<(self.size[1]))
    
    def zero(self, pos):
        for i, j in ((pos[0]+i, pos[1]+j) for i, j in self.cps):
            if self.on_board(i,j) and (self.board[i][j] != 0):
                self.board[i][j] -= 1
        self.board[pos[0]][pos[1]] = 0
 
    def set_weights(self):
        rangen, rangem = range(self.size[0]), range(self.size[1])
        for i, j in ((i,j) for i in rangen for j in rangem):
            for ci, cj in ((i+c[0], j+c[1]) for c in self.cps):
                if self.on_board(ci, cj): self.board[i][j] += 1
 
    def get_lowest(self, pos):
        neighbors = [(pos[0]+i, pos[1]+j) for i, j in self.cps]
        lowv = min(((self.board[i][j], i, j) for i, j in neighbors
                    if self.on_board(i, j)), key=lambda x: x[0] or 9)
        if lowv[0] in (0, 9): return None
        return lowv[1:]
    
    def solve(self):
        i = 1
        while True:
            low = self.get_lowest(self.pos)
            self.zero(self.pos)
            if not low: break
            self.pos = pos = low
            self.moves.append(low)
            self.move_board[low[0]][low[1]] = i
            i += 1
 
        if i == (self.size[0] * self.size[1]):
            if self.start in ((pos[0]+i, pos[1]+j) for i, j in self.cps):
                self.tour_type = "closed"
            else:
                self.tour_type = "open"
        else: self.tour_type = "incomplete"
    
    def __str__(self):
        out = ''
        for i in range(self.size[0]):
            for j in range(self.size[1]):
                out += "%02d " % self.move_board[i][j]
            out += "\n"
        return out
 
def main(n):
    b = chessboard(n,n, 0, 0)
    b.solve()
    print b, # solution!
    print "Found a Knight's tour that is", b.tour_type
 
if __name__=="__main__":
    import sys
    if len(sys.argv) < 2: main(8, 8)
    else: main(int(sys.argv[1]))