Skip to content

Commit

Permalink
eliminate shapes that span fill width or height of grid
Browse files Browse the repository at this point in the history
  • Loading branch information
skedwards88 committed May 13, 2024
1 parent e3e3b3c commit 4f80bea
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/logic/getColumnIndex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Gets the column index of a given index in a grid, assuming a square grid
export function getColumnIndex(index, gridSize) {
// error if index exceeds the grid size
if (index >= gridSize * gridSize || index < 0) {
throw new Error("Index is not within grid size");
}

return index % gridSize;
}
56 changes: 56 additions & 0 deletions src/logic/getColumnIndex.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {getColumnIndex} from "./getColumnIndex";

describe("getColumnIndex", () => {
test("returns the column index of a given index (grid size 4)", () => {
const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const gridSize = 4;
const expectedColumns = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3];
const result = indexes.map((index) => getColumnIndex(index, gridSize));
expect(result).toEqual(expectedColumns);
});

test("returns the column index of a given index (grid size 5)", () => {
const indexes = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24,
];
const gridSize = 5;
const expectedColumns = [
0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
];
const result = indexes.map((index) => getColumnIndex(index, gridSize));
expect(result).toEqual(expectedColumns);
});

test("returns the column index of a given index (grid size 1)", () => {
const index = 0;
const gridSize = 1;
const expectedColumn = 0;
const result = getColumnIndex(index, gridSize);
expect(result).toEqual(expectedColumn);
});

test("errors if index exceeds gridSize", () => {
const index = 4;
const gridSize = 2;
expect(() => getColumnIndex(index, gridSize)).toThrow(
"Index is not within grid size",
);
});

test("errors if index is negative", () => {
const index = -1;
const gridSize = 2;
expect(() => getColumnIndex(index, gridSize)).toThrow(
"Index is not within grid size",
);
});

test("errors if gridSize is 0", () => {
const index = 0;
const gridSize = 0;
expect(() => getColumnIndex(index, gridSize)).toThrow(
"Index is not within grid size",
);
});
});
12 changes: 11 additions & 1 deletion src/logic/getLettersAndShapes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {trie} from "./trie";
import {shuffleArray} from "@skedwards88/word_logic";
import {omitDuplicateWordsAcrossShapes} from "./omitDuplicateWordsAcrossShapes";
import {centerIndexes} from "./centerIndexes";
import {omitShapesThatExceedSize} from "./omitShapesThatExceedSize";

export function getLettersAndShapes({
gridSize,
Expand All @@ -23,7 +24,16 @@ export function getLettersAndShapes({
trie: trie,
});

const shuffledWordIndexes = shuffleArray(wordIndexes, pseudoRandomGenerator);
// Remove wordIndexes that exceed a shape width or height of gridSize - 1
const wordIndexesOfAppropriateSize = omitShapesThatExceedSize({
wordIndexes,
gridSize,
});

const shuffledWordIndexes = shuffleArray(
wordIndexesOfAppropriateSize,
pseudoRandomGenerator,
);

// Figure out what shape each word makes
// by centering the word indexes in the grid
Expand Down
9 changes: 9 additions & 0 deletions src/logic/getRowIndex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Gets the row index of a given index in a grid, assuming a square grid
export function getRowIndex(index, gridSize) {
// error if index exceeds the grid size
if (index >= gridSize * gridSize || index < 0) {
throw new Error("Index is not within grid size");
}

return Math.floor(index / gridSize);
}
56 changes: 56 additions & 0 deletions src/logic/getRowIndex.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {getRowIndex} from "./getRowIndex";

describe("getRowIndex", () => {
test("returns the row index of a given index (grid size 4)", () => {
const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
const gridSize = 4;
const expectedRows = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3];
const result = indexes.map((index) => getRowIndex(index, gridSize));
expect(result).toEqual(expectedRows);
});

test("returns the row index of a given index (grid size 5)", () => {
const indexes = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24,
];
const gridSize = 5;
const expectedRows = [
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
];
const result = indexes.map((index) => getRowIndex(index, gridSize));
expect(result).toEqual(expectedRows);
});

test("returns the row index of a given index (grid size 1)", () => {
const index = 0;
const gridSize = 1;
const expectedRow = 0;
const result = getRowIndex(index, gridSize);
expect(result).toEqual(expectedRow);
});

test("errors if index exceeds gridSize", () => {
const index = 4;
const gridSize = 2;
expect(() => getRowIndex(index, gridSize)).toThrow(
"Index is not within grid size",
);
});

test("errors if index is negative", () => {
const index = -1;
const gridSize = 2;
expect(() => getRowIndex(index, gridSize)).toThrow(
"Index is not within grid size",
);
});

test("errors if gridSize is 0", () => {
const index = 0;
const gridSize = 0;
expect(() => getRowIndex(index, gridSize)).toThrow(
"Index is not within grid size",
);
});
});
22 changes: 22 additions & 0 deletions src/logic/omitShapesThatExceedSize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {getColumnIndex} from "./getColumnIndex";
import {getRowIndex} from "./getRowIndex";

// Remove wordIndexes that exceed a shape width or height of gridSize - 1
export function omitShapesThatExceedSize({wordIndexes, gridSize}) {
const filteredWordIndexes = wordIndexes.filter((indexes) => {
const rowIndexes = indexes.map((index) => getRowIndex(index, gridSize));
const columnIndexes = indexes.map((index) =>
getColumnIndex(index, gridSize),
);
const maxRow = Math.max(...rowIndexes);
const minRow = Math.min(...rowIndexes);
const maxColumn = Math.max(...columnIndexes);
const minColumn = Math.min(...columnIndexes);

return (
maxRow - minRow < gridSize - 1 && maxColumn - minColumn < gridSize - 1
);
});

return filteredWordIndexes;
}
103 changes: 103 additions & 0 deletions src/logic/omitShapesThatExceedSize.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {omitShapesThatExceedSize} from "./omitShapesThatExceedSize";

describe("omitShapesThatExceedSize", () => {
test("removes wordIndexes that exceed a shape width or height of gridSize - 1 (grid size 5)", () => {
const wordIndexes = [
[0, 1, 2, 3], // width 4, height 1
[2, 3, 4, 0, 1], // width 5, height 1
[15, 18, 19, 20, 16, 17], // width 5, height 2
[10, 11, 12, 13, 14, 15, 16], // width 5, height 2
[0, 1, 2, 3, 5, 6, 7, 8], // width 4, height 2
[15, 10, 5, 0], // width 1, height 4
[2, 7, 12, 17, 22], // width 1, height 5
[0, 5, 10, 15, 20, 2], // width 2, height 5
[3, 7, 11, 15], // width 4, height 4
[0, 6, 12, 18, 24], // width 5, height 5
];
const gridSize = 5;
const expectedWordIndexes = [
[0, 1, 2, 3], // width 4, height 1
[0, 1, 2, 3, 5, 6, 7, 8], // width 4, height 2
[15, 10, 5, 0], // width 1, height 4
[3, 7, 11, 15], // width 4, height 4
];
const result = omitShapesThatExceedSize({wordIndexes, gridSize});
expect(result).toEqual(expectedWordIndexes);
});

test("removes wordIndexes that exceed a shape width or height of gridSize - 1 (grid size 4)", () => {
const wordIndexes = [
[1, 2, 3], // width 3, height 1
[0, 1, 2, 3], // width 4, height 1
[2, 3, 7, 1], // width 3, height 2
[2, 3, 4, 0, 1], // width 4, height 2
[7, 8, 9, 10, 11, 12], // width 4, height 3
[8, 4, 9, 10, 12], // width 3, height 3
[12, 8, 4, 0], // width 1, height 4
[12, 8, 4], // width 1, height 3
[0, 4, 8, 12, 5], // width 2, height 4
[0, 4, 8, 5], // width 2, height 3
[3, 6, 9, 12], // width 4, height 4
];
const gridSize = 4;
const expectedWordIndexes = [
[1, 2, 3], // width 3, height 1
[2, 3, 7, 1], // width 3, height 2
[8, 4, 9, 10, 12], // width 3, height 3
[12, 8, 4], // width 1, height 3
[0, 4, 8, 5], // width 2, height 3
];
const result = omitShapesThatExceedSize({wordIndexes, gridSize});
expect(result).toEqual(expectedWordIndexes);
});

test("works with empty wordIndexes input", () => {
const wordIndexes = [];
const gridSize = 4;
const expectedWordIndexes = [];
const result = omitShapesThatExceedSize({wordIndexes, gridSize});
expect(result).toEqual(expectedWordIndexes);
});

test("works with singleton wordIndexes input", () => {
const wordIndexes = [[0, 1, 2, 3]];
const gridSize = 4;
const expectedWordIndexes = [];
const result = omitShapesThatExceedSize({wordIndexes, gridSize});
expect(result).toEqual(expectedWordIndexes);
});

test("does not remove any indexes if all are within size", () => {
const wordIndexes = [
[1, 2, 3], // width 3, height 1
[2, 3, 7, 1], // width 3, height 2
[8, 4, 9, 10, 12], // width 3, height 3
[12, 8, 4], // width 1, height 3
[0, 4, 8, 5], // width 2, height 3
];
const gridSize = 4;
const expectedWordIndexes = [
[1, 2, 3], // width 3, height 1
[2, 3, 7, 1], // width 3, height 2
[8, 4, 9, 10, 12], // width 3, height 3
[12, 8, 4], // width 1, height 3
[0, 4, 8, 5], // width 2, height 3
];
const result = omitShapesThatExceedSize({wordIndexes, gridSize});
expect(result).toEqual(expectedWordIndexes);
});

test("removes all input if all exceed size", () => {
const wordIndexes = [
[0, 1, 2, 3], // width 4, height 1
[2, 3, 4, 0, 1], // width 4, height 2
[7, 8, 9, 10, 11, 12], // width 4, height 3
[12, 8, 4, 0], // width 1, height 4
[3, 6, 9, 12], // width 4, height 4
];
const gridSize = 4;
const expectedWordIndexes = [];
const result = omitShapesThatExceedSize({wordIndexes, gridSize});
expect(result).toEqual(expectedWordIndexes);
});
});

0 comments on commit 4f80bea

Please sign in to comment.