Skip to content

Commit 2dac4ea

Browse files
committed
Eight Queens Problem
1 parent 41737dc commit 2dac4ea

File tree

3 files changed

+97
-8
lines changed

3 files changed

+97
-8
lines changed

chapter3/csp.js

+28-8
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ class CSP {
1919
this.variables = variables; // variables to be constrained
2020
this.domains = domains; // domain of each variable
2121
this.constraints = {};
22-
for (variable of this.variables) {
22+
for (let variable of this.variables) {
2323
this.constraints[variable] = [];
24-
if (Object.keys(this.domains).indexOf(variable) == -1) {
24+
if (!member(Object.keys(this.domains), variable)) {
2525
throw "Every variable should have a domain assigned to it.";
2626
}
2727
}
2828
}
2929

3030
addConstraint(constraint) {
31-
for (variable of constraint.variables) {
32-
if (this.variables.indexOf(variable) == -1) {
31+
for (let variable of constraint.variables) {
32+
if (!member(this.variables, variable)) {
3333
throw "Variable in constraint not in CSP";
3434
} else {
3535
this.constraints[variable].push(constraint);
@@ -49,7 +49,7 @@ class CSP {
4949
}
5050

5151
backtrackingSearch(assignment) {
52-
if (assignment == null) {
52+
if (!assignment) {
5353
assignment = {};
5454
}
5555
// assignment is complete if every variable is assigned (our base case)
@@ -58,8 +58,7 @@ class CSP {
5858
}
5959

6060
// get all variables in the CSP but not in the assignment
61-
let unassigned = this.variables.filter((v) => Object.keys(assignment).indexOf(v) == -1);
62-
61+
let unassigned = this.variables.filter((v) => !member(Object.keys(assignment), v));
6362
// get every possible domain value of the first unassigned variable
6463
let first = unassigned[0];
6564
for (let value of this.domains[first]) {
@@ -79,9 +78,30 @@ class CSP {
7978
}
8079
}
8180

81+
// array membership helper function
82+
function member(array, element) {
83+
if (array.length == 0) {
84+
return false;
85+
}
86+
if (typeof array[0] == typeof element) {
87+
return array.indexOf(element) > -1;
88+
}
89+
if (typeof array[0] == 'string' && typeof element == 'number') {
90+
return array.indexOf(element.toString()) > -1;
91+
}
92+
for (let item of array) {
93+
if (element == item) {
94+
return true;
95+
}
96+
}
97+
return false;
98+
}
99+
100+
82101
let _exports = {
83102
Constraint: Constraint,
84-
CSP: CSP
103+
CSP: CSP,
104+
member: member
85105
};
86106

87107
if (typeof window === 'undefined') {

chapter3/queens.html

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Eight Queens Problem</title>
5+
</head>
6+
<body>
7+
<pre>
8+
<script type="text/javascript" src="../util_web.js"></script>
9+
<script type="text/javascript" src="csp.js"></script>
10+
<script type="text/javascript" src="queens.js"></script>
11+
</pre>
12+
<p><a href="../index.html">Back to list</a></p>
13+
</body>
14+
</html>

chapter3/queens.js

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
if (typeof window === 'undefined') {
2+
csp = require(__dirname + '/csp.js');
3+
util = require(__dirname + '/../util.js');
4+
}
5+
6+
class QueensConstraint extends csp.Constraint {
7+
constructor(columns) {
8+
super(columns);
9+
this.columns = columns;
10+
}
11+
12+
satisfied(assignment) {
13+
// q1c = queen1 column, q1r = queen 1 row
14+
let q1c, q1r;
15+
for ([q1c, q1r] of this.tuples(assignment)) {
16+
// q2c = queen 2 column
17+
for (let q2c = parseInt(q1c) + 1; q2c <= this.columns.length; q2c++) {
18+
if (csp.member(Object.keys(assignment), q2c)) {
19+
let q2r = assignment[q2c]; // q2r = queen 2 row
20+
if (q1r == q2r) { // same row?
21+
return false;
22+
}
23+
if (Math.abs(q1r - q2r) == Math.abs(q1c - q2c)) { // same diagonal?
24+
return false;
25+
}
26+
}
27+
}
28+
}
29+
return true; // no conflict
30+
}
31+
32+
// Helper function to turn an object {key1: value1, key2: value2...}
33+
// into an array of tuples: [[key1, value1], [key2, value2]...]
34+
tuples(object) {
35+
let result = [];
36+
for (let key of Object.keys(object)) {
37+
result.push([key, object[key]]);
38+
}
39+
return result;
40+
}
41+
}
42+
43+
let columns = [1, 2, 3, 4, 5, 6, 7, 8];
44+
let rows = {};
45+
for (let column of columns) {
46+
rows[column] = [1, 2, 3, 4, 5, 6, 7, 8];
47+
}
48+
let qCsp = new csp.CSP(columns, rows);
49+
qCsp.addConstraint(new QueensConstraint(columns));
50+
let solution = qCsp.backtrackingSearch();
51+
if (solution == null) {
52+
util.out("No solution found!");
53+
} else {
54+
util.out(solution);
55+
}

0 commit comments

Comments
 (0)