forked from code-clash/sudoku-verifier
Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Lothar Buchholz | 8bd7d827a8 | 5 years ago |
@ -1,71 +1,59 @@
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
import java.util.stream.*;
|
||||||
|
|
||||||
/**
|
|
||||||
* Template code to help you parse the standard input
|
|
||||||
* according to the problem statement.
|
|
||||||
**/
|
|
||||||
class Solution {
|
class Solution {
|
||||||
|
|
||||||
|
private static final int SIZE = 9;
|
||||||
|
private static final int BLOCK_SIZE = 3;
|
||||||
|
|
||||||
public static void main( String[] args ) {
|
public static void main( String[] args ) {
|
||||||
Scanner in = new Scanner( System.in );
|
var digits = new Scanner( System.in ).tokens()
|
||||||
|
.map( Integer::valueOf )
|
||||||
|
.collect( Collectors.toList() );
|
||||||
|
|
||||||
int[][] grid = new int[9][9];
|
System.out.println( checkSudoku( digits ));
|
||||||
for ( int index = 0; in.hasNext(); index++ ) {
|
|
||||||
int row = index / 9;
|
|
||||||
int col = index % 9;
|
|
||||||
grid[row][col] = in.nextShort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println( checkHorizontally( grid )
|
/**
|
||||||
&& checkVertically( grid )
|
* The basic idea is to split the digits into groups that can be verified by the same logic over and over again.
|
||||||
&& checkAllBlocks( grid )
|
* The code will create 27 groups - 9 lines, 9 rows and 9 blocks - and checks for all digits in each group.
|
||||||
);
|
*/
|
||||||
|
private static boolean checkSudoku( List<Integer> digits ) {
|
||||||
|
return Stream.of(
|
||||||
|
filterGroup( digits, Solution::byLine ),
|
||||||
|
filterGroup( digits, Solution::byRow ),
|
||||||
|
filterGroup( digits, Solution::byBlock )
|
||||||
|
).flatMap( Collection::stream )
|
||||||
|
.allMatch( Solution::checkAllDigits );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkHorizontally( int[][] grid ) {
|
/**
|
||||||
//noinspection ForLoopReplaceableByForEach
|
* Splitting is done with a grouping function that calculates the group number for a grid index.
|
||||||
for ( int r = 0; r < grid.length; r++ ) {
|
*/
|
||||||
BitSet bs = new BitSet( 9 );
|
private static Collection<List<Integer>> filterGroup( List<Integer> digits, IntFunction<Integer> grpFunc ) {
|
||||||
for ( int c = 0; c < grid[r].length; c++ ) {
|
var group = IntStream.range( 0, digits.size() ).boxed()
|
||||||
bs.set( grid[r][c] );
|
.collect( Collectors.groupingBy( grpFunc::apply, Collectors.mapping( digits::get, Collectors.toList() )));
|
||||||
}
|
return group.values();
|
||||||
if ( bs.cardinality() != 9 ) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkVertically( int[][] grid ) {
|
/**
|
||||||
for ( int c = 0; c < 9; c++ ) {
|
* Checks if every digit from 1 to 9 is present in each group.
|
||||||
BitSet bs = new BitSet( 9 );
|
*/
|
||||||
//noinspection ForLoopReplaceableByForEach
|
private static boolean checkAllDigits( List<Integer> group ) {
|
||||||
for ( int r = 0; r < grid.length; r++ ) {
|
return group.stream().distinct().count() == SIZE;
|
||||||
bs.set( grid[r][c] );
|
|
||||||
}
|
|
||||||
if ( bs.cardinality() != 9 ) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkAllBlocks( int[][] grid ) {
|
private static int byLine( int index ) {
|
||||||
return checkBlock( grid, 0, 0 )
|
return index / SIZE;
|
||||||
&& checkBlock( grid, 0, 3 )
|
|
||||||
&& checkBlock( grid, 0, 6 )
|
|
||||||
&& checkBlock( grid, 3, 0 )
|
|
||||||
&& checkBlock( grid, 3, 3 )
|
|
||||||
&& checkBlock( grid, 3, 6 )
|
|
||||||
&& checkBlock( grid, 6, 0 )
|
|
||||||
&& checkBlock( grid, 6, 3 )
|
|
||||||
&& checkBlock( grid, 6, 6 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkBlock( int[][] block, int indexTop, int indexLeft ) {
|
private static int byRow( int index ) {
|
||||||
BitSet bs = new BitSet( 9 );
|
return index % SIZE;
|
||||||
for ( int r = indexTop; r < indexTop + 3; r++ ) {
|
|
||||||
for ( int c = indexLeft; c < indexLeft + 3; c++ ) {
|
|
||||||
bs.set( block[r][c] );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ( bs.cardinality() == 9 );
|
|
||||||
|
private static int byBlock( int index ) {
|
||||||
|
return byRow( index ) / BLOCK_SIZE + ( index / ( SIZE * BLOCK_SIZE )) * BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue