diff --git a/README.md b/README.md index 05f923e..76431b0 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ It follows the directory structure: > [!NOTE] > 📂 dist
> 📂 src
-> └─ 📂 utils
+> └─ 📂 aoc
> └─ 📂 sample
> └─ 📂 2024
> └─── 📂 2024-12-01
@@ -77,7 +77,7 @@ Each Advent of Code (AOC) event quiz has its folder under **`"/src// { +export const checkVertical = (coord: Coordinate, fullData: string[][], WORD: string): boolean => { let yIndex = coord.y let subWord = '' @@ -79,11 +68,11 @@ export const checkHorizontal = (coord: Coordinate, rowData: string[], WORD: stri * @typedef param {CoordinateData} Direction and data object * @param param.xDirection {number} `-1` for "left" going to (0,0) or `1` for "right" going to (N,N) from the `coord` * @param param.yDirection {number} `-1` for "up" going to (0,0) or `1` for "down" going to (N,N) from the `coord` - * @param param.data {CharacterArray} 2D string array containing the input text + * @param param.data {string[][]} 2D string array containing the input text * @returns {boolean} Flag indicating the existence of the `WORD` * @param WORD {string} Word to find */ -export const checkDiagonal = (coord: CoordinateBase, param: CoordinateData, WORD: string): boolean => { +export const checkDiagonal = (coord: Point, param: CoordinateData, WORD: string): boolean => { let xIndex = coord.x let yIndex = coord.y let subWord = '' diff --git a/src/2024/2024-12-04/lib/wordCount.ts b/src/2024/2024-12-04/lib/wordCount.ts index 463aeb3..0db10c3 100644 --- a/src/2024/2024-12-04/lib/wordCount.ts +++ b/src/2024/2024-12-04/lib/wordCount.ts @@ -2,7 +2,7 @@ import { checkVertical, checkHorizontal, checkDiagonal } from './wordCheckerUtil /** * Counts the number of occurence of the `WORD` from a set of input - * @param data {CharacterArray} 2D string array containing the input text + * @param data {string[][]} 2D string array containing the input text * @param WORD_TO_FIND {string} Word to find * @returns {number} Number of `WORD`s */ diff --git a/src/2024/2024-12-04/main.ts b/src/2024/2024-12-04/main.ts index d12deaf..75051e4 100644 --- a/src/2024/2024-12-04/main.ts +++ b/src/2024/2024-12-04/main.ts @@ -1,5 +1,5 @@ import path from 'path' -import { directory, readFile } from '@/utils/file.js' +import { directory, readFile } from '@/aoc/file/utils.js' import { wordCount } from './lib/wordCount.js' import { countMASword } from './lib/xmasCount.js' diff --git a/src/2024/2024-12-05/lib/fileReader.ts b/src/2024/2024-12-05/lib/fileReader.ts index 48b12c9..e9a4cbe 100644 --- a/src/2024/2024-12-05/lib/fileReader.ts +++ b/src/2024/2024-12-05/lib/fileReader.ts @@ -1,6 +1,6 @@ import path from 'path' -import { directory, readFile } from '@/utils/file.js' -import { uniformArrayElements } from '@/utils/arrays.js' +import { directory, readFile } from '@/aoc/file/utils.js' +import { uniformArrayElements } from '@/aoc/array/utils.js' export type Rules = Record diff --git a/src/2024/2024-12-05/lib/fixOrderingUpdates.ts b/src/2024/2024-12-05/lib/fixOrderingUpdates.ts index b7001eb..5221143 100644 --- a/src/2024/2024-12-05/lib/fixOrderingUpdates.ts +++ b/src/2024/2024-12-05/lib/fixOrderingUpdates.ts @@ -1,5 +1,5 @@ import { isOrderedReport } from './orderedUpdates.js' -import { arrayMiddleIndex, uniformArrayElements } from '@/utils/arrays.js' +import { arrayMiddleIndex, uniformArrayElements } from '@/aoc/array/utils.js' import type { Rules } from './fileReader.js' import type { QuizData } from './fileReader.js' diff --git a/src/2024/2024-12-05/lib/orderedUpdates.ts b/src/2024/2024-12-05/lib/orderedUpdates.ts index 9511495..9fb8824 100644 --- a/src/2024/2024-12-05/lib/orderedUpdates.ts +++ b/src/2024/2024-12-05/lib/orderedUpdates.ts @@ -1,5 +1,5 @@ import type { QuizData, Rules } from './fileReader.js' -import { uniformArrayElements, arrayMiddleIndex } from '@/utils/arrays.js' +import { arrayMiddleIndex, uniformArrayElements } from '@/aoc/array/utils.js' /** * Checks if an "update" list is correct according to defined "rules" diff --git a/src/2024/2024-12-06/README.md b/src/2024/2024-12-06/README.md index eb3a023..7dabb26 100644 --- a/src/2024/2024-12-06/README.md +++ b/src/2024/2024-12-06/README.md @@ -7,19 +7,25 @@ Visit the Advent of Code website for more information on this puzzle at: ## Code -1. **grid.ts** - - `Grid` - class that has a 2D array object containing paths and obstacles in which a `Guard` runs. +### `grid.ts` + +**`Grid`** class + - class that has a 2D array object containing paths and obstacles in which a `Guard` runs. - Has functions and methods for managing a `Grid` object -2. **guard.ts** - - `Guard` - class representing an object that can walk in the `Grid` map. +### `guard.ts` + +**`Guard`** class + - class representing an object that can walk in the `Grid` map. - Have methods for moving around in the `Grid`. -3. **guardController.ts** - - `guardController()` - Runs the `Guard` on the `Grid`, counting distinct positions/steps. +### `guardController.ts` + +- **`guardController()`** - Runs the `Guard` on the `Grid`, counting distinct positions/steps. + +### `guardControllerLoop.ts` +- **`gridHasInfiniteLoop()`** + - Runs the `Guard` on a `Grid` with obstacles, checking the placement of paths and obstacles that will make the `Guard` walk in an infinite loop +- **`findObstructionPositions()`** - Counts the number of positions in the `Grid` in which inserting one (1) obstruction symbol # will cause the `Guard` to walk in an infinite loop. + - > _**WARNING:** This is a very slow, unoptimized program execution that takes about ~3 mins to complete using the actual AoC input text._ -5. **guardControllerLoop.ts** - - `gridHasInfiniteLoop()` - - Runs the `Guard` on a `Grid` with obstacles, checking the placement of paths and obstacles that will make the `Guard` walk in an infinite loop - - `findObstructionPositions()` - Counts the number of positions in the `Grid` in which inserting one (1) obstruction symbol # will cause the `Guard` to walk in an infinite loop. - - > _**WARNING:** This is a very slow, unoptimized program execution that takes about ~3 mins to complete using the actual AoC input text._ diff --git a/src/2024/2024-12-06/lib/grid.ts b/src/2024/2024-12-06/lib/grid.ts index 38f6019..c5a71ff 100644 --- a/src/2024/2024-12-06/lib/grid.ts +++ b/src/2024/2024-12-06/lib/grid.ts @@ -1,7 +1,6 @@ import { GuardStatus, GuardDirection } from './guard.types.js' import type { GuardState } from './guard.types.js' - /** * @class Grid * @description Object containing a 2D array of strings and other data in which a `Guard` object runs. Each item represents an open path or obstacle. diff --git a/src/2024/2024-12-06/lib/grid.types.ts b/src/2024/2024-12-06/lib/grid.types.ts deleted file mode 100644 index 4c18219..0000000 --- a/src/2024/2024-12-06/lib/grid.types.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * `Grid` dimensions properties - * - * @property {number} length - Length of the grid - * @property {number} wwidth - Width of the grid - */ -export type GridDimensions = { - length: number; - width: number; -} diff --git a/src/2024/2024-12-06/main.ts b/src/2024/2024-12-06/main.ts index 285dded..1e11310 100644 --- a/src/2024/2024-12-06/main.ts +++ b/src/2024/2024-12-06/main.ts @@ -1,6 +1,6 @@ import path from 'path' -import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { guardController } from './lib/guardController.js' import { findObstructionPositions } from './lib/guardControllerLoop.js' diff --git a/src/2024/2024-12-06/sample.test.ts b/src/2024/2024-12-06/sample.test.ts index d5629f5..b6d3327 100644 --- a/src/2024/2024-12-06/sample.test.ts +++ b/src/2024/2024-12-06/sample.test.ts @@ -1,8 +1,8 @@ import path from 'path' import { test, expect } from 'vitest' -import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { guardController } from './lib/guardController.js' import { findObstructionPositions } from './lib/guardControllerLoop.js' diff --git a/src/2024/2024-12-07/main.ts b/src/2024/2024-12-07/main.ts index 2db9ac2..c43eead 100644 --- a/src/2024/2024-12-07/main.ts +++ b/src/2024/2024-12-07/main.ts @@ -1,6 +1,6 @@ import path from 'path' -import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { totalCalibrationResult } from './lib/totalCalibration.js' import { totalCalibrationConcat } from './lib/totalCalibrationConcat.js' diff --git a/src/2024/2024-12-07/sample.test.ts b/src/2024/2024-12-07/sample.test.ts index 710bdba..a555f8a 100644 --- a/src/2024/2024-12-07/sample.test.ts +++ b/src/2024/2024-12-07/sample.test.ts @@ -1,8 +1,8 @@ import path from 'path' import { test, expect } from 'vitest' -import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { totalCalibrationResult } from './lib/totalCalibration.js' import { totalCalibrationConcat } from './lib/totalCalibrationConcat.js' diff --git a/src/2024/2024-12-08/README.md b/src/2024/2024-12-08/README.md index b917a5e..9aa653c 100644 --- a/src/2024/2024-12-08/README.md +++ b/src/2024/2024-12-08/README.md @@ -9,14 +9,14 @@ Visit the Advent of Code website for more information on this puzzle at: ### `GridAntinodes.ts` -- `GridAntiNodes` class - Object that tracks and manages `Antennas` and `Antinodes` in a 2D grid array +- **`GridAntiNodes`** class - Object that tracks and manages `Antennas` and `Antinodes` in a 2D grid array ### `uniqueAntinodes.ts` -- `uniqueAntinodes()` - Counts the unique locations in the grid that contains an antinode +- **`countAntinodes()`** - Counts the unique locations in the grid that contains an antinode ### `allAntinodes.ts` -- `getAntinodesInPath()` - Finds all `Antinode` coordinates along a path within a 2D array (grid) given a `Point`, increment steps and a +/- direction +- **`getAntinodesInPath()`** - Finds all `Antinode` coordinates along a path within a 2D array (grid) given a `Point`, increment steps and a +/- direction -- `countAllAntinodes()` - Counts the unique locations in the grid that contains all locations of antinodes along a path +- **`countAllAntinodes()`** - Counts the unique locations in the grid that contains all locations of antinodes along a path diff --git a/src/2024/2024-12-08/lib/allAntinodes.ts b/src/2024/2024-12-08/lib/allAntinodes.ts index e63b7cb..db6d8d8 100644 --- a/src/2024/2024-12-08/lib/allAntinodes.ts +++ b/src/2024/2024-12-08/lib/allAntinodes.ts @@ -1,4 +1,5 @@ -import type { Antenna, Point } from './types.js' +import type { Antenna } from './types.js' +import type { Point } from '@/aoc/point/types.js' import { GridAntiNodes } from './GridAntinodes.js' /** diff --git a/src/2024/2024-12-08/lib/types.ts b/src/2024/2024-12-08/lib/types.ts index 868a9c2..3c9bb04 100644 --- a/src/2024/2024-12-08/lib/types.ts +++ b/src/2024/2024-12-08/lib/types.ts @@ -1,7 +1,4 @@ -export interface Point { - x: number; - y: number; -} +import type { Point } from '@/aoc/point/types.js' export interface Antenna extends Point { frequency: string; diff --git a/src/2024/2024-12-08/lib/uniqueAntinodes.ts b/src/2024/2024-12-08/lib/uniqueAntinodes.ts index 12c2882..8e494ef 100644 --- a/src/2024/2024-12-08/lib/uniqueAntinodes.ts +++ b/src/2024/2024-12-08/lib/uniqueAntinodes.ts @@ -1,4 +1,5 @@ -import type { Antenna, Point } from './types.js' +import type { Antenna } from './types.js' +import type { Point } from '@/aoc/point/types.js' import { GridAntiNodes } from './GridAntinodes.js' /** diff --git a/src/2024/2024-12-08/main.ts b/src/2024/2024-12-08/main.ts index 68ace42..190eb66 100644 --- a/src/2024/2024-12-08/main.ts +++ b/src/2024/2024-12-08/main.ts @@ -1,6 +1,6 @@ import path from 'path' -import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { countAntinodes } from './lib/uniqueAntinodes.js' import { countAllAntinodes } from './lib/allAntinodes.js' diff --git a/src/2024/2024-12-08/sample.test.ts b/src/2024/2024-12-08/sample.test.ts index 43dd301..e01904c 100644 --- a/src/2024/2024-12-08/sample.test.ts +++ b/src/2024/2024-12-08/sample.test.ts @@ -1,8 +1,8 @@ import path from 'path' import { test, expect } from 'vitest' -import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { countAntinodes } from './lib/uniqueAntinodes.js' import { countAllAntinodes } from './lib/allAntinodes.js' diff --git a/src/2024/2024-12-09/main.ts b/src/2024/2024-12-09/main.ts index 7d13b4e..facbcb9 100644 --- a/src/2024/2024-12-09/main.ts +++ b/src/2024/2024-12-09/main.ts @@ -1,7 +1,7 @@ import path from 'path' -import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { CompactDisk } from './lib/compact.js' import { WholeDisk } from './lib/whole.js' diff --git a/src/2024/2024-12-09/sample.test.ts b/src/2024/2024-12-09/sample.test.ts index 35ffb07..1ec89dd 100644 --- a/src/2024/2024-12-09/sample.test.ts +++ b/src/2024/2024-12-09/sample.test.ts @@ -1,8 +1,8 @@ import path from 'path' import { test, expect } from 'vitest' -import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js' -import { directory } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/aoc/file/aocfile.js' +import { directory } from '@/aoc/file/utils.js' import { CompactDisk } from './lib/compact.js' import { WholeDisk } from './lib/whole.js' diff --git a/src/2024/2024-12-10/README.md b/src/2024/2024-12-10/README.md index 5faaddb..685faeb 100644 --- a/src/2024/2024-12-10/README.md +++ b/src/2024/2024-12-10/README.md @@ -13,6 +13,6 @@ Visit the Advent of Code website for more information on this puzzle at: ### `scoresRatings.ts` -- `countTrailScores()` +- **`countTrailScores()`** - Finds valid hiking trails (trailheads) from a point coordinate in a 2D array starting with `0` and ending in `9` symbol and calculates the **scores** for each trailhead. - Calculates the trailhead **ratings** instead of the trailhead scores if provided with the optional `{ isRating: true }` parameter. Defaults to `false` diff --git a/src/2024/2024-12-10/lib/scoresRatings.ts b/src/2024/2024-12-10/lib/scoresRatings.ts index 8d3176a..63d2e6d 100644 --- a/src/2024/2024-12-10/lib/scoresRatings.ts +++ b/src/2024/2024-12-10/lib/scoresRatings.ts @@ -1,11 +1,8 @@ -import type { Point } from '../../2024-12-08/lib/types.js' -import type { InputOptions, PointSteps, PointDirection, TrailScores } from './types.js' - -import { - findValidSteps, - findZeroCoordinatePositions, - getCoordinateSymbol -} from './utils.js' +import type { Point, PointDirection, PointSteps } from '@/aoc/point/types.js' +import type { InputOptions, TrailScores } from './types.js' + +import { getCoordinateSymbol } from '@/aoc/grid/utils.js' +import { findValidSteps, findZeroCoordinatePositions } from './utils.js' // List of trailhead scores const scores: Record = {} diff --git a/src/2024/2024-12-10/lib/types.ts b/src/2024/2024-12-10/lib/types.ts index 5318951..165bf76 100644 --- a/src/2024/2024-12-10/lib/types.ts +++ b/src/2024/2024-12-10/lib/types.ts @@ -1,44 +1,3 @@ -/** - * Point (y,x) coordinate in a 2D array with direction - * @type {Object} PointSteps - * @property {number} x - x-coordinate of the point - * @property {number} y - y-coordinate of the point - * @property {Object} direction - Direction vector - * @property {number} direction.x - Left/right x-direction denoted by `+1` or `-1` - * @property {number} direction.y - Up/down y-direction denoted by `-1` or `+1` - */ -export type PointSteps = { - x: number; - y: number; - direction: { - x: number; - y: number; - } -} - -/** - * Point (y,x) coordinate in a 2D array with a list of valid coordinates from its location. - * @type {Object} PointDirection - * @property {number} x - x-coordinate of the point - * @property {number} y - y-coordinate of the point - * @property {PointSteps[]} validSteps - List of valid up/down/left/right coordinates from the (y,x) position. - */ -export type PointDirection = { - x: number; - y: number; - validSteps: PointSteps[] -} - -/** - * Represents a "(y,x)" coordinate in string and its value from a 2D array. - * @param {string} coordinate - String version of an "(y,x)" coordinate - * @param {string | number} symbol - Number or character in a 2D arary denoted by the (y,x) coordinate - */ -export type GridCoordinateSymbol = { - coordinate: string; - symbol: string | number; -} - /** * Data returned by the trailhead scores counting function. * @param {Record} scores - Object list of trailhead scores per (y,x) coordinate that starts with a unique `0` and ends with a `9` diff --git a/src/2024/2024-12-10/lib/utils.ts b/src/2024/2024-12-10/lib/utils.ts index ac34313..d1c1c30 100644 --- a/src/2024/2024-12-10/lib/utils.ts +++ b/src/2024/2024-12-10/lib/utils.ts @@ -1,19 +1,6 @@ -import type { Point } from '@/2024/2024-12-08/lib/types.js' -import type { GridDimensions } from '@/2024/2024-12-06/lib/grid.types.js' -import type { GridCoordinateSymbol, PointSteps } from './types.js' - -/** - * Converts a 2D `Point` point object to string and returns its value from the 2D array - * @param {Point} point - (y,x) coordinatate in the 2D array - * @param {number[][]} data - 2D number array containing hiking trail data - * @returns {GridCoordinateSymbol} Returns the `poiint` (x,y) coordinate expressed in string and its value - */ -export const getCoordinateSymbol = (point: Point, data: number[][] | string[][]): GridCoordinateSymbol => { - return { - coordinate: `${point!.x},${point!.y}`, - symbol: data[point!.y]![point!.x] as number - } -} +import type { Point, PointSteps } from '@/aoc/point/types.js' +import type { GridDimensions } from '@/aoc/grid/types.js' +import { isOutOfBounds } from '@/aoc/grid/utils.js' /** * Finds the (y,x) coordinates of starting positions in a trailhead grid @@ -32,19 +19,6 @@ export const findZeroCoordinatePositions = (data: number[][], symbol?: number): }, []) } -/** - * Checks if a (y,x) coordinate is out of the grid area - * @param {Point} point - (y,x) coordinate - * @param {GridDimensions} gridMeta - Length and width definitions of a 2D array (grid) - * @returns {boolean} Flag if a coordinate is out of the grid area - */ -export const isOutOfBounds = (point: Point, gridMeta: GridDimensions): boolean => { - return ( - point.x < 0 || point.x >= gridMeta.width || - point.y < 0 || point.y >= gridMeta.length - ) -} - /** * Finds valid positions and coordinates of next steps from a coordinate. * @param {Point} point - (y,x) coordinate object in a 2D array grid diff --git a/src/2024/2024-12-10/main.ts b/src/2024/2024-12-10/main.ts index 13621d6..c7ecd48 100644 --- a/src/2024/2024-12-10/main.ts +++ b/src/2024/2024-12-10/main.ts @@ -1,6 +1,6 @@ -import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/utils/aocInputFile.js' -import { file } from '@/utils/file.js' +import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/aoc/file/aocfile.js' +import { file } from '@/aoc/file/utils.js' import { countTrailScores } from './lib/scoresRatings.js' diff --git a/src/2024/2024-12-10/sample.test.ts b/src/2024/2024-12-10/sample.test.ts index 8b456c8..bfbde18 100644 --- a/src/2024/2024-12-10/sample.test.ts +++ b/src/2024/2024-12-10/sample.test.ts @@ -1,7 +1,7 @@ import { test, expect } from 'vitest' -import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js' -import { file } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/aoc/file/aocfile.js' +import { file } from '@/aoc/file/utils.js' import { countTrailScores } from './lib/scoresRatings.js' diff --git a/src/2024/2024-12-11/README.md b/src/2024/2024-12-11/README.md index 2be84da..39d4f10 100644 --- a/src/2024/2024-12-11/README.md +++ b/src/2024/2024-12-11/README.md @@ -10,9 +10,7 @@ Visit the Advent of Code website for more information on this puzzle at: ### `utils.ts` - contains helper and utility scripts for the quiz. -- `isEvenDigits()` - Checks if a number has an even number of digits -- `halfDigit()` - Divides the number into two (2) separate groups (digits) if they have an even number of digits, each group having half the original number's digits. -- `arrayToObject()` - Converts an array of numbers to an Object, using the array number elements as keys with a default numeric value of `1` +- **`halfDigit()`** - Divides the number into two (2) separate groups (digits) if they have an even number of digits, each group having half the original number's digits. ### `blink.ts` diff --git a/src/2024/2024-12-11/lib/blink.ts b/src/2024/2024-12-11/lib/blink.ts index 81a2161..f8d3af1 100644 --- a/src/2024/2024-12-11/lib/blink.ts +++ b/src/2024/2024-12-11/lib/blink.ts @@ -1,4 +1,6 @@ -import { arrayToObject, isEvenDigits, halfDigit } from './utils.js' +import { arrayToObject } from '@/aoc/array/utils.js' +import { isEvenDigits } from '@/aoc/number/utils.js' +import { halfDigit } from './utils.js' /** * @class Blinker diff --git a/src/2024/2024-12-11/lib/utils.ts b/src/2024/2024-12-11/lib/utils.ts index 85b2ef1..30052a0 100644 --- a/src/2024/2024-12-11/lib/utils.ts +++ b/src/2024/2024-12-11/lib/utils.ts @@ -1,11 +1,3 @@ -/** - * Checks if a number has an even number of digits - * @param {number} number - Number input - */ -export const isEvenDigits = (number: number): boolean => { - return number.toString().length % 2 === 0 -} - /** * Divides the number into two (2) separate groups (digits) if they have an even number of digits, * aach group having half the original number's digits. @@ -21,17 +13,3 @@ export const halfDigit = (number: number): number[] => { ) ] } - -/** - * Converts an array of numbers to an Object, using the array number elements as keys with a default numeric value of `1` - * @param {number[]} numbers - Array of numbers - * @returns {Record} Object - */ -export const arrayToObject = (numbers: number[]): Record => { - return numbers.reduce((list: Record, num) => - (list[num] === undefined - ? list[num] = 1 - : list[num] += 1, list), - {} - ) -} diff --git a/src/2024/2024-12-12/README.md b/src/2024/2024-12-12/README.md index 38bafe6..bdf952c 100644 --- a/src/2024/2024-12-12/README.md +++ b/src/2024/2024-12-12/README.md @@ -9,27 +9,22 @@ Visit the Advent of Code website for more information on this puzzle at: ### `garden.ts` -- **Garden** class - - A set of methods and properties for calculating Garden, Region, and Plots data - - `Garden.calculatePlot()` - Calculates the per-plot perimeter and total area of all garden regions in a 2D grid, each defined by an initial symbol at a starting (y,x) coordinate. - - `Garden.calculateFencePrice()` - Calculates the total fencing price of all regions in a garden per connected plot using the formula: area * perimeter (per plot). +**Garden** class +- A set of methods and properties for calculating Garden, Region, and Plots data +- `Garden.calculatePlot()` - Calculates the per-plot perimeter and total area of all garden regions in a 2D grid, each defined by an initial symbol at a starting (y,x) coordinate. +- `Garden.calculateFencePrice()` - Calculates the total fencing price of all regions in a garden per connected plot using the formula: area * perimeter (per plot). ### `wholesale.ts` -- **WholesaleGarden** class - - A set of methods and properties for calculating the wholesale fencing price of garden regions - - `WholesaleGarden.calculateRegionCorners()` - Calculates the number of corners (sides) of a whole region. - - `WholesaleGarden.calculateFencePrice()` - Calculates the total fencing price of all regions in a garden using the formula: area * perimeter (of whole region). +**WholesaleGarden** class +- A set of methods and properties for calculating the wholesale fencing price of garden regions +- **`calculateRegionCorners()`** - Calculates the number of corners (sides) of a whole region. +- **`calculateFencePrice()`** - Calculates the total fencing price of all regions in a garden using the formula: area * perimeter (of whole region). ### `utils.ts` - A script containing helper and utility scripts for the quiz -- `findNeighbors()` - Finds all coordinates of the neighboring plots from a specified coordinate (up/down/left/right) -- `isIllegalCoordinate()` - Checks if a point at coordinate (y,x) in a grid is illegal: if it's out of bounds of the grid area or if its symbol differs from the symbol parameter. -- `getDiagonalNeighbors()` - Retrieves the four (4) diagonally-aligned (y,x) coordinates and the symbol character from a `Point` in the grid. Substitutes a `"*"` symbol character in the `NeighborPoint.symbol`if the `point` is out of the grid bounds. -- `getCrossNeighbors()` - Retrieves the four (4) horizontal/vertical aligned (y,x) coordinates and the symbol character from a `Point` in the grid. Substitutes a `"*"` symbol character in the `NeighborPoint.symbol`if the `point` is out of the grid bounds. -- `isDiagonal()` - Checks if two (2) `Points` are diagonally-aligned -- `innerCorners()` - Counts the "inner" corners from groups of valid L-shaped `Points` that originate from a `Point` coordinate. +- **`innerCorners()`** - Counts the "inner" corners from groups of valid L-shaped `Points` that has the `point` parameter coordinate as its center ## Notes diff --git a/src/2024/2024-12-12/lib/garden.ts b/src/2024/2024-12-12/lib/garden.ts index 7e29e38..b773c5f 100644 --- a/src/2024/2024-12-12/lib/garden.ts +++ b/src/2024/2024-12-12/lib/garden.ts @@ -1,8 +1,9 @@ import type { GardenRegionDetails } from './types.js' -import type { GridDimensions } from '@/2024/2024-12-06/lib/grid.types.js' -import type { Point } from '@/2024/2024-12-08/lib/types.js' +import type { GridDimensions } from '@/aoc/grid/types.js' +import type { Point } from '@/aoc/point/types.js' -import { findNeighbors, isIllegalCoordinate } from './utils.js' +import { findNeighbors } from '@/aoc/point/utils.js' +import { isIllegalCoordinate } from '@/aoc/grid/utils.js' /** * @class Garden diff --git a/src/2024/2024-12-12/lib/types.ts b/src/2024/2024-12-12/lib/types.ts index 4b05820..9106e8f 100644 --- a/src/2024/2024-12-12/lib/types.ts +++ b/src/2024/2024-12-12/lib/types.ts @@ -1,6 +1,3 @@ -import type { GridDimensions } from '@/2024/2024-12-06/lib/grid.types.js' -import type { Point } from '@/2024/2024-12-08/lib/types.js' - /** * @type {Object} GardenRegionDetails * @property {number} area - Area of a garden region - sum of connected plots with similar symbols. @@ -20,21 +17,3 @@ export type GardenRegionSides = { area: number; sides: number; } - -/** - * @type {Object} IllegalCoordinateParams - * @property {Point} point - (y,x) coordinate object in a 2D array grid - * @property {string} symbol - Character to check in the `point` coordinate. - * @property {GridDimensions} gridMeta - Grid length and width - * @property {string[][]} grid - 2D string array input - */ -export type IllegalCoordinateParams = { - point: Point; - symbol: string; - gridMeta: GridDimensions; - grid: string[][]; -} - -export interface NeighborPoint extends Point { - symbol: string; -} diff --git a/src/2024/2024-12-12/lib/utils.ts b/src/2024/2024-12-12/lib/utils.ts index e44785d..966d9bd 100644 --- a/src/2024/2024-12-12/lib/utils.ts +++ b/src/2024/2024-12-12/lib/utils.ts @@ -1,115 +1,11 @@ -import type { Point } from '@/2024/2024-12-08/lib/types.js' -import type { IllegalCoordinateParams, NeighborPoint } from './types.js' +import type { Point } from '@/aoc/point/types.js' -import { getGridDimensions } from '@/utils/grid/utils.js' -import { isOutOfBounds } from '@/2024/2024-12-10/lib/utils.js' +import { getDiagonalNeighbors } from '@/aoc/grid/utils.js' +import { getGridDimensions, isOutOfBounds } from '@/aoc/grid/utils.js' -/** - * Finds all coordinates of the neighboring plots from a specified coordinate (up/down/left/right) - * @param {Point} point - (y,x) coordinate object in a 2D array grid - * @param {GridDimensions} gridMeta - grid length and width - * @param {string[][]} grid - 2D string array input - * @returns {PointSteps[]} Array of neighboring similar plants from the given `point` - */ -export const findNeighbors = (point: Point): Point[] | undefined => { - // All 4 possible locations (directions) from a coordinate - const steps = [ - { ...point, x: point.x - 1 }, // left - { ...point, x: point.x + 1 }, // right - { ...point, y: point.y - 1 }, // down - { ...point, y: point.y + 1 } // up - ] - - return steps -} - -/** - * Checks if a point at coordinate (y,x) in a grid is illegal: if it's out of bounds of the grid area - * or if its symbol differs from the symbol parameter. - * @param params {IllegalCoordinateParams} - Object input parameters. - * See the `IllegalCoordinateParams` for more information. - * @returns {boolean} Flag if a coordinate is illegae - */ -export const isIllegalCoordinate = (params: IllegalCoordinateParams): boolean => { - const { point, symbol, gridMeta } = params - - return ( - point.x < 0 || - point.x >= gridMeta.width || - point.y < 0 || - point.y >= gridMeta.length || - params.grid[point.y]![point.x] !== symbol - ) -} - -/** - * Retrieves the four (4) diagonally-aligned (y,x) coordinates and the symbol character from a `Point` in the grid. - * Substitutes a `"*"` symbol character in the `NeighborPoint.symbol`if the `point` is out of the grid bounds. - * @param {Point} point - (y,x) coordinate object in a 2D array grid - * @param {string[][]} data - 2D string array input - * @returns {NeighborPoint[]} Array of `NeighborPoint` with symbol characters. - */ -export const getDiagonalNeighbors = (point: Point, data: string[][]): NeighborPoint[] => { - const grid = getGridDimensions(data) - - // diagonal coordinates - const diagonals = [ - { x: point.x + 1, y: point.y - 1 }, - { x: point.x - 1, y: point.y - 1 }, - { x: point.x + 1, y: point.y + 1 }, - { x: point.x - 1, y: point.y + 1 } - ] - - return diagonals.reduce((list: NeighborPoint[], pt) => { - const item = { x: pt.x, y: pt.y, symbol: '*' } - - if (!isOutOfBounds(pt, grid)) { - item.symbol = data[pt.y]![pt.x] as string - } - - return [...list, item] - }, []) -} - -/** - * Retrieves the four (4) horizontal/vertical aligned (y,x) coordinates and the symbol character from a `Point` in the grid. - * Substitutes a `"*"` symbol character in the `NeighborPoint.symbol`if the `point` is out of the grid bounds. - * @param {Point} point - (y,x) coordinate object in a 2D array grid - * @param {string[][]} data - 2D string array input - * @returns {NeighborPoint[]} Array of `NeighborPoint` with symbol characters. - */ -export const getCrossNeighbors = (point: Point, data: string[][]): NeighborPoint[] => { - const neighbors = findNeighbors(point) as Point[] - const grid = getGridDimensions(data) - - return neighbors.reduce((list: NeighborPoint[], pt) => { - const item = { x: pt.x, y: pt.y, symbol: '*' } - - if (!isOutOfBounds(pt, grid)) { - item.symbol = data[pt.y]![pt.x] as string - } - - return [...list, item] - }, []) -} - -/** - * Checks if two (2) `Points` are diagonally-aligned - * @param {Point} p1 - (y,x) Start `Point` - * @param {Point} p2 - (y,x) End `Point` - * @returns {boolean} Flag indicating if 2 `Points` are diagonally aligned - */ -export const isDiagonal = (p1: Point, p2: Point): boolean => { - const diff = { - x: Math.abs(p1.x - p2.x), - y: Math.abs(p1.y - p2.y) - } - - return diff.x == 1 && diff.y === 1 -} /** - * Counts the "inner" corners from groups of valid L-shaped `Points` that originate from a `Point` coordinate. + * Counts the "inner" corners from groups of valid L-shaped `Points` that has the `point` parameter coordinate as its center * @param {Point} point - Origin (y,x) coordinate object in a 2D array grid * @param {string} symbol - Character to check in the `point` coordinate. * @param {string[][]} data - 2D string array input diff --git a/src/2024/2024-12-12/lib/wholesale.ts b/src/2024/2024-12-12/lib/wholesale.ts index 7fed7e2..01595fb 100644 --- a/src/2024/2024-12-12/lib/wholesale.ts +++ b/src/2024/2024-12-12/lib/wholesale.ts @@ -1,10 +1,10 @@ -import type { Point } from '@/2024/2024-12-08/lib/types.js' - -import { isOutOfBounds } from '@/2024/2024-12-10/lib/utils.js' -import { getGridDimensions } from '@/utils/grid/utils.js' -import { getCrossNeighbors, innerCorners, isDiagonal } from './utils.js' +import type { Point } from '@/aoc/point/types.js' import type { GardenRegionSides } from './types.js' +import { getCrossNeighbors, getGridDimensions, isOutOfBounds } from '@/aoc/grid/utils.js' +import { isDiagonal } from '@/aoc/point/utils.js' +import { innerCorners } from './utils.js' + /** * @class WholesaleGarden * @description A set of methods and properties for calculating the wholesale fencing price of garden regions @@ -46,7 +46,7 @@ export class WholesaleGarden { corners += 2 * Math.floor(invalidPoints.length / 2) } - // Diagonally-aligned other symbols (if only 2) count as a corner + // diagonally aligned other symbols (if only 2) count as a corner if (invalidPoints.length === 2) { if (isDiagonal(invalidPoints[0] as Point, invalidPoints[1] as Point)) { corners += 1 diff --git a/src/2024/2024-12-12/main.ts b/src/2024/2024-12-12/main.ts index 41993a2..f8055b7 100644 --- a/src/2024/2024-12-12/main.ts +++ b/src/2024/2024-12-12/main.ts @@ -1,5 +1,5 @@ -import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js' -import { file } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/aoc/file/aocfile.js' +import { file } from '@/aoc/file/utils.js' import { Garden } from './lib/garden.js' import { WholesaleGarden } from './lib/wholesale.js' diff --git a/src/2024/2024-12-12/sample.test.ts b/src/2024/2024-12-12/sample.test.ts index 1becc11..b9241a0 100644 --- a/src/2024/2024-12-12/sample.test.ts +++ b/src/2024/2024-12-12/sample.test.ts @@ -1,8 +1,8 @@ import { test, expect } from 'vitest' -import { AOC_OUTPUT_TYPE } from '@/utils/aocInputFile.js' -import { file } from '@/utils/file.js' +import { AOC_OUTPUT_TYPE } from '@/aoc/file/aocfile.js' +import { file } from '@/aoc/file/utils.js' -import { readAOCInputFileAsync } from '@/utils/aocInputFile.js' +import { readAOCInputFileAsync } from '@/aoc/file/aocfile.js' import { Garden } from './lib/garden.js' import { WholesaleGarden } from './lib/wholesale.js' diff --git a/src/aoc/README.md b/src/aoc/README.md new file mode 100644 index 0000000..4a68ac1 --- /dev/null +++ b/src/aoc/README.md @@ -0,0 +1,48 @@ +## aoc + +This folder contains common AoC-related types, scripts, and other generic helper utility functions. + +### 📂 `array` + +#### `utils.ts` + +A collection handler functions for manipulating regular arrays. + +- **`arrangeArray()`** - Array sorting function that arranges array items in ascending or descending order. +- **`arrayToObject()`** - Converts an array of numbers to an Object, using the array number elements as keys with a default numeric value of `1` +- **`arrayMiddleIndex()`** - Retrieves the middle (center) index of an array +- **`uniformArrayElements()`** - Checks if array elements have the same type using `typeof` and have no null or undefined values + +### 📂 `file` + +- **`utils.ts`** - ES modules file and directory handlers +- **`aocfile.ts`** - Functions for reading common-format AoC file input (arrays of `strings` or `numbers`) + +### 📂 `grid` + +#### `utils.ts` + +A collection of convenience handler functions for AoC 2D input arrays. + +- **`getCoordinateSymbol()`** - Converts a 2D `Point` point object to a string and returns its value from the 2D array +- **`getGridDimensions()`** - Retrieves the length and width of a 2D string or number array +- **`isIllegalCoordinate()`** - Checks if a point at coordinate (y,x) in a grid is illegal: if it's out of bounds of the grid area or if its symbol differs from the symbol parameter. +- **`isOutOfBounds()`** - Checks if a (y,x) coordinate is out of the grid area +- **`getDiagonalNeighbors()`** - Retrieves the four (4) diagonally aligned (y,x) coordinates and the symbol character from a `Point` in the grid. Substitutes a `"*"` symbol character in the `PointSymbol.symbol`if the `point` is out of the grid bounds. +- **`getCrossNeighbors()`** - Retrieves the four (4) horizontal/vertical aligned (y,x) coordinates and the symbol character from a `Point` in the grid. Substitutes a `"*"` symbol character in the `PointSymbol.symbol`if the `point` is out of the grid bounds. + +### 📂 `number` + +#### `utils.ts` + +- **`isNumber()`** - Checks if a number-like input is a number +- **`isEvenDigits()`** - Checks if a number has an even number of digits + +### 📂 `point` + +#### `utils.ts` + +- **`findNeighbors()`** - Finds all coordinates of the neighboring plots from a specified coordinate (up/down/left/right) +- **`isDiagonal()`** - Checks if two (2) `Points` are diagonally aligned + + diff --git a/src/utils/arrays.ts b/src/aoc/array/utils.ts similarity index 72% rename from src/utils/arrays.ts rename to src/aoc/array/utils.ts index f8ce6b2..c252581 100644 --- a/src/utils/arrays.ts +++ b/src/aoc/array/utils.ts @@ -20,7 +20,30 @@ export const arrangeArray = (order: ARRAY_ORDERING) => } /** - * Checks if array elements have the same type using `typeof` and has no null or undefined values + * Converts an array of numbers to an Object, using the array number elements as keys with a default numeric value of `1` + * @param {number[]} numbers - Array of numbers + * @returns {Record} Object + */ +export const arrayToObject = (numbers: number[]): Record => { + return numbers.reduce((list: Record, num) => + (list[num] === undefined + ? list[num] = 1 + : list[num] += 1, list), + {} + ) +} + +/** + * Retrieves the middle (center) index of an array + * @param list {T[]} 1-dimensional array + * @returns {number} Middle index of an array + */ +export const arrayMiddleIndex = (list: T[]): number => { + return Math.floor(list.length / 2) + list.length % 2 +} + +/** + * Checks if array elements have the same type using `typeof` and have no null or undefined values * @param items {S[]} array of elements * @param type {T} primitive type name of the elements inside the array (e.g., number, string, boolean) * @returns {boolean} Flag indicating if all array elements have the same type @@ -34,12 +57,3 @@ export const uniformArrayElements = ( .length === items.length ) } - -/** - * Retrieves the middle (center) index of an array - * @param list {T[]} 1-dimensional array - * @returns {number} Middle index of an array - */ -export const arrayMiddleIndex = (list: T[]): number => { - return Math.floor(list.length / 2) + list.length % 2 -} diff --git a/src/utils/aocInputFile.ts b/src/aoc/file/aocfile.ts similarity index 98% rename from src/utils/aocInputFile.ts rename to src/aoc/file/aocfile.ts index 690acae..2917931 100644 --- a/src/utils/aocInputFile.ts +++ b/src/aoc/file/aocfile.ts @@ -1,5 +1,5 @@ // This code contains file input readers for common AoC input types. -import { readFile } from './file.js' +import { readFile } from './utils.js' /** * Definitions of the privimite types (`AOCFileOutput`) in which to convert the AoC quiz input text file. diff --git a/src/utils/file.ts b/src/aoc/file/utils.ts similarity index 100% rename from src/utils/file.ts rename to src/aoc/file/utils.ts diff --git a/src/aoc/grid/types.ts b/src/aoc/grid/types.ts new file mode 100644 index 0000000..81d1d08 --- /dev/null +++ b/src/aoc/grid/types.ts @@ -0,0 +1,36 @@ +import type { Point } from '../point/types.js' + +/** + * Represents a "(y,x)" coordinate in string and its value from a 2D array. + * @param {string} coordinate - String version of an "(y,x)" coordinate + * @param {string | number} symbol - Number or character in a 2D arary denoted by the (y,x) coordinate + */ +export type GridCoordinateSymbol = { + coordinate: string; + symbol: string | number; +} + +/** + * `Grid` dimensions properties + * + * @property {number} length - Length of the grid + * @property {number} wwidth - Width of the grid + */ +export type GridDimensions = { + length: number; + width: number; +} + +/** + * @type {Object} IllegalCoordinateParams + * @property {Point} point - (y,x) coordinate object in a 2D array grid + * @property {string} symbol - Character to check in the `point` coordinate. + * @property {GridDimensions} gridMeta - Grid length and width + * @property {string[][]} grid - 2D string array input + */ +export type IllegalCoordinateParams = { + point: Point; + symbol: string; + gridMeta: GridDimensions; + grid: string[][]; +} diff --git a/src/aoc/grid/utils.ts b/src/aoc/grid/utils.ts new file mode 100644 index 0000000..73bab05 --- /dev/null +++ b/src/aoc/grid/utils.ts @@ -0,0 +1,117 @@ +import type { + IllegalCoordinateParams, + GridCoordinateSymbol, + GridDimensions +} from './types.js' + +import type { Point, PointSymbol } from '../point/types.js' + +import { findNeighbors } from '../point/utils.js' + +/** + * Converts a 2D `Point` point object to a string and returns its value from the 2D array + * @param {Point} point - (y,x) coordinatate in the 2D array + * @param {number[][]} data - 2D number array containing hiking trail data + * @returns {GridCoordinateSymbol} Returns the `GridCoordinateSymbol` (x,y) coordinate expressed in string and its value + */ +export const getCoordinateSymbol = (point: Point, data: number[][] | string[][]): GridCoordinateSymbol => { + return { + coordinate: `${point!.x},${point!.y}`, + symbol: data[point!.y]![point!.x] as number + } +} + +/** + * Retrieves the length and width of a 2D string or number array + * @param {string[][] | number[][]} data - 2D string or number array + * @returns {GridDimensions} Object containig the length and width of the 2D array + */ +export const getGridDimensions = (data: T[][]): GridDimensions => { + return { + length: data.length, + width: data[0]!.length + } +} + +/** + * Checks if a point at coordinate (y,x) in a grid is illegal: if it's out of bounds of the grid area + * or if its symbol differs from the symbol parameter. + * @param params {IllegalCoordinateParams} - Object input parameters. + * See the `IllegalCoordinateParams` for more information. + * @returns {boolean} Flag if a coordinate is illegae + */ +export const isIllegalCoordinate = (params: IllegalCoordinateParams): boolean => { + const { point, symbol, gridMeta } = params + + return ( + point.x < 0 || + point.x >= gridMeta.width || + point.y < 0 || + point.y >= gridMeta.length || + params.grid[point.y]![point.x] !== symbol + ) +} + +/** + * Checks if a (y,x) coordinate is out of the grid area + * @param {Point} point - (y,x) coordinate + * @param {GridDimensions} gridMeta - Length and width definitions of a 2D array (grid) + * @returns {boolean} Flag if a coordinate is out of the grid area + */ +export const isOutOfBounds = (point: Point, gridMeta: GridDimensions): boolean => { + return ( + point.x < 0 || point.x >= gridMeta.width || + point.y < 0 || point.y >= gridMeta.length + ) +} + +/** + * Retrieves the four (4) diagonally aligned (y,x) coordinates and the symbol character from a `Point` in the grid. + * Substitutes a `"*"` symbol character in the `PointSymbol.symbol`if the `point` is out of the grid bounds. + * @param {Point} point - (y,x) coordinate object in a 2D array grid + * @param {string[][]} data - 2D string array input + * @returns {PointSymbol[]} Array of `PointSymbol` with symbol characters. + */ +export const getDiagonalNeighbors = (point: Point, data: string[][]): PointSymbol[] => { + const grid = getGridDimensions(data) + + // diagonal coordinates + const diagonals = [ + { x: point.x + 1, y: point.y - 1 }, + { x: point.x - 1, y: point.y - 1 }, + { x: point.x + 1, y: point.y + 1 }, + { x: point.x - 1, y: point.y + 1 } + ] + + return diagonals.reduce((list: PointSymbol[], pt) => { + const item = { x: pt.x, y: pt.y, symbol: '*' } + + if (!isOutOfBounds(pt, grid)) { + item.symbol = data[pt.y]![pt.x] as string + } + + return [...list, item] + }, []) +} + +/** + * Retrieves the four (4) horizontal/vertical aligned (y,x) coordinates and the symbol character from a `Point` in the grid. + * Substitutes a `"*"` symbol character in the `PointSymbol.symbol`if the `point` is out of the grid bounds. + * @param {Point} point - (y,x) coordinate object in a 2D array grid + * @param {string[][]} data - 2D string array input + * @returns {PointSymbol[]} Array of `PointSymbol` with symbol characters. + */ +export const getCrossNeighbors = (point: Point, data: string[][]): PointSymbol[] => { + const neighbors = findNeighbors(point) as Point[] + const grid = getGridDimensions(data) + + return neighbors.reduce((list: PointSymbol[], pt) => { + const item = { x: pt.x, y: pt.y, symbol: '*' } + + if (!isOutOfBounds(pt, grid)) { + item.symbol = data[pt.y]![pt.x] as string + } + + return [...list, item] + }, []) +} diff --git a/src/utils/numbers.ts b/src/aoc/number/utils.ts similarity index 62% rename from src/utils/numbers.ts rename to src/aoc/number/utils.ts index fc271eb..b7a4651 100644 --- a/src/utils/numbers.ts +++ b/src/aoc/number/utils.ts @@ -11,3 +11,11 @@ export const isNumber = (input: string | number): boolean => { return !isNaN(Number(input)) } + +/** + * Checks if a number has an even number of digits + * @param {number} number - Number input + */ +export const isEvenDigits = (number: number): boolean => { + return number.toString().length % 2 === 0 +} diff --git a/src/aoc/point/types.ts b/src/aoc/point/types.ts new file mode 100644 index 0000000..f40c50b --- /dev/null +++ b/src/aoc/point/types.ts @@ -0,0 +1,74 @@ +/** + * Point (y,x) coordinate in a 2D array + * @type {Object} + * @property {number} x - x-coordinate of the point + * @property {number} y - y-coordinate of the point + */ +export interface Point { + x: number; + y: number; +} + +/** + * Point (y,x) coordinate in a 2D array with a direction that denotes either the vertical (y) or horizontal (x) direction of a `Point` + * @type {Object} + * @extends {Point} + * @property {number} direction - Vertical (y) or horizontal (x) direction of a `Point` + */ +export interface Coordinate extends Point { + direction: 1 | -1; +} + +/** + * Point (y,x) coordinate in a 2D array with symbol character + * @type {Object} + * @extends {Point} + * @property {string | number} symbol - Character or number symbol in the (y,x) coordinate location + */ +export interface PointSymbol extends Point { + symbol: string; +} + +/** + * Defines the x and y direction of a point and a 2D array data. + * @type {Object} + * @property {number} xDirection - `-1` or `1` x-coordinate direction + * @property {number} yDirection - `-1` or `1` y-coordinate direction + * @property {string[][] | number[][]} data - 2D string or number array + */ +export interface CoordinateData { + xDirection: 1 | -1; + yDirection: 1 | -1; + data: string[][] | number[][] +} + +/** + * Point (y,x) coordinate in a 2D array with a (y,x) direction + * @type {Object} PointSteps + * @property {number} x - x-coordinate of the point + * @property {number} y - y-coordinate of the point + * @property {Object} direction - Direction vector + * @property {number} direction.x - Left/right x-direction denoted by `+1` or `-1` + * @property {number} direction.y - Up/down y-direction denoted by `-1` or `+1` + */ +export type PointSteps = { + x: number; + y: number; + direction: { + x: number; + y: number; + } +} + +/** + * Point (y,x) coordinate in a 2D array with a list of valid coordinate `PointSteps[]` from its location. + * @type {Object} PointDirection + * @property {number} x - x-coordinate of the point + * @property {number} y - y-coordinate of the point + * @property {PointSteps[]} validSteps - List of valid up/down/left/right coordinates from the (y,x) position. + */ +export type PointDirection = { + x: number; + y: number; + validSteps: PointSteps[] +} diff --git a/src/aoc/point/utils.ts b/src/aoc/point/utils.ts new file mode 100644 index 0000000..9155c91 --- /dev/null +++ b/src/aoc/point/utils.ts @@ -0,0 +1,35 @@ +import type { Point } from './types.js' + +/** + * Finds all coordinates of the neighboring plots from a specified coordinate (up/down/left/right) + * @param {Point} point - (y,x) coordinate object in a 2D array grid + * @param {GridDimensions} gridMeta - grid length and width + * @param {string[][]} grid - 2D string array input + * @returns {PointSteps[]} Array of neighboring similar plants from the given `point` + */ +export const findNeighbors = (point: Point): Point[] | undefined => { + // All 4 possible locations (directions) from a coordinate + const steps = [ + { ...point, x: point.x - 1 }, // left + { ...point, x: point.x + 1 }, // right + { ...point, y: point.y - 1 }, // down + { ...point, y: point.y + 1 } // up + ] + + return steps +} + +/** + * Checks if two (2) `Points` are diagonally aligned + * @param {Point} p1 - (y,x) Start `Point` + * @param {Point} p2 - (y,x) End `Point` + * @returns {boolean} Flag indicating if 2 `Points` are diagonally aligned + */ +export const isDiagonal = (p1: Point, p2: Point): boolean => { + const diff = { + x: Math.abs(p1.x - p2.x), + y: Math.abs(p1.y - p2.y) + } + + return diff.x == 1 && diff.y === 1 +} diff --git a/src/utils/grid/utils.ts b/src/utils/grid/utils.ts deleted file mode 100644 index 084dad2..0000000 --- a/src/utils/grid/utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { GridDimensions } from '@/2024/2024-12-06/lib/grid.types.js' - -/** - * Retrieves the length and width of a 2D string or number array - * @param {string[][] | number[][]} data - 2D string or number array - * @returns {GridDimensions} Object containig the length and width of the 2D array - */ -export const getGridDimensions = (data: T[][]): GridDimensions => { - return { - length: data.length, - width: data[0]!.length - } -}