nonogram
"""
A nonogram is a logic puzzle, similar to a crossword, in which the player is given a blank grid and has to color it according to some instructions. Specifically, each cell can be either black or white, which we will represent as 0 for black and 1 for white.
+------------+
| 1 1 1 1 |
| 0 1 1 1 |
| 0 1 0 0 |
| 1 1 0 1 |
| 0 0 1 1 |
+------------+
For each row and column, the instructions give the lengths of contiguous runs of black (0) cells. For example, the instructions for one row of [ 2, 1 ] indicate that there must be a run of two black cells, followed later by another run of one black cell, and the rest of the row filled with white cells.
These are valid solutions: [ 1, 0, 0, 1, 0 ] and [ 0, 0, 1, 1, 0 ] and also [ 0, 0, 1, 0, 1 ]
This is not valid: [ 1, 0, 1, 0, 0 ] since the runs are not in the correct order.
This is not valid: [ 1, 0, 0, 0, 1 ] since the two runs of 0s are not separated by 1s.
Your job is to write a function to validate a possible solution against a set of instructions. Given a 2D matrix representing a player's solution; and instructions for each row along with additional instructions for each column; return True or False according to whether both sets of instructions match.
Example instructions #1
matrix1 = [[1,1,1,1],
[0,1,1,1],
[0,1,0,0],
[1,1,0,1],
[0,0,1,1]]
rows1_1 = [], [1], [1,2], [1], [2]
columns1_1 = [2,1], [1], [2], [1]
validateNonogram(matrix1, rows1_1, columns1_1) => True
Example solution matrix:
matrix1 ->
row
+------------+ instructions
| 1 1 1 1 | <-- []
| 0 1 1 1 | <-- [1]
| 0 1 0 0 | <-- [1,2]
| 1 1 0 1 | <-- [1]
| 0 0 1 1 | <-- [2]
+------------+
^ ^ ^ ^
| | | |
column [2,1] | [2] |
instructions [1] [1]
Example instructions #2
(same matrix as above)
rows1_2 = [], [], [1], [1], [1,1]
columns1_2 = [2], [1], [2], [1]
validateNonogram(matrix1, rows1_2, columns1_2) => False
The second and third rows and the first column do not match their respective instructions.
Example instructions #3
matrix2 = [
[ 1, 1 ],
[ 0, 0 ],
[ 0, 0 ],
[ 1, 0 ]
]
rows2_1 = [], [2], [2], [1]
columns2_1 = [1, 1], [3]
validateNonogram(matrix2, rows2_1, columns2_1) => False
The black cells in the first column are not separated by white cells.
n: number of rows in the matrix
m: number of columns in the matrix
"""
matrix1 = [
[1,1,1,1], # []
[0,1,1,1], # [1] -> a single run of _1_ zero (i.e.: "0")
[0,1,0,0], # [1, 2] -> first a run of _1_ zero, then a run of _2_ zeroes
[1,1,0,1], # [1]
[0,0,1,1], # [2]
]
# True
rows1_1 = [[],[1],[1,2],[1],[2]]
columns1_1 = [[2,1],[1],[2],[1]]
# False
rows1_2 = [[],[],[1],[1],[1,1]]
columns1_2 = [[2],[1],[2],[1]]
matrix2 = [
[1,1],
[0,0],
[0,0],
[1,0]
]
# False
rows2_1 = [[],[2],[2],[1]]
columns2_1 = [[1,1],[3]]
Encoding then compare with rows, cols
public class ValidNonogram {
public boolean isValidNonogram(int[][] matrix, int[][] rows, int[][] cols)
{
for(int i = 0; i< matrix.length; i++)
{
List<Integer> currentRowEncoding = rowEncoding(matrix, i);
int[] convertedRow = currentRowEncoding.stream().mapToInt(c -> c).toArray();
if(!Arrays.equals(convertedRow, rows[i]))
{
return false;
}
}
for(int j = 0; j< matrix[0].length; j++)
{
List<Integer> currentColEncoding = colEncoding(matrix, j);
int[] convertedCol = currentColEncoding.stream().mapToInt(c -> c).toArray();
if(!Arrays.equals(convertedCol, cols[j]))
{
return false;
}
}
return true;
}
public List<Integer> rowEncoding(int[][] matrix, int rowNum)
{
List<Integer> res = new ArrayList<Integer>();
int countZero = 0;
for(int i = 0; i< matrix[0].length; i++)
{
if(matrix[rowNum][i] == 0)
{
countZero++;
}
else if(countZero > 0)
{
res.add(countZero);
countZero = 0;
}
}
if(countZero > 0)
{
res.add(countZero);
}
return res;
}
public List<Integer> colEncoding(int[][] matrix, int colNum)
{
List<Integer> res = new ArrayList<Integer>();
int countZero = 0;
for(int i = 0; i< matrix.length; i++)
{
if(matrix[i][colNum] == 0)
{
countZero++;
}
else if(countZero > 0)
{
res.add(countZero);
countZero = 0;
}
}
if(countZero > 0)
{
res.add(countZero);
}
return res;
}
}
Last updated