DEV Community

loading...

Discussion on: Checking Sudoku with Functional JavaScript

Collapse
rhysbrettbowen profile image
Rhys Brett-Bowen • Edited

There might be a better way to check for squares. Basically you are always getting the data and putting it in to 9 arrays. So at its simplest you want to put these in to arrays and then check them all.

How about we have a function that that takes the x,y and gives us a number that tells us which array something should be in? For rows it's easy (x,y) => x. For columns also easy (x,y) => y. For squares it's a little different - you were mostly there though: (x, y) => 3 * Math.floor(x / 3) + Math.floor(y/3)

basically you divide and floor it to get x and y to 0,1 or 2. Then you multiply one by 3 to basically use base3 numbers.

you'd end up with something like the below (excuse any minor errors and messiness - I just did this quick):

makeBlankSudoku = () => [[],[],[],[],[],[],[],[],[]];
sudokuReducer(getArray) => sudokuData => sudokuData.reduce((output, line, y) => line.map((number, x) => output[getArray(x,y)].push(number)), makeBlankSodoku());
rowConverter = sudokuReducer(x => x);
colConverter = sudokuReducer((_, y) => y);
squareConverter = sudokuReducer((x, y) => 3 * Math.floor(x / 3) + Math.floor(y/3));
rowConverter(data).concat(columnConverter(data)).concat(squareConverter(data)).every(isValid);
Collapse
rhysbrettbowen profile image
Rhys Brett-Bowen • Edited

you could make this a bit better by just flattening the data and using a utility like lodash's groupBy. Then you can do something like withIndexAsXY = (fn, index) => fn(index % 9, Math.floor(index / 9)); and use the above functions on flattened data like:

xyToSquare = (x, y) => .....
squareData = groupBy(flatten(sudokuData), partial(withIndexAsXY, xyToSquare));

which may seem more complicated - but it means things have become more reusable