Last active
June 30, 2019 09:25
-
-
Save icsaba/5ea8984b53994f5d21c7698860234606 to your computer and use it in GitHub Desktop.
EAK 2 exam, parallel NQueens
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package obsxvv; | |
import java.util.*; | |
import java.util.concurrent.*; | |
/** An immutable board of non-attacking queens. */ | |
class Board { | |
/** An immutable linked list of int values. */ | |
protected static class Node { | |
protected final int value; | |
protected final Node next; | |
protected Node( int value, Node next ){ | |
this.value = value; | |
this.next = next; | |
} | |
} | |
protected final Node queens; // list of non-attacking queens | |
protected final int nrQueens; // length of queens | |
/** An empty board. */ | |
protected Board(){ | |
queens = null; | |
nrQueens = 0; | |
} | |
/** Adding a new column to a board. */ | |
protected Board( int queen, Board board ){ | |
queens = new Node(queen,board.queens); | |
nrQueens = board.nrQueens + 1; | |
} | |
/** Whether a new queen attacks existing queens on this board. */ | |
protected boolean attacks( int queen ){ | |
int distance = 0; | |
Node cursor = queens; | |
while( cursor != null ){ | |
++distance; | |
if( queen == cursor.value || Math.abs(queen - cursor.value) == distance ){ | |
return true; | |
} | |
cursor = cursor.next; | |
} | |
return false; | |
} | |
/** Compute all possible solutions starting from the current board. */ | |
protected List<Board> continuations( int size, ExecutorService exec, CountDownLatch latch){ | |
List<Board> boards = Collections.synchronizedList(new LinkedList<>()); | |
for( int row = 1; row <= size; ++row ){ | |
int finalRow = row; | |
exec.execute(() -> { | |
(new Board(finalRow,this)).rec(size, boards); | |
latch.countDown(); | |
}); | |
} | |
try { | |
latch.await(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
return boards; | |
} | |
public void rec(int size, List<Board> boards) { | |
if( nrQueens == size ){ // no more queens have to be added | |
boards.addAll(Arrays.asList(this)); // return a single solution: this | |
} else { | |
// add one more column by trying all non-attacking rows in that column, | |
// and recursively find all continuations from all the resulting boards | |
for( int row = 1; row <= size; ++row ){ | |
if( !attacks(row) ){ | |
(new Board(row,this)).rec(size, boards); | |
} | |
} | |
} | |
} | |
/** Place <code>size</code> queens on a size x size board in all possible ways. */ | |
public static List<Board> solve( int size ){ | |
ExecutorService executorService = Executors.newFixedThreadPool(size); | |
CountDownLatch latch = new CountDownLatch(size); | |
try{ | |
return (new Board()).continuations(size, executorService, latch); | |
} finally { | |
executorService.shutdown(); | |
try { | |
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
} | |
class NQueens { | |
public static void main( String[] args ){ | |
long startTime = System.currentTimeMillis(); | |
System.out.println( Board.solve( Integer.parseInt(args[0]) ).size() ); | |
long estimatedTime = System.currentTimeMillis() - startTime; | |
System.out.println("Total time: " + estimatedTime); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment