Skip to content

Commit 1f86aa0

Browse files
committed
feat: day 4 ceres search quiz 1/2 soln, #9
1 parent ba57b18 commit 1f86aa0

File tree

7 files changed

+232
-1
lines changed

7 files changed

+232
-1
lines changed

src/2024/2024-12-01/lib/fileReader.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export const fileReader = (): arrayLists => {
2424
const pair = item.split(' ')
2525

2626
if (pair[0] === undefined || pair[1] === undefined) {
27-
console.log(pair)
2827
throw new Error('Undefined value')
2928
}
3029

src/2024/2024-12-04/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
## Day 4: Ceres Search
2+
3+
Visit the Advent of Code website for more information on this puzzle at:
4+
5+
**Source:** https://adventofcode.com/2024/day/4<br>
6+
**Status:** On-going

src/2024/2024-12-04/input.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
SAMPLEONLY
2+
REPLACEITW
3+
ACTUALAOC.
4+
INPUTEXT..
5+
ABCDEFGHIJ
6+
XMASXMASXM
7+
GMUASHLGWH
8+
MXAXAXMHRD
9+
AFHSGJM2AX
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
export type CharacterArray = string[][]
2+
3+
interface CoordinateBase {
4+
x: number;
5+
y: number;
6+
}
7+
8+
interface Coordinate extends CoordinateBase {
9+
direction: 1 | -1;
10+
}
11+
12+
interface CoordinateData {
13+
xDirection: 1 | -1;
14+
yDirection: 1 | -1;
15+
data: CharacterArray
16+
}
17+
18+
/**
19+
* Checks for the 'XMAS' word in the vertical directions (up/down) from an (x,y) coordinate
20+
* @typedef coord {Coordinate} Coordinate object
21+
* @param coord.x {number} x coordinate (array x index)
22+
* @param coord.y {number} y coordinate (array y index)
23+
* @param coord.direction {number} Up or down letter-checking direction
24+
* - `-1` for "up" going to (0,0)
25+
* - `1` for "down" going to (N,N) from the `coord`
26+
* @param fullData {CharacterArray} 2D array of strings consisting of letters per item
27+
* @param WORD {string} Word to find
28+
* @returns {boolean} Flag indicating the existence of the 'XMAS' word
29+
*/
30+
export const checkVertical = (coord: Coordinate, fullData: CharacterArray, WORD: string): boolean => {
31+
let yIndex = coord.y
32+
let subWord = ''
33+
34+
if (!Array.isArray(fullData)) return false
35+
36+
for (let i = 0; i < WORD.length; i += 1) {
37+
if (yIndex < 0) break
38+
if (yIndex >= fullData.length) break
39+
40+
subWord += (fullData[yIndex])?.[coord.x]
41+
yIndex += (coord.direction * 1)
42+
}
43+
44+
return subWord === WORD
45+
}
46+
47+
/**
48+
* Checks for the 'XMAS' word in the horizontal directions (left/right) from an (x,y) coordinate
49+
* @typedef coord {Coordinate} Coordinate object
50+
* @param coord.x {number} x coordinate (array x index)
51+
* @param coord.y {number} y coordinate (array y index)
52+
* @param coord.direction {number} `-1` for "left" going to (0,0) or `1` for "right" going to (N,N) from the `coord`
53+
* @param rowData {string[]} Array of row-wise letters from a 2D array
54+
* @returns {boolean} Flag indicating the existence of the 'XMAS' word
55+
* @param WORD {string} Word to find
56+
*/
57+
export const checkHorizontal = (coord: Coordinate, rowData: string[], WORD: string): boolean => {
58+
let xIndex = coord.x
59+
let subWord = ''
60+
61+
if (!Array.isArray(rowData)) return false
62+
63+
for (let i = 0; i < WORD.length; i += 1) {
64+
if (xIndex < 0) break
65+
if (xIndex >= rowData.length) break
66+
67+
subWord += rowData[xIndex]
68+
xIndex += (coord.direction * 1)
69+
}
70+
71+
return subWord === WORD
72+
}
73+
74+
/**
75+
* Checks for the 'XMAS' word in the horizontal directions from an (x,y) coordinate
76+
* @typedef coord {Coordinate} Coordinate object
77+
* @param coord.x {number} x coordinate (array x index)
78+
* @param coord.y {number} y coordinate (array y index)
79+
* @typedef param {CoordinateData} Direction and data object
80+
* @param param.xDirection {number} `-1` for "left" going to (0,0) or `1` for "right" going to (N,N) from the `coord`
81+
* @param param.yDirection {number} `-1` for "up" going to (0,0) or `1` for "down" going to (N,N) from the `coord`
82+
* @param param.data {CharacterArray} 2D string array containing the input text
83+
* @returns {boolean} Flag indicating the existence of the 'XMAS' word
84+
* @param WORD {string} Word to find
85+
*/
86+
export const checkDiagonal = (coord: CoordinateBase, param: CoordinateData, WORD: string): boolean => {
87+
let xIndex = coord.x
88+
let yIndex = coord.y
89+
let subWord = ''
90+
91+
if (!Array.isArray(param.data)) return false
92+
if (param.data[0] === undefined) return false
93+
94+
for (let i = 0; i < WORD.length; i += 1) {
95+
if (xIndex < 0 || xIndex >= param.data[0].length) break
96+
if (yIndex < 0 || yIndex >= param.data.length) break
97+
98+
subWord += (param.data[yIndex])?.[xIndex]
99+
100+
xIndex += (param.xDirection * 1)
101+
yIndex += (param.yDirection * 1)
102+
}
103+
104+
return subWord === WORD
105+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { checkVertical, checkHorizontal, checkDiagonal } from './wordChecker.js'
2+
3+
/**
4+
* Counts the number of occurence of the 'XMAS' word from a set of input
5+
* @param data {CharacterArray} 2D string array containing the input text
6+
* @param WORD_TO_FIND {string} Word to find
7+
* @returns {number} Number of 'XMAS' words
8+
*/
9+
export const wordCount = (data: string[][], WORD_TO_FIND: string): number => {
10+
let xmasCount = 0
11+
const firstLetter = WORD_TO_FIND[0]
12+
13+
for (let y = 0; y < data.length; y += 1) {
14+
const row = data[y]
15+
16+
if (!Array.isArray(row)) continue
17+
18+
if (row.filter(
19+
item => typeof item !== 'string').length > 0
20+
) continue
21+
22+
for (let x = 0; x < row.length; x += 1) {
23+
const letter = row[x]
24+
25+
if (letter !== firstLetter) continue
26+
27+
// Check WORD_TO_FIND down
28+
if (checkVertical(
29+
{ x, y, direction: 1 }, data, WORD_TO_FIND)) xmasCount += 1
30+
31+
// Check WORD_TO_FIND up
32+
if (checkVertical(
33+
{ x, y, direction: -1 }, data, WORD_TO_FIND)) xmasCount += 1
34+
35+
// Check WORD_TO_FIND right
36+
if (checkHorizontal(
37+
{ x, y, direction: 1 }, row, WORD_TO_FIND)) xmasCount += 1
38+
39+
// Check WORD_TO_FIND left
40+
if (checkHorizontal(
41+
{ x, y, direction: -1 }, row, WORD_TO_FIND)) xmasCount += 1
42+
43+
// Check WORD_TO_FIND diagonally right-up
44+
if (checkDiagonal(
45+
{ x, y },
46+
{ xDirection: 1, yDirection: -1, data },
47+
WORD_TO_FIND
48+
)) {
49+
xmasCount += 1
50+
}
51+
52+
// Check WORD_TO_FIND diagonally right-down
53+
if (checkDiagonal(
54+
{ x, y },
55+
{ xDirection: 1, yDirection: 1, data },
56+
WORD_TO_FIND
57+
)) {
58+
xmasCount += 1
59+
}
60+
61+
// Check WORD_TO_FIND diagonally left-up
62+
if (checkDiagonal(
63+
{ x, y },
64+
{ xDirection: -1, yDirection: -1, data },
65+
WORD_TO_FIND
66+
)) {
67+
xmasCount += 1
68+
}
69+
70+
// Check WORD_TO_FIND diagonally left-down
71+
if (checkDiagonal(
72+
{ x, y },
73+
{ xDirection: -1, yDirection: 1, data },
74+
WORD_TO_FIND
75+
)) {
76+
xmasCount += 1
77+
}
78+
}
79+
}
80+
81+
return xmasCount
82+
}

src/2024/2024-12-04/main.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import path from 'path'
2+
import { currentDirectory, readFile } from '@/utils/file.js'
3+
import { wordCount } from './lib/wordCount.js'
4+
5+
const directory = currentDirectory(import.meta.url)
6+
7+
const data: string[][] = readFile(path.join(directory, 'input.txt'))
8+
.split('\n')
9+
.map(row => row.split(''))
10+
11+
const quiz20241204_01 = () => {
12+
const count = wordCount(data, 'XMAS')
13+
console.log('"XMAS" word count:', count)
14+
}
15+
16+
quiz20241204_01()

src/2024/2024-12-04/sample.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { test, expect } from 'vitest'
2+
import { wordCount } from './lib/wordCount.js'
3+
4+
const data: string[][] = `ABCDEFGHIJ
5+
XMASXMASXM
6+
GMUASHLGWH
7+
MXAXAXMHRD
8+
AFHSGJM2AX`
9+
.split('\n')
10+
.map(row => row.split(''))
11+
12+
test('Count "XMAS" words - demo', () => {
13+
expect(wordCount(data, 'XMAS')).toBe(3)
14+
})

0 commit comments

Comments
 (0)