Skip to content

Commit

Permalink
fix padding logic and add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
skedwards88 committed Aug 25, 2024
1 parent 56ccd4a commit b8b0acd
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 20 deletions.
34 changes: 19 additions & 15 deletions src/logic/resizeGrid.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import cloneDeep from "lodash.clonedeep";
import {getMaxShifts} from "@skedwards88/word_logic";

// `grid` starts out as a 12x12 2D array
// Remove or add empty edge columns or rows to get as close as possible to one empty row/column on each edge
// Remove/add empty edge columns or rows to
// get as close as possible to one empty row/column on each edge
// and to center the contents,
// while still keeping the grid square
// and not making the grid smaller than 8x8
export function resizeGrid(grid) {
if (grid.some((row) => row.length != grid.length)) {
throw new Error("Input grid is not square");
}

let paddedGrid = cloneDeep(grid);

// Get the current maximum number of empty columns/rows that are on the edge of the grid
Expand All @@ -14,12 +19,15 @@ export function resizeGrid(grid) {
"",
);

//
// Get the width/height, not counting empty rows/cols on the edge
const usedWidth = grid.length - maxShiftLeft - maxShiftRight;
const usedHeight = grid[0].length - maxShiftUp - maxShiftDown;

// The optimum dimension is 1 empty row/col on each side
// but extra will be added to keep the grid square and at least 8x8
const targetDimension = Math.max(usedHeight + 2, usedWidth + 2, 8);

// Figure out the number of empty rows/cols on each edge
const targetPadTop = Math.floor((targetDimension - usedHeight) / 2);
const targetPadBottom = Math.ceil((targetDimension - usedHeight) / 2);
const targetPadLeft = Math.floor((targetDimension - usedWidth) / 2);
Expand All @@ -30,25 +38,21 @@ export function resizeGrid(grid) {
paddedGrid.splice(0, maxShiftUp - targetPadTop);
} else {
// or pad
paddedGrid = [
...Array(targetPadTop - maxShiftUp).fill(
Array(paddedGrid[0].length).fill(""),
),
...paddedGrid,
];
const newRows = Array.from({length: targetPadTop - maxShiftUp}, () =>
Array(paddedGrid[0].length).fill(""),
);
paddedGrid = [...newRows, ...paddedGrid];
}

if (targetPadBottom < maxShiftDown) {
// trim bottom
paddedGrid.splice(-(maxShiftDown - targetPadBottom));
} else {
// or pad
paddedGrid = [
...paddedGrid,
...Array(targetPadBottom - maxShiftDown).fill(
Array(paddedGrid[0].length).fill(""),
),
];
const newRows = Array.from({length: targetPadBottom - maxShiftDown}, () =>
Array(paddedGrid[0].length).fill(""),
);
paddedGrid = [...paddedGrid, ...newRows];
}

if (targetPadLeft < maxShiftLeft) {
Expand Down
209 changes: 204 additions & 5 deletions src/logic/resizeGrid.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,29 @@ describe("resizeGrid", () => {
expect(resizeGrid(input)).toEqual(expected);
});

test("expands a grid up to 8x8", () => {
const input = [
["A", "B", "C", "", "", ""],
["A", "B", "C", "", "", ""],
["X", "Y", "Z", "", "", ""],
["", "", "", "", "", ""],
["", "", "", "", "", ""],
["", "", "", "", "", ""],
];
const expected = [
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "X", "Y", "Z", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(resizeGrid(input)).toEqual(expected);
});

test("pads a grid so that there 1 empty row/col on each edge", () => {
const input = [
["A", "", "", "", "", "", "", "", "", "", "", "B"],
Expand Down Expand Up @@ -80,7 +103,6 @@ describe("resizeGrid", () => {
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
];
console.log(JSON.stringify(resizeGrid(input)));

const expected = [
["", "", "", "", "", "", "", ""],
Expand All @@ -96,7 +118,7 @@ describe("resizeGrid", () => {
expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are on the left edge", () => {
test("works if the grid contents are on the left edge and need padding", () => {
const input = [
["A", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
Expand Down Expand Up @@ -131,7 +153,7 @@ describe("resizeGrid", () => {
expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are on the right edge", () => {
test("works if the grid contents are on the right edge and need padding", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", "", "A"],
["", "", "", "", "", "", "", "", "", "", "", ""],
Expand Down Expand Up @@ -166,7 +188,7 @@ describe("resizeGrid", () => {
expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are on the top edge", () => {
test("works if the grid contents are on the top edge and need padding", () => {
const input = [
["A", "", "", "D", "", "", "", "", "", "", "", "C"],
["", "", "", "", "", "", "", "", "", "", "", ""],
Expand Down Expand Up @@ -201,7 +223,7 @@ describe("resizeGrid", () => {
expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are on the bottom edge", () => {
test("works if the grid contents are on the bottom edge and need padding", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
Expand Down Expand Up @@ -236,6 +258,153 @@ describe("resizeGrid", () => {
expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are near bottom edge and need trimming on the top and padding on the bottom", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "A", "B", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
];

const expected = [
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "A", "B", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are near top edge and need trimming on the bottom and padding on the top", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "A", "B", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
];

const expected = [
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "A", "B", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are near left edge", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "A", "B", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""],
];

const expected = [
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "A", "B", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(resizeGrid(input)).toEqual(expected);
});

test("works if the grid contents are near right edge", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "A", "B", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
];

const expected = [
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "A", "B", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(resizeGrid(input)).toEqual(expected);
});

test("testing odd number row/cols", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "A", "B", "C", "", "", "", "", ""],
["", "", "", "A", "B", "C", "", "", "", "", ""],
["", "", "", "X", "Y", "Z", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", "", "", ""],
];
const expected = [
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "X", "Y", "Z", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(resizeGrid(input)).toEqual(expected);
});

test("works on an empty grid", () => {
const input = [
["", "", "", "", "", "", "", "", "", "", "", ""],
Expand Down Expand Up @@ -281,4 +450,34 @@ describe("resizeGrid", () => {
expect(resizeGrid(input)).toEqual(input);
expect(resizeGrid(input)).not.toBe(input);
});

test("errors if grid is taller than wide", () => {
const input = [
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "X", "Y", "Z", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(() => resizeGrid(input)).toThrow("Input grid is not square");
});

test("errors if grid is wider than tall", () => {
const input = [
["", "", "", "", "", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "A", "B", "C", "", "", ""],
["", "", "X", "Y", "Z", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
];

expect(() => resizeGrid(input)).toThrow("Input grid is not square");
});
});

0 comments on commit b8b0acd

Please sign in to comment.