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; | ||||
|  | ||||
| /** | ||||
|  * stream.Solution involving a Sukdoku Board, a SudokuVerifier, plus some RxJava processing. | ||||
|  * stream.Solution involving a SudokuVerifier, and some RxJava processing. | ||||
| **/ | ||||
| class Solution { | ||||
| 	 | ||||
|   | ||||
| @@ -1,46 +1,79 @@ | ||||
| package rxjava; | ||||
|  | ||||
| import io.reactivex.rxjava3.annotations.NonNull; | ||||
| 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.stream.Collectors; | ||||
| import java.util.stream.IntStream; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| public class SudokuVerifier { | ||||
|  | ||||
| 	@NonNull Observable<String> digitObservable; | ||||
|  | ||||
| 	List<DigitField> digitFields; | ||||
|  | ||||
| 	public SudokuVerifier(Stream<String> digitStream) { | ||||
| 		// 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() { | ||||
| 		AtomicInteger row = new AtomicInteger(1); | ||||
| 		AtomicInteger column = new AtomicInteger(0); | ||||
| 		@NonNull Observable<DigitField> digitFieldObservable = digitObservable | ||||
| 			.map(digit -> digitField(row, column, digit)); | ||||
| 		@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); | ||||
| 		// Filter for 9 rows, 9 columns, 9 squares | ||||
| 		return digitsInBlockFilters() | ||||
| 			.map(blockFilter -> blockFilter.distinct().count().blockingGet() == 9) | ||||
| 			.all(solved -> solved).blockingGet(); | ||||
| 	} | ||||
|  | ||||
| 	DigitField digitField(AtomicInteger row, AtomicInteger column, String digit) { | ||||
| 		if (column.getAndIncrement() > 9) { | ||||
| 		if (column.incrementAndGet() > 9) { | ||||
| 			row.getAndIncrement(); | ||||
| 			column.set(1); | ||||
| 		} | ||||
| 		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 { | ||||
| 		int row; | ||||
| 		int column; | ||||
| @@ -51,5 +84,12 @@ public class SudokuVerifier { | ||||
| 			this.column = column; | ||||
| 			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 ) { | ||||
| 		System.setIn( input ); | ||||
| 		System.setOut( output ); | ||||
| 		System.setErr( error ); | ||||
| 		//System.setErr( error ); | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 paul
					paul