Skip to content

Instantly share code, notes, and snippets.

@icsaba
Last active June 30, 2019 09:25
Show Gist options
  • Save icsaba/5ea8984b53994f5d21c7698860234606 to your computer and use it in GitHub Desktop.
Save icsaba/5ea8984b53994f5d21c7698860234606 to your computer and use it in GitHub Desktop.
EAK 2 exam, parallel NQueens
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