Skip to content

feat: day 7 bridge repair 20241207 #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ dist/
*.zip
*.rar
*.tgz
src/**/*.js

**/*.txt
!src/**/*.txt
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This repository contains solutions and a local development environment for the [
- Day 4: Ceres Search [[link]](/src/2024/2024-12-04/README.md)
- Day 5: Print Queue [[link]](/src/2024/2024-12-05/README.md)
- Day 6: Guard Gallivant [[link]](/src/2024/2024-12-06/README.md)
- Day 7: Bridge Repair [[link]](/src/2024/2024-12-07/README.md)

</details>

Expand Down
2 changes: 1 addition & 1 deletion src/2024/2024-12-06/lib/guardController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const guardController = (data: string[][], printTrail: boolean = false):
let yDirection = 0
let xDirection = 0

// Find the guard's direction
// Set the guard's direction in the grid
switch(guard.direction) {
case GuardDirection.UP:
yDirection = -1
Expand Down
2 changes: 1 addition & 1 deletion src/2024/2024-12-06/lib/guardControllerLoop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const gridHasInfiniteLoop = (
let yDirection = 0
let xDirection = 0

// Find the guard's direction
// Set the guard's direction in the grid
switch(guard.direction) {
case GuardDirection.UP:
yDirection = -1
Expand Down
2 changes: 1 addition & 1 deletion src/2024/2024-12-06/sample.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ test('Count distinct guard positions', () => {
expect(guardController(file).positionCount).toBe(26)
})

test('Count obstackle positions', () => {
test('Count obstacle positions', () => {
expect(findObstructionPositions(file)).toBe(2)
})
29 changes: 29 additions & 0 deletions src/2024/2024-12-07/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Day 7: Bridge Repair

Visit the Advent of Code website for more information on this puzzle at:

**Source:** https://adventofcode.com/2024/day/7<br>
**Status:** Complete ⭐⭐

## Code

### `totalCalibration.ts`

- `operatorCombinations()`
- Finds the possible combinations in which to place operator symbols for an `N`-length array

- `doEquation()`
- Returns the result of an AoC text equation and a set of operator symbols with the condition: left to write equation processing, disregarding operator precedence

- `totalCalibrationResult()`
- Counts the total calibration sum of input lines whose elements (numbers) match the line's target sum after processing with one of N possible combinations of `+` and `*` operator placements

### `totalCalibrationConcat.ts`

- `doEquationWithConcat()`
- Returns the result of an AoC text equation and a set of operator symbols with the conditions:
- Concatenate two (2) numbers with the `||` symbol in between
- Left to write equation processing, disregarding operator precedence

- `totalCalibrationConcat()`
- Counts the total calibration sum of input lines whose single or concatenated "joined" elements (numbers) match the line's target sum after processing with one of N possible combinations of `+`, `*` and `||` (concatenator) operator placements
9 changes: 9 additions & 0 deletions src/2024/2024-12-07/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
180: 10 18
3124: 64 44 19
76: 21 4
194: 3 5
1432: 1 1 1 3
15: 5 5 2 3
12345: 6 4 9 10
100: 25 50 10 15
125: 12 5
85 changes: 85 additions & 0 deletions src/2024/2024-12-07/lib/totalCalibration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* Finds the possible combinations in which to place operator symbols for an `N`-length array
* @param {string[]} operators String array containing operator symbols
* @param {number} N Length of a linear array
* @returns {string[][]} List (2D-string array) of possible operators placement combinations
*/
export const operatorCombinations = (
operators: string[] = ['+', '*'],
N: number
): string[][] => {
const combinations: string[][] = []
const totalCombinations = Math.pow(operators.length, N)

for (let i = 0; i < totalCombinations; i += 1) {
const list: string[] = []
let seed = i

for (let j = 0; j < N; j += 1) {
list.push(operators[seed % operators.length] as string)
seed = Math.floor(seed / operators.length)
}

combinations.push(list)
}

return combinations
}

/**
* Returns the result of an AoC text equation and a set of operator symbols with the condition:
* - Left to write equation processing, disregarding operator precedence
* @param {string} eqnString Math equation expressed as string
* @returns {number} Result of the `eqnString`
*/
export const doEquation = (numbers: number[], operators: string[]): number => {
let sum = numbers[0] as number

operators.forEach((operator, index) => {
if (operator === '+') {
sum += numbers[index + 1] as number
}

if (operator === '*') {
sum *= numbers[index + 1] as number
}
})

return sum
}

/**
* Counts the total calibration sum of input lines whose elements (numbers) match the line's target sum
* after processing with one of N possible combinations of `+` and `*` operator placements
* @param input Input string array
* @returns {number} Total calibration sum
*/
export const totalCalibrationResult = (input: string[]): number => {
const operators = ['+', '*']
let sum = 0

for (let i = 0; i < input.length; i += 1) {
const line = input[i]

if (line === undefined) break

const [targetSum, data] = line.split(': ')
const numbers = data?.split(' ').map(Number) as number[]

// Find all operator placement combinations
const combinations = operatorCombinations(operators, numbers.length - 1)

// Build the text equation
for (let j = 0; j < combinations.length; j += 1) {
// Process equation
const result = doEquation(numbers, combinations[j] as string[])

if (result === Number(targetSum)) {
sum += result
break
}
}
}

return sum
}
70 changes: 70 additions & 0 deletions src/2024/2024-12-07/lib/totalCalibrationConcat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { operatorCombinations } from './totalCalibration.js'

/**
* Returns the result of an AoC text equation and a set of operator symbols with the condition:
* - Concatenate two (2) numbers with the `||` symbol in between
* - Left to write equation processing, disregarding operator precedence
* @param {string} eqnString Math equation expressed as string
* @returns {number} Result of the `eqnString`
*/
const doEquationWithConcat = (numbers: number[], operators: string[]): number => {
let sum = numbers[0] as number

operators.forEach((operator, index) => {
if (operator === '+') {
sum += numbers[index + 1] as number
}

if (operator === '*') {
sum *= numbers[index + 1] as number
}

if (operator === '||') {
const concatNum = `${sum}${numbers[index + 1]}`
sum = Number(concatNum)
}
})

return sum
}

/**
* Counts the total calibration sum of input lines whose single or concatenated "joined" elements (numbers)
* match the line's target sum after processing with one of N possible combinations
* of `+`, `*` and `||` (concatenator) operator placements
* @param input Input string array
* @returns {number} Total calibration sum
*/
export const totalCalibrationConcat = (input: string[]): number => {
let sum = 0

for (let i = 0; i < input.length; i += 1) {
const line = input[i]

if (line === undefined) break

const [targetSum, data] = line.split(': ')
const numbers = data?.split(' ').map(Number) as number[]

// Find all operator placement combinations
const combinations = operatorCombinations(
['+', '*', '||'],
numbers.length - 1
)

// Process the text equations
for (let j = 0; j < combinations.length; j += 1) {
const result = doEquationWithConcat(
numbers,
combinations[j] as string[]
)

if (result === Number(targetSum)) {
sum += result
break
}
}
}

return sum
}
35 changes: 35 additions & 0 deletions src/2024/2024-12-07/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import path from 'path'
import { AOC_OUTPUT_TYPE, readAOCInputFile } from '@/utils/aocInputFile.js'
import { currentDirectory } from '@/utils/file.js'

import { totalCalibrationResult } from './lib/totalCalibration.js'
import { totalCalibrationConcat } from './lib/totalCalibrationConcat.js'

// Read and process the input file
const input = (readAOCInputFile({
filePath: path.join(currentDirectory(import.meta.url), 'input.txt'),
type: AOC_OUTPUT_TYPE.STRING
}) as string)
.split('\n')

/**
* Part 1/2 of the 2024-12-07 quiz
* Counts the total calibration result of the input data
*/
const quiz20241207_01 = () => {
const total = totalCalibrationResult(input)
console.log('Calibration total:', total)
}

/**
* Part 2/2 of the 2024-12-07 quiz
* Counts the total calibration result of the input data including
* "concatenated" numbers
*/
const quiz20241207_02 = () => {
const total = totalCalibrationConcat(input)
console.log('Calibration total (with concat):', total)
}

quiz20241207_01()
quiz20241207_02()
23 changes: 23 additions & 0 deletions src/2024/2024-12-07/sample.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import path from 'path'
import { test, expect } from 'vitest'

import { readAOCInputFile, AOC_OUTPUT_TYPE } from '@/utils/aocInputFile.js'
import { currentDirectory } from '@/utils/file.js'

import { totalCalibrationResult } from './lib/totalCalibration.js'
import { totalCalibrationConcat } from './lib/totalCalibrationConcat.js'

// Read and process the input file
const input = (readAOCInputFile({
filePath: path.join(currentDirectory(import.meta.url), 'input.txt'),
type: AOC_OUTPUT_TYPE.STRING
}) as string)
.split('\n')

test('1/2: Total calibration result', () => {
expect(totalCalibrationResult(input)).toBe(295)
})

test('2/2: Total calibration result (with concat)', () => {
expect(totalCalibrationConcat(input)).toBe(420)
})
1 change: 0 additions & 1 deletion src/utils/aocInputFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ type Output = string | string[] | string[][] |
* @param param.filePath {string} Full file path to an input text file
* @param param.type {AOC_OUTPUT_TYPE} Type to convert the input text file
* @param param.delimiter {string} String delimiter
* @param moduleFile {string} File URL of the current module being executed: `"import.meta.url"`
* @throws {Error}
*/
export const readAOCInputFile = (param: FileInput): Output => {
Expand Down
Loading