mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 09:40:21 +00:00
118 lines
3.5 KiB
Plaintext
118 lines
3.5 KiB
Plaintext
/*
|
|
* This file is part of the X10 project (http://x10-lang.org).
|
|
*
|
|
* This file is licensed to You under the Eclipse Public License (EPL);
|
|
* You may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* http://www.opensource.org/licenses/eclipse-1.0.php
|
|
*
|
|
* (C) Copyright IBM Corporation 2006-2014.
|
|
* (C) Copyright Australian National University 2011.
|
|
*/
|
|
|
|
/**
|
|
* Compute the number of solutions to the N queens problem.
|
|
*/
|
|
public class NQueensPar {
|
|
public static val EXPECTED_SOLUTIONS =
|
|
[0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184, 14772512];
|
|
|
|
val N:Int;
|
|
val P:Int;
|
|
var nSolutions:Int = 0n;
|
|
val R:IntRange;
|
|
|
|
def this(N:Int, P:Int) {
|
|
this.N=N;
|
|
this.P=P;
|
|
this.R = 0n..(N-1n);
|
|
}
|
|
|
|
def start() {
|
|
new Board().parSearch();
|
|
}
|
|
|
|
class Board {
|
|
val q: Rail[Int];
|
|
/** The number of low-rank positions that are fixed in this board for the purposes of search. */
|
|
var fixed:Int;
|
|
def this() {
|
|
q = new Rail[Int](N);
|
|
fixed = 0n;
|
|
}
|
|
|
|
def this(b:Board) {
|
|
this.q = new Rail[Int](b.q);
|
|
this.fixed = b.fixed;
|
|
}
|
|
|
|
/**
|
|
* @return true if it is safe to put a queen in file <code>j</code>
|
|
* on the next rank after the last fixed position.
|
|
*/
|
|
def safe(j:Int) {
|
|
for (k in 0n..(fixed-1n)) {
|
|
if (j == q(k) || Math.abs(fixed-k) == Math.abs(j-q(k)))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** Search all positions for the current board. */
|
|
def search() {
|
|
for (k in R) searchOne(k);
|
|
}
|
|
|
|
/**
|
|
* Modify the current board by adding a new queen
|
|
* in file <code>k</code> on rank <code>fixed</code>,
|
|
* and search for all safe positions with this prefix.
|
|
*/
|
|
def searchOne(k:Int) {
|
|
if (safe(k)) {
|
|
if (fixed==(N-1n)) {
|
|
// all ranks safely filled
|
|
atomic NQueensPar.this.nSolutions++;
|
|
} else {
|
|
q(fixed++) = k;
|
|
search();
|
|
fixed--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search this board, dividing the work between threads
|
|
* using a block distribution of the current free rank.
|
|
*/
|
|
def parSearch() {
|
|
for (work in R.split(P)) async {
|
|
val board = new Board(this);
|
|
for (w in work) {
|
|
board.searchOne(w);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static def main(args:Rail[String]) {
|
|
val n = args.size > 0 ? Int.parse(args(0)) : 8n;
|
|
Console.OUT.println("N=" + n);
|
|
//warmup
|
|
//finish new NQueensPar(12, 1).start();
|
|
val ps = [1n,2n,4n];
|
|
for (numTasks in ps) {
|
|
Console.OUT.println("starting " + numTasks + " tasks");
|
|
val nq = new NQueensPar(n,numTasks);
|
|
var start:Long = -System.nanoTime();
|
|
finish nq.start();
|
|
val result = (nq.nSolutions as Long)==EXPECTED_SOLUTIONS(nq.N);
|
|
start += System.nanoTime();
|
|
start /= 1000000;
|
|
Console.OUT.println("NQueensPar " + nq.N + "(P=" + numTasks +
|
|
") has " + nq.nSolutions + " solutions" +
|
|
(result? " (ok)." : " (wrong).") + "time=" + start + "ms");
|
|
}
|
|
}
|
|
}
|