rxjava solution - check rows, columns, and squares
This commit is contained in:
		@@ -6,7 +6,7 @@ import java.util.stream.Stream;
 | 
				
			|||||||
import java.util.stream.StreamSupport;
 | 
					import java.util.stream.StreamSupport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * stream.Solution involving a Sukdoku Board, a SudokuVerifier, plus some RxJava processing.
 | 
					 * stream.Solution involving a SudokuVerifier, and some RxJava processing.
 | 
				
			||||||
**/
 | 
					**/
 | 
				
			||||||
class Solution {
 | 
					class Solution {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,46 +1,79 @@
 | 
				
			|||||||
package rxjava;
 | 
					package rxjava;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io.reactivex.rxjava3.annotations.NonNull;
 | 
					 | 
				
			||||||
import io.reactivex.rxjava3.core.Observable;
 | 
					import io.reactivex.rxjava3.core.Observable;
 | 
				
			||||||
import io.reactivex.rxjava3.core.Single;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.concurrent.atomic.AtomicInteger;
 | 
					import java.util.concurrent.atomic.AtomicInteger;
 | 
				
			||||||
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					import java.util.stream.IntStream;
 | 
				
			||||||
import java.util.stream.Stream;
 | 
					import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SudokuVerifier {
 | 
					public class SudokuVerifier {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@NonNull Observable<String> digitObservable;
 | 
					
 | 
				
			||||||
 | 
						List<DigitField> digitFields;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public SudokuVerifier(Stream<String> digitStream) {
 | 
						public SudokuVerifier(Stream<String> digitStream) {
 | 
				
			||||||
		// Observable on the digit stream
 | 
							// Observable on the digit stream
 | 
				
			||||||
		digitObservable = Observable.fromStream(digitStream);
 | 
							AtomicInteger row = new AtomicInteger(1);
 | 
				
			||||||
 | 
							AtomicInteger column = new AtomicInteger(0);
 | 
				
			||||||
 | 
							digitFields = Observable.fromStream(digitStream)
 | 
				
			||||||
 | 
								.map(digit -> digitField(row, column, digit))
 | 
				
			||||||
 | 
								.collect(Collectors.toList())
 | 
				
			||||||
 | 
								.blockingGet();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public boolean isSolved() {
 | 
						public boolean isSolved() {
 | 
				
			||||||
		AtomicInteger row = new AtomicInteger(1);
 | 
							// Filter for 9 rows, 9 columns, 9 squares
 | 
				
			||||||
		AtomicInteger column = new AtomicInteger(0);
 | 
							return digitsInBlockFilters()
 | 
				
			||||||
		@NonNull Observable<DigitField> digitFieldObservable = digitObservable
 | 
								.map(blockFilter -> blockFilter.distinct().count().blockingGet() == 9)
 | 
				
			||||||
			.map(digit -> digitField(row, column, digit));
 | 
								.all(solved -> solved).blockingGet();
 | 
				
			||||||
		@NonNull Observable<DigitField> filter = digitFieldObservable
 | 
					 | 
				
			||||||
			.filter(digitField -> digitField.row == 1);
 | 
					 | 
				
			||||||
		return isSolved(filter).blockingGet();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@NonNull Single<Boolean> isSolved(@NonNull Observable<DigitField> filter) {
 | 
					 | 
				
			||||||
		return filter
 | 
					 | 
				
			||||||
			.map(digitField -> digitField.digit)
 | 
					 | 
				
			||||||
			.distinct().count()
 | 
					 | 
				
			||||||
			.map(count -> count == 9);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DigitField digitField(AtomicInteger row, AtomicInteger column, String digit) {
 | 
						DigitField digitField(AtomicInteger row, AtomicInteger column, String digit) {
 | 
				
			||||||
		if (column.getAndIncrement() > 9) {
 | 
							if (column.incrementAndGet() > 9) {
 | 
				
			||||||
			row.getAndIncrement();
 | 
								row.getAndIncrement();
 | 
				
			||||||
			column.set(1);
 | 
								column.set(1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return new DigitField(row.get(), column.get(), digit);
 | 
							return new DigitField(row.get(), column.get(), digit);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Observable<Observable<String>> digitsInBlockFilters() {
 | 
				
			||||||
 | 
							Stream<Observable<String>> stream = Stream.of(
 | 
				
			||||||
 | 
								IntStream.rangeClosed(1, 9).boxed().map(row -> digitsInRowFilter(row)),
 | 
				
			||||||
 | 
								IntStream.rangeClosed(1, 9).boxed().map(column -> digitsInColumnFilter(column)),
 | 
				
			||||||
 | 
								digitsInSquareFilters()
 | 
				
			||||||
 | 
							).flatMap(s -> s);
 | 
				
			||||||
 | 
							return Observable.fromStream(stream);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Observable<String> digitsInRowFilter(Integer row) {
 | 
				
			||||||
 | 
							return Observable.fromStream(
 | 
				
			||||||
 | 
								digitFields.stream()
 | 
				
			||||||
 | 
									.filter(digitField -> digitField.row == row)
 | 
				
			||||||
 | 
									.map(digitField -> digitField.digit));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Observable<String> digitsInColumnFilter(Integer column) {
 | 
				
			||||||
 | 
							return Observable.fromStream(
 | 
				
			||||||
 | 
								digitFields.stream()
 | 
				
			||||||
 | 
									.filter(digitField -> digitField.column == column)
 | 
				
			||||||
 | 
									.map(digitField -> digitField.digit));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Stream<Observable<String>> digitsInSquareFilters() {
 | 
				
			||||||
 | 
							return IntStream.rangeClosed(1, 3).boxed().flatMap(
 | 
				
			||||||
 | 
								squareRow -> IntStream.rangeClosed(1, 3).boxed().map(
 | 
				
			||||||
 | 
									squareColumn -> digitsInSquareFilter(squareRow, squareColumn)));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Observable<String> digitsInSquareFilter(Integer squareRow, Integer squareColumn) {
 | 
				
			||||||
 | 
							return Observable.fromStream(
 | 
				
			||||||
 | 
								digitFields.stream()
 | 
				
			||||||
 | 
									.filter(digitField -> digitField.isInSquare(squareRow, squareColumn))
 | 
				
			||||||
 | 
									.map(digitField -> digitField.digit));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static class DigitField {
 | 
						static class DigitField {
 | 
				
			||||||
		int row;
 | 
							int row;
 | 
				
			||||||
		int column;
 | 
							int column;
 | 
				
			||||||
@@ -51,5 +84,12 @@ public class SudokuVerifier {
 | 
				
			|||||||
			this.column = column;
 | 
								this.column = column;
 | 
				
			||||||
			this.digit = digit;
 | 
								this.digit = digit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public boolean isInSquare(Integer squareRow, Integer squareColumn) {
 | 
				
			||||||
 | 
								return row >= squareRow * 3 - 2
 | 
				
			||||||
 | 
									&& row <= squareRow * 3
 | 
				
			||||||
 | 
									&& column >= squareColumn * 3 - 2
 | 
				
			||||||
 | 
									&& column <= squareColumn * 3;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,6 @@ class SolutionTest {
 | 
				
			|||||||
	static void redirectStreams( final InputStream input, final PrintStream output, final PrintStream error ) {
 | 
						static void redirectStreams( final InputStream input, final PrintStream output, final PrintStream error ) {
 | 
				
			||||||
		System.setIn( input );
 | 
							System.setIn( input );
 | 
				
			||||||
		System.setOut( output );
 | 
							System.setOut( output );
 | 
				
			||||||
		System.setErr( error );
 | 
							//System.setErr( error );
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user