mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			124 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			3.8 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.
 | 
						|
 */
 | 
						|
 | 
						|
import x10.array.DistArray_Unique;
 | 
						|
 | 
						|
/**
 | 
						|
 * A distributed version of NQueens. Runs over NUM_PLACES.
 | 
						|
 * Identical to NQueensPar, except that work is distributed 
 | 
						|
 * over multiple places rather than shared between threads.
 | 
						|
 */
 | 
						|
public class NQueensDist {
 | 
						|
    public static val EXPECTED_SOLUTIONS =
 | 
						|
        [0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184, 14772512];
 | 
						|
 | 
						|
    val N:Long;
 | 
						|
    val P:Long;
 | 
						|
    val results:DistArray_Unique[Long];
 | 
						|
    val R:LongRange;
 | 
						|
 | 
						|
    def this(N:Long, P:Long) { 
 | 
						|
        this.N=N;
 | 
						|
        this.P=P;
 | 
						|
        this.results = new DistArray_Unique[Long]();
 | 
						|
        this.R = 0..(N-1);
 | 
						|
    }
 | 
						|
    def start() {
 | 
						|
        new Board().distSearch();
 | 
						|
    }
 | 
						|
    def run():Long {
 | 
						|
       finish start();
 | 
						|
       val result = results.reduce(((x:Long,y:Long) => x+y),0);
 | 
						|
       return result;
 | 
						|
    }
 | 
						|
 | 
						|
    class Board {
 | 
						|
        val q: Rail[Long];
 | 
						|
        /** The number of low-rank positions that are fixed in this board for the purposes of search. */
 | 
						|
        var fixed:Long;
 | 
						|
        def this() {
 | 
						|
            q = new Rail[Long](N);
 | 
						|
            fixed = 0;
 | 
						|
        }
 | 
						|
 | 
						|
        /** 
 | 
						|
         * @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:Long) {
 | 
						|
            for (k in 0..(fixed-1)) {
 | 
						|
                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:Long) {
 | 
						|
            if (safe(k)) {
 | 
						|
                if (fixed==(N-1)) {
 | 
						|
                    // all ranks safely filled
 | 
						|
                    atomic NQueensDist.this.results(here.id)++;
 | 
						|
                } else {
 | 
						|
                    q(fixed++) = k;
 | 
						|
                    search();
 | 
						|
                    fixed--;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Search this board, dividing the work between all places
 | 
						|
         * using a block distribution of the current free rank.
 | 
						|
         */
 | 
						|
        def distSearch()  {
 | 
						|
            val work = R.split(Place.numPlaces());
 | 
						|
            finish for (p in Place.places()) {
 | 
						|
                val myPiece = work(p.id);
 | 
						|
                at (p) async {
 | 
						|
                    // implicit copy of 'this' made across the at divide
 | 
						|
                    for (k in myPiece) {
 | 
						|
                        searchOne(k);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public static def main(args:Rail[String])  {
 | 
						|
        val n = args.size > 0 ? Long.parse(args(0)) : 8;
 | 
						|
        Console.OUT.println("N=" + n);
 | 
						|
        //warmup
 | 
						|
        //finish new NQueensPar(12, 1).start();
 | 
						|
        val P = Place.numPlaces();
 | 
						|
        val nq = new NQueensDist(n,P);
 | 
						|
        var start:Long = -System.nanoTime();
 | 
						|
        val answer = nq.run();
 | 
						|
        val result = answer==EXPECTED_SOLUTIONS(n);
 | 
						|
        start += System.nanoTime();
 | 
						|
        start /= 1000000;
 | 
						|
        Console.OUT.println("NQueensDist " + nq.N + "(P=" + P +
 | 
						|
                            ") has " + answer + " solutions" +
 | 
						|
                            (result? " (ok)." : " (wrong).") + 
 | 
						|
                            "time=" + start + "ms");
 | 
						|
    }
 | 
						|
}
 |