Data update
This commit is contained in:
parent
72eb4943cb
commit
4d5544505c
2347 changed files with 62432 additions and 16731 deletions
13
Task/N-queens-problem/Python/n-queens-problem-10.py
Normal file
13
Task/N-queens-problem/Python/n-queens-problem-10.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
$ python3 ./queens.py
|
||||
['a1', 'b7', 'c5', 'd8', 'e2', 'f4', 'g6', 'h3']
|
||||
['a1', 'b7', 'c4', 'd6', 'e8', 'f2', 'g5', 'h3']
|
||||
['a6', 'b1', 'c5', 'd2', 'e8', 'f3', 'g7', 'h4']
|
||||
['a4', 'b1', 'c5', 'd8', 'e2', 'f7', 'g3', 'h6']
|
||||
['a5', 'b1', 'c8', 'd4', 'e2', 'f7', 'g3', 'h6']
|
||||
['a3', 'b1', 'c7', 'd5', 'e8', 'f2', 'g4', 'h6']
|
||||
['a5', 'b1', 'c4', 'd6', 'e8', 'f2', 'g7', 'h3']
|
||||
['a7', 'b1', 'c3', 'd8', 'e6', 'f4', 'g2', 'h5']
|
||||
['a5', 'b1', 'c8', 'd6', 'e3', 'f7', 'g2', 'h4']
|
||||
['a5', 'b3', 'c1', 'd7', 'e2', 'f8', 'g6', 'h4']
|
||||
['a5', 'b7', 'c1', 'd4', 'e2', 'f8', 'g6', 'h3']
|
||||
['a6', 'b3', 'c1', 'd8', 'e4', 'f2', 'g7', 'h5']
|
||||
|
|
@ -6,6 +6,5 @@ def queens(n: int, i: int, a: list, b: list, c: list):
|
|||
else:
|
||||
yield a
|
||||
|
||||
|
||||
for solution in queens(8, 0, [], [], []):
|
||||
print(solution)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,23 @@
|
|||
def queens(i: int, a: set):
|
||||
if a: # set a is not empty
|
||||
for j in a:
|
||||
if i + j not in b and i - j not in c:
|
||||
b.add(i + j); c.add(i - j); x.append(j)
|
||||
yield from queens(i + 1, a - {j})
|
||||
b.remove(i + j); c.remove(i - j); x.pop()
|
||||
else:
|
||||
yield x
|
||||
def queens(n: int):
|
||||
|
||||
def sub(i: int):
|
||||
if i < n:
|
||||
for k in range(i, n):
|
||||
j = a[k]
|
||||
if b[i + j] and c[i - j]:
|
||||
a[i], a[k] = a[k], a[i]
|
||||
b[i + j] = c[i - j] = False
|
||||
yield from sub(i + 1)
|
||||
b[i + j] = c[i - j] = True
|
||||
a[i], a[k] = a[k], a[i]
|
||||
else:
|
||||
yield a
|
||||
|
||||
a = list(range(n))
|
||||
b = [True] * (2 * n - 1)
|
||||
c = [True] * (2 * n - 1)
|
||||
yield from sub(0)
|
||||
|
||||
|
||||
b = set(); c = set(); x = []
|
||||
for solution in queens(0, set(range(8))):
|
||||
print(solution)
|
||||
sum(1 for solution in queens(8)) # count solutions
|
||||
92
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
def queens(n: int):
|
||||
def queens_lex(n: int):
|
||||
|
||||
def sub(i: int):
|
||||
if i < n:
|
||||
for k in range(i, n):
|
||||
j = a[k]
|
||||
a[i], a[k] = a[k], a[i]
|
||||
if b[i + j] and c[i - j]:
|
||||
a[i], a[k] = a[k], a[i]
|
||||
b[i + j] = c[i - j] = False
|
||||
yield from sub(i + 1)
|
||||
b[i + j] = c[i - j] = True
|
||||
a[i], a[k] = a[k], a[i]
|
||||
a[i:(n - 1)], a[n - 1] = a[(i + 1):n], a[i]
|
||||
else:
|
||||
yield a
|
||||
|
||||
|
|
@ -19,5 +19,11 @@ def queens(n: int):
|
|||
yield from sub(0)
|
||||
|
||||
|
||||
sum(1 for p in queens(8)) # count solutions
|
||||
92
|
||||
next(queens(31))
|
||||
[0, 2, 4, 1, 3, 8, 10, 12, 14, 6, 17, 21, 26, 28, 25, 27, 24, 30, 7, 5, 29, 15, 13, 11, 9, 18, 22, 19, 23, 16, 20]
|
||||
|
||||
next(queens_lex(31))
|
||||
[0, 2, 4, 1, 3, 8, 10, 12, 14, 5, 17, 22, 25, 27, 30, 24, 26, 29, 6, 16, 28, 13, 9, 7, 19, 11, 15, 18, 21, 23, 20]
|
||||
|
||||
#Compare to A065188
|
||||
#1, 3, 5, 2, 4, 9, 11, 13, 15, 6, 8, 19, 7, 22, 10, 25, 27, 29, 31, 12, 14, 35, 37, ...
|
||||
|
|
|
|||
|
|
@ -1,29 +1,146 @@
|
|||
def queens_lex(n: int):
|
||||
'''N Queens problem'''
|
||||
|
||||
def sub(i: int):
|
||||
if i < n:
|
||||
for k in range(i, n):
|
||||
j = a[k]
|
||||
a[i], a[k] = a[k], a[i]
|
||||
if b[i + j] and c[i - j]:
|
||||
b[i + j] = c[i - j] = False
|
||||
yield from sub(i + 1)
|
||||
b[i + j] = c[i - j] = True
|
||||
a[i:(n - 1)], a[n - 1] = a[(i + 1):n], a[i]
|
||||
else:
|
||||
yield a
|
||||
|
||||
a = list(range(n))
|
||||
b = [True] * (2 * n - 1)
|
||||
c = [True] * (2 * n - 1)
|
||||
yield from sub(0)
|
||||
from functools import reduce
|
||||
from itertools import chain
|
||||
|
||||
|
||||
next(queens(31))
|
||||
[0, 2, 4, 1, 3, 8, 10, 12, 14, 6, 17, 21, 26, 28, 25, 27, 24, 30, 7, 5, 29, 15, 13, 11, 9, 18, 22, 19, 23, 16, 20]
|
||||
# queenPuzzle :: Int -> Int -> [[Int]]
|
||||
def queenPuzzle(nCols):
|
||||
'''All board patterns of this dimension
|
||||
in which no two Queens share a row,
|
||||
column, or diagonal.
|
||||
'''
|
||||
def go(nRows):
|
||||
lessRows = nRows - 1
|
||||
return reduce(
|
||||
lambda a, xys: a + reduce(
|
||||
lambda b, iCol: b + [xys + [iCol]] if (
|
||||
safe(lessRows, iCol, xys)
|
||||
) else b,
|
||||
enumFromTo(1)(nCols),
|
||||
[]
|
||||
),
|
||||
go(lessRows),
|
||||
[]
|
||||
) if 0 < nRows else [[]]
|
||||
return go
|
||||
|
||||
next(queens_lex(31))
|
||||
[0, 2, 4, 1, 3, 8, 10, 12, 14, 5, 17, 22, 25, 27, 30, 24, 26, 29, 6, 16, 28, 13, 9, 7, 19, 11, 15, 18, 21, 23, 20]
|
||||
|
||||
#Compare to A065188
|
||||
#1, 3, 5, 2, 4, 9, 11, 13, 15, 6, 8, 19, 7, 22, 10, 25, 27, 29, 31, 12, 14, 35, 37, ...
|
||||
# safe :: Int -> Int -> [Int] -> Bool
|
||||
def safe(iRow, iCol, pattern):
|
||||
'''True if no two queens in the pattern
|
||||
share a row, column or diagonal.
|
||||
'''
|
||||
def p(sc, sr):
|
||||
return (iCol == sc) or (
|
||||
sc + sr == (iCol + iRow)
|
||||
) or (sc - sr == (iCol - iRow))
|
||||
return not any(map(p, pattern, range(0, iRow)))
|
||||
|
||||
|
||||
# ------------------------- TEST -------------------------
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Number of solutions for boards of various sizes'''
|
||||
|
||||
n = 5
|
||||
xs = queenPuzzle(n)(n)
|
||||
|
||||
print(
|
||||
str(len(xs)) + ' solutions for a {n} * {n} board:\n'.format(n=n)
|
||||
)
|
||||
print(showBoards(10)(xs))
|
||||
|
||||
print(
|
||||
fTable(
|
||||
'\n\n' + main.__doc__ + ':\n'
|
||||
)(str)(lambda n: str(n).rjust(3, ' '))(
|
||||
lambda n: len(queenPuzzle(n)(n))
|
||||
)(enumFromTo(1)(10))
|
||||
)
|
||||
|
||||
|
||||
# ---------------------- FORMATTING ----------------------
|
||||
|
||||
# showBoards :: Int -> [[Int]] -> String
|
||||
def showBoards(nCols):
|
||||
'''String representation, with N columns
|
||||
of a set of board patterns.
|
||||
'''
|
||||
def showBlock(b):
|
||||
return '\n'.join(map(intercalate(' '), zip(*b)))
|
||||
|
||||
def go(bs):
|
||||
return '\n\n'.join(map(
|
||||
showBlock,
|
||||
chunksOf(nCols)([
|
||||
showBoard(b) for b in bs
|
||||
])
|
||||
))
|
||||
return go
|
||||
|
||||
|
||||
# showBoard :: [Int] -> String
|
||||
def showBoard(xs):
|
||||
'''String representation of a Queens board.'''
|
||||
lng = len(xs)
|
||||
|
||||
def showLine(n):
|
||||
return ('.' * (n - 1)) + '♛' + ('.' * (lng - n))
|
||||
return map(showLine, xs)
|
||||
|
||||
|
||||
# fTable :: String -> (a -> String) ->
|
||||
# (b -> String) -> (a -> b) -> [a] -> String
|
||||
def fTable(s):
|
||||
'''Heading -> x display function -> fx display function ->
|
||||
f -> xs -> tabular string.
|
||||
'''
|
||||
def go(xShow, fxShow, f, xs):
|
||||
ys = [xShow(x) for x in xs]
|
||||
w = max(map(len, ys))
|
||||
return s + '\n' + '\n'.join(map(
|
||||
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
|
||||
xs, ys
|
||||
))
|
||||
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
|
||||
xShow, fxShow, f, xs
|
||||
)
|
||||
|
||||
|
||||
# ----------------------- GENERIC ------------------------
|
||||
|
||||
# enumFromTo :: (Int, Int) -> [Int]
|
||||
def enumFromTo(m):
|
||||
'''Integer enumeration from m to n.'''
|
||||
return lambda n: range(m, 1 + n)
|
||||
|
||||
|
||||
# chunksOf :: Int -> [a] -> [[a]]
|
||||
def chunksOf(n):
|
||||
'''A series of lists of length n, subdividing the
|
||||
contents of xs. Where the length of xs is not evenly
|
||||
divible, the final list will be shorter than n.
|
||||
'''
|
||||
return lambda xs: reduce(
|
||||
lambda a, i: a + [xs[i:n + i]],
|
||||
range(0, len(xs), n), []
|
||||
) if 0 < n else []
|
||||
|
||||
|
||||
# intercalate :: [a] -> [[a]] -> [a]
|
||||
# intercalate :: String -> [String] -> String
|
||||
def intercalate(x):
|
||||
'''The concatenation of xs
|
||||
interspersed with copies of x.
|
||||
'''
|
||||
return lambda xs: x.join(xs) if isinstance(x, str) else list(
|
||||
chain.from_iterable(
|
||||
reduce(lambda a, v: a + [x, v], xs[1:], [xs[0]])
|
||||
)
|
||||
) if xs else []
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -1,146 +1,34 @@
|
|||
'''N Queens problem'''
|
||||
|
||||
from functools import reduce
|
||||
from itertools import chain
|
||||
|
||||
|
||||
# queenPuzzle :: Int -> Int -> [[Int]]
|
||||
def queenPuzzle(nCols):
|
||||
'''All board patterns of this dimension
|
||||
in which no two Queens share a row,
|
||||
column, or diagonal.
|
||||
'''
|
||||
def go(nRows):
|
||||
lessRows = nRows - 1
|
||||
return reduce(
|
||||
lambda a, xys: a + reduce(
|
||||
lambda b, iCol: b + [xys + [iCol]] if (
|
||||
safe(lessRows, iCol, xys)
|
||||
) else b,
|
||||
enumFromTo(1)(nCols),
|
||||
[]
|
||||
),
|
||||
go(lessRows),
|
||||
[]
|
||||
) if 0 < nRows else [[]]
|
||||
return go
|
||||
|
||||
|
||||
# safe :: Int -> Int -> [Int] -> Bool
|
||||
def safe(iRow, iCol, pattern):
|
||||
'''True if no two queens in the pattern
|
||||
share a row, column or diagonal.
|
||||
'''
|
||||
def p(sc, sr):
|
||||
return (iCol == sc) or (
|
||||
sc + sr == (iCol + iRow)
|
||||
) or (sc - sr == (iCol - iRow))
|
||||
return not any(map(p, pattern, range(0, iRow)))
|
||||
|
||||
|
||||
# ------------------------- TEST -------------------------
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Number of solutions for boards of various sizes'''
|
||||
|
||||
n = 5
|
||||
xs = queenPuzzle(n)(n)
|
||||
|
||||
print(
|
||||
str(len(xs)) + ' solutions for a {n} * {n} board:\n'.format(n=n)
|
||||
)
|
||||
print(showBoards(10)(xs))
|
||||
|
||||
print(
|
||||
fTable(
|
||||
'\n\n' + main.__doc__ + ':\n'
|
||||
)(str)(lambda n: str(n).rjust(3, ' '))(
|
||||
lambda n: len(queenPuzzle(n)(n))
|
||||
)(enumFromTo(1)(10))
|
||||
)
|
||||
|
||||
|
||||
# ---------------------- FORMATTING ----------------------
|
||||
|
||||
# showBoards :: Int -> [[Int]] -> String
|
||||
def showBoards(nCols):
|
||||
'''String representation, with N columns
|
||||
of a set of board patterns.
|
||||
'''
|
||||
def showBlock(b):
|
||||
return '\n'.join(map(intercalate(' '), zip(*b)))
|
||||
|
||||
def go(bs):
|
||||
return '\n\n'.join(map(
|
||||
showBlock,
|
||||
chunksOf(nCols)([
|
||||
showBoard(b) for b in bs
|
||||
])
|
||||
))
|
||||
return go
|
||||
|
||||
|
||||
# showBoard :: [Int] -> String
|
||||
def showBoard(xs):
|
||||
'''String representation of a Queens board.'''
|
||||
lng = len(xs)
|
||||
|
||||
def showLine(n):
|
||||
return ('.' * (n - 1)) + '♛' + ('.' * (lng - n))
|
||||
return map(showLine, xs)
|
||||
|
||||
|
||||
# fTable :: String -> (a -> String) ->
|
||||
# (b -> String) -> (a -> b) -> [a] -> String
|
||||
def fTable(s):
|
||||
'''Heading -> x display function -> fx display function ->
|
||||
f -> xs -> tabular string.
|
||||
'''
|
||||
def go(xShow, fxShow, f, xs):
|
||||
ys = [xShow(x) for x in xs]
|
||||
w = max(map(len, ys))
|
||||
return s + '\n' + '\n'.join(map(
|
||||
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
|
||||
xs, ys
|
||||
))
|
||||
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
|
||||
xShow, fxShow, f, xs
|
||||
)
|
||||
|
||||
|
||||
# ----------------------- GENERIC ------------------------
|
||||
|
||||
# enumFromTo :: (Int, Int) -> [Int]
|
||||
def enumFromTo(m):
|
||||
'''Integer enumeration from m to n.'''
|
||||
return lambda n: range(m, 1 + n)
|
||||
|
||||
|
||||
# chunksOf :: Int -> [a] -> [[a]]
|
||||
def chunksOf(n):
|
||||
'''A series of lists of length n, subdividing the
|
||||
contents of xs. Where the length of xs is not evenly
|
||||
divible, the final list will be shorter than n.
|
||||
'''
|
||||
return lambda xs: reduce(
|
||||
lambda a, i: a + [xs[i:n + i]],
|
||||
range(0, len(xs), n), []
|
||||
) if 0 < n else []
|
||||
|
||||
|
||||
# intercalate :: [a] -> [[a]] -> [a]
|
||||
# intercalate :: String -> [String] -> String
|
||||
def intercalate(x):
|
||||
'''The concatenation of xs
|
||||
interspersed with copies of x.
|
||||
'''
|
||||
return lambda xs: x.join(xs) if isinstance(x, str) else list(
|
||||
chain.from_iterable(
|
||||
reduce(lambda a, v: a + [x, v], xs[1:], [xs[0]])
|
||||
)
|
||||
) if xs else []
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
def queens(n):
|
||||
def q(pl, r):
|
||||
def place(c):
|
||||
return r+c not in pl[1] and r-c not in pl[2]
|
||||
return ((pl[0]+[c], pl[1]|{r+c}, pl[2]|{r-c}, pl[3]-{c})
|
||||
for c in pl[3] if place(c))
|
||||
def pipeline(pl, i):
|
||||
for ipl in q(pl, i):
|
||||
if i+1 < n:
|
||||
yield from pipeline(ipl, i+1)
|
||||
else:
|
||||
yield ipl[0]
|
||||
def toletter(x):
|
||||
return 'abcdefghijklmnopqrstuvwxyz'[x]
|
||||
def fund_solut(fl):
|
||||
def inversed(xl):
|
||||
return (xl.index(i) for i in range(0, n))
|
||||
def variants(xl):
|
||||
rl = [xl]
|
||||
rl += [[*inversed(x)] for x in rl]
|
||||
rl += [[*reversed(x)] for x in rl]
|
||||
rl += [[n-1-i for i in x] for x in rl]
|
||||
return (''.join(toletter(i) for i in x) for x in rl)
|
||||
rs = set()
|
||||
for i in fl:
|
||||
ks = {*variants(i)}
|
||||
if rs.isdisjoint(ks):
|
||||
rs |= ks
|
||||
yield i
|
||||
for i in fund_solut(
|
||||
pipeline(([], set(), set(), {*range(0, n)}), 0)):
|
||||
rl = sorted(toletter(v)+str(k+1) for k, v in enumerate(i))
|
||||
print(rl)
|
||||
queens(8)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue