Skip to content

Commit 15d604c

Browse files
committed
feat: solve advent of code 2016 day 1 part 2
1 parent 85bf20c commit 15d604c

File tree

6 files changed

+160
-1
lines changed

6 files changed

+160
-1
lines changed

src/advent-of-code/2016/01-no-time-for-a-taxicab/part-a/ntfta.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const bigInputPath = join(__dirname, '../input-big.txt')
1010
const bigInput = readFileSync(bigInputPath, 'utf-8')
1111

1212
for (const { fun, id } of solutions) {
13-
describe(`Advent of Code 'No Time for a Taxicab' solution '${id}'`, () => {
13+
describe(`Advent of Code 'No Time for a Taxicab p1' solution '${id}'`, () => {
1414
it('solves for empty directions', () => {
1515
assert.equal(fun(''), 0)
1616
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Finds the block distance from the first repeated location. Uses maps
3+
* numbers to number set to remember locations.
4+
*
5+
* @param {string} instr
6+
* @returns {number}
7+
*/
8+
const blockDistance = (instr) => {
9+
let x = 0
10+
let y = 0
11+
let dir = 0 // 0: north, 1: east, 2: south, 3: west
12+
13+
/** @type {Map<number, Set<number>>} */
14+
const pastLocs = new Map()
15+
const splitIns = instr ? instr.split(', ') : []
16+
17+
for (const ins of splitIns) {
18+
const turn = ins[0]
19+
const dist = parseInt(ins.slice(1))
20+
let prevX = x
21+
let prevY = y
22+
23+
// Update direction based on turn.
24+
if (turn === 'L') dir = (dir + 3) % 4
25+
else dir = (dir + 1) % 4
26+
27+
// Update distance based on direction.
28+
if (dir === 0) y += dist
29+
else if (dir === 1) x += dist
30+
else if (dir === 2) y -= dist
31+
else x -= dist
32+
33+
// Remember all visited locations on the x axis.
34+
while (prevX !== x) {
35+
if (!pastLocs.has(prevX)) pastLocs.set(prevX, new Set([y]))
36+
else if (!pastLocs.get(prevX)?.has(y)) pastLocs.get(prevX)?.add(y)
37+
else return Math.abs(prevX) + Math.abs(y)
38+
39+
if (prevX < x) prevX++
40+
else prevX--
41+
}
42+
43+
// Remember all visited locations on the y axis.
44+
while (prevY !== y) {
45+
if (!pastLocs.has(x)) pastLocs.set(x, new Set([prevY]))
46+
else if (!pastLocs.get(x)?.has(prevY)) pastLocs.get(x)?.add(prevY)
47+
else return Math.abs(x) + Math.abs(prevY)
48+
49+
if (prevY < y) prevY++
50+
else prevY--
51+
}
52+
}
53+
54+
throw new Error('No location was visited more than once')
55+
}
56+
57+
module.exports = {
58+
fun: blockDistance,
59+
id: 'number-map-set'
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Finds the block distance from the first repeated location. Uses one string
3+
* set to remember locations.
4+
*
5+
* Time complexity: O(n)
6+
* Space complexity: O(n)
7+
*
8+
* @param {string} instr
9+
* @returns {number} Block distance to the first repeated location.
10+
*/
11+
const blockDistance = (instr) => {
12+
let x = 0
13+
let y = 0
14+
let dir = 0 // 0: north, 1: east, 2: south, 3: west
15+
16+
const splitIns = instr ? instr.split(', ') : []
17+
const pastLocs = new Set(`${x},${y}`)
18+
19+
for (const ins of splitIns) {
20+
const turn = ins[0]
21+
const dist = parseInt(ins.slice(1))
22+
23+
// Update direction based on turn.
24+
if (turn === 'L') dir = (dir + 3) % 4
25+
else dir = (dir + 1) % 4
26+
27+
for (let block = 0; block < dist; block++) {
28+
if (dir === 0) y++
29+
else if (dir === 1) x++
30+
else if (dir === 2) y--
31+
else x--
32+
33+
const strLoc = `${x},${y}`
34+
if (pastLocs.has(strLoc)) return Math.abs(x) + Math.abs(y)
35+
36+
pastLocs.add(strLoc)
37+
}
38+
}
39+
40+
throw new Error('No location was visited more than once')
41+
}
42+
43+
module.exports = {
44+
fun: blockDistance,
45+
id: 'str-set'
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const ntftbNumMapSet = require('./ntftb-num-map-set')
2+
const ntftbStrSet = require('./ntftb-str-set')
3+
4+
const solutions = [
5+
ntftbNumMapSet,
6+
ntftbStrSet
7+
]
8+
9+
module.exports = solutions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const { describe, it } = require('node:test')
2+
const assert = require('node:assert/strict')
3+
4+
const { readFileSync } = require('fs')
5+
const { join } = require('path')
6+
7+
const solutions = require('./ntftb.repo')
8+
9+
const bigInputPath = join(__dirname, '../input-big.txt')
10+
const bigInput = readFileSync(bigInputPath, 'utf-8')
11+
12+
for (const { fun, id } of solutions) {
13+
describe(`Advent of Code 'No Time for a Taxicab p2' solution '${id}'`, () => {
14+
it('throws for empty directions', () => {
15+
assert.throws(() => fun(''))
16+
})
17+
18+
it('throws for directions without solution', () => {
19+
assert.throws(() => fun('R2, L2, R2, L2'))
20+
})
21+
22+
it('solves for four directions', () => {
23+
assert.equal(fun('R8, R4, R4, R8'), 4)
24+
})
25+
26+
it('solves big-sized directions (solves the puzzle)', () => {
27+
assert.equal(fun(bigInput), 182)
28+
})
29+
})
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const { readFileSync } = require('fs')
2+
const { join } = require('path')
3+
4+
const { timeAndReport } = require('../../../../../lib/time')
5+
const solutions = require('./ntftb.repo')
6+
7+
const bigInputPath = join(__dirname, '../input-huge.txt')
8+
const bigInput = readFileSync(bigInputPath, 'utf-8')
9+
10+
const args = [bigInput]
11+
const runs = 10_000
12+
const id = 'Advent of Code 2016 day 1 part 2'
13+
14+
timeAndReport(solutions, args, runs, id)

0 commit comments

Comments
 (0)