About exercise 2.2
Place N queens on N*N board, 1 queen per line, so that all queens are safe.
Use permutation to improve the provided implementation from book.
The exercise 2.2 asked to do it via permutation, and I did that with recursion, using shallow copy before passing arrays to next level of recursion.
Things I think might need review:
- I'm very new to lua; is there some lua specific improvements can be done to my code (I googled while programming this exercise).
- How to improve the algorithm? e.g., avoid the shallow copy?
- Parallel programming to speed up?
Code
eight_queen_perm.lua:
--local inspect = require('inspect')
N = 8 -- board size
z = 0 -- follow performance, by counting the time isplaceok() is called,
-- check whether position (n,c) is free from attacks
function isplaceok (a, n, c)
z = z + 1
for i = 1, n - 1 do
-- for each queen already placed
if (a[i] == c) or -- same column?
(a[i] - i == c - n) or -- same diagonal?
(a[i] + i == c + n) then
-- same diagonal?
return false -- place can be attacked
end
end
return true -- no attacks; place is OK
end
-- print a board
function printsolution (a)
for i = 1, N do
-- for each row
for j = 1, N do
-- and for each column
-- write "X" or "-" plus a space
io.write(a[i] == j and "Q" or "-", " ")
end
io.write("\n")
end
io.write("\n")
end
-- add queen to board, via checking permutation,
function queenPermRec(seq, prefix, arr)
if #arr == 0 then
-- prefix is the result,
seq = seq + 1
--io.write(string.format("[%d] %s\n", seq, inspect(prefix)))
io.write(string.format("(%d)\n", seq))
printsolution(prefix)
return seq
end
for i = 1, #arr do
if not isplaceok(prefix, #prefix + 1, arr[i]) then
-- stop early if not valid,
goto skip_to_next
end
prefix2 = table.shallow_copy(prefix)
table.insert(prefix2, arr[i])
arr2 = table.shallow_copy(arr)
table.remove(arr2, i)
seq = queenPermRec(seq, prefix2, arr2)
:: skip_to_next ::
end
return seq
end
function table.shallow_copy(t)
local t2 = {}
for k, v in pairs(t) do
t2[k] = v
end
return t2
end
function table.join(t1, t2)
for i = 1, #t2 do
t1[#t1 + 1] = t2[i]
end
return t1
end
-- generate increase array in [1, n],
function genIncArr(n)
arr = {}
for i = 1, n do
arr[i] = i
end
return arr
end
queenPermRec(0, {}, genIncArr(N))
io.write(string.format("isplaceok() called %d times\n", z))