-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathN_Queens.rb
81 lines (72 loc) · 1.79 KB
/
N_Queens.rb
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
70
71
72
73
74
75
76
77
78
79
80
81
require_relative '../../Hypertension'
module N_Queens
include Hypertension
extend self
#-----------------------------------------------
# Domain
#-----------------------------------------------
@domain = {
# Operators
:put_piece => true,
# Methods
:solve => [:try_next]
}
def solve(size, debug, verbose)
state = {
:queen => [],
:free_collumn => (0...size).to_a
}
tasks = [
[:solve, size]
]
if verbose
problem(state, tasks, debug)
else
@debug = debug
@state = state
planning(tasks)
end
end
#-----------------------------------------------
# Operators
#-----------------------------------------------
def put_piece(x, y)
# Add effects
q = @state[:queen].dup << [x, y]
# Del effects
(f = @state[:free_collumn].dup).delete(x)
@state = {:queen => q, :free_collumn => f}
end
#-----------------------------------------------
# Methods
#-----------------------------------------------
def try_next(y)
# Base of recursion
return yield [] if y.zero?
y -= 1 # Closed row boost
queen = @state[:queen]
# Generate unifications without generate
@state[:free_collumn].each {|x|
# No need to test x == i, free collumn test, or y == j, every piece have a row
next if queen.any? {|i,j| (i - x).abs == j - y}
yield [
[:put_piece, x, y],
[:solve, y]
]
}
end
end
#-----------------------------------------------
# Main
#-----------------------------------------------
if $0 == __FILE__
# Size input
size = ARGV[0] ? ARGV[0].to_i : 8
N_Queens.solve(size, ARGV[1] == 'debug', true)
# Draw from row size - 1 to 0
N_Queens.state[:queen].reverse_each {|i,|
row = '[ ]' * size
row[i * 3 + 1] = 'Q'
puts row
}
end