Skip to content

Commit 801e467

Browse files
committed
feat: solve advent of code 2015 day 1
1 parent 94cebd1 commit 801e467

13 files changed

+216
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Advent of Code 2015 Day 1 - Not Quite Lisp
2+
3+
## Part A
4+
5+
Santa is trying to deliver presents in a large apartment building, but he can't
6+
find the right floor - the directions he got are a little confusing. He starts
7+
on the ground floor (floor `0`) and then follows the instructions one character
8+
at a time.
9+
10+
An opening parenthesis, `(`, means he should go up one floor, and a closing
11+
parenthesis, `)`, means he should go down one floor.
12+
13+
The apartment building is very tall, and the basement is very deep; he will
14+
never find the top or bottom floors.
15+
16+
To what floor do the instructions take Santa? Assume that the input string can
17+
only contain the characters `(`, `)`.
18+
19+
### Expected Behavior
20+
21+
```
22+
In: ''
23+
Out: 0
24+
25+
In: '(())'
26+
Out: 0
27+
28+
In: '(((('
29+
Out: 4
30+
31+
In: '))))'
32+
Out: -4
33+
34+
In: ')())())'
35+
Out: -3
36+
```
37+
38+
## Part B
39+
40+
Now, given the same instructions, find the position of the first character that
41+
causes him to enter the basement (floor -1). The first character in the
42+
instructions has position 1, the second character has position 2, and so on.
43+
44+
What is the position of the character that causes Santa to first enter the
45+
basement? Throw an error if the basement is never reached.
46+
47+
### Expected Behavior
48+
49+
```
50+
In: ''
51+
Out: Throw error
52+
53+
In: ')'
54+
Out: 1
55+
56+
In: '())()'
57+
Out: 3
58+
59+
In: '()((()'
60+
Out: Throw error
61+
```

src/advent-of-code/2015/01-not-quite-lisp/part-a/nqla-recursive-tail.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22
* Finds the floor where santa needs to deliver presents. Uses tail recursion.
33
*
44
* Time complexity: O(n)
5-
* Space complexity: O(n)
5+
* Space complexity: O(n) (call stack size)
66
*
77
* @param {string} dir Floor directions.
88
* @returns {number} Floor number.
99
*/
1010
const findFloor = (dir) => {
1111
/**
1212
* Recursive helper function.
13+
*
1314
* @param {number} idx Current index.
1415
* @param {number} sum Current sum.
16+
* @returns {number} Floor number.
1517
*/
1618
const recur = (idx, sum) => {
1719
if (idx >= dir.length) return sum

src/advent-of-code/2015/01-not-quite-lisp/part-a/nqla-recursive.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Finds the floor where santa needs to deliver presents. Uses recursion.
33
*
44
* Time complexity: O(n)
5-
* Space complexity: O(n)
5+
* Space complexity: O(n^2) (string copy in each call stack)
66
*
77
* @param {string} dir Floor directions.
88
* @returns {number} Floor number.

src/advent-of-code/2015/01-not-quite-lisp/part-a/nqla.repo.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const nqlaForLoop = require('./nqla-for-loop')
1+
const nqlaForLoop = require('./nqla-loop-for')
22
const nqlaReduce = require('./nqla-reduce')
33
const nqlaRecursive = require('./nqla-recursive')
44
const nqlaTail = require('./nqla-recursive-tail')

src/advent-of-code/2015/01-not-quite-lisp/part-a/nqla.test.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,23 @@ const bigInput = readFileSync(bigInputPath, 'utf-8')
1111

1212
for (const { fun, id } of solutions) {
1313
describe(`Advent of Code 'Not Quite Lisp (part a)' solution '${id}'`, () => {
14-
it('Solves empty string', () => {
14+
it('solves empty string', () => {
1515
assert.equal(fun(''), 0)
1616
})
1717

18-
it('Solves string of length 1', () => {
18+
it('solves string of length 1', () => {
1919
assert.equal(fun('('), 1)
2020
assert.equal(fun(')'), -1)
2121
})
2222

23-
it('Solves string of length 4', () => {
23+
it('solves string of length 4', () => {
2424
assert.equal(fun('(())'), 0)
2525
assert.equal(fun('()()'), 0)
2626
assert.equal(fun('((()'), 2)
2727
assert.equal(fun('))))'), -4)
2828
})
2929

30-
it('Solves big input', () => {
30+
it('solves big input', () => {
3131
assert.equal(fun(bigInput), 232)
3232
})
3333
})

src/advent-of-code/2015/01-not-quite-lisp/part-a/nqla.time.js

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

1010
const args = [bigInput]
11-
const runs = 1_000
11+
const runs = 2_000
1212
const id = 'Advent of Code "Not Quite Lisp (part a)"'
1313

1414
timeAndReport(solutions, args, runs, id)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Finds the position of the first character that causes santa to enter the
3+
* basement (floor -1). Uses a for loop.
4+
*
5+
* Time complexity: O(n)
6+
* Space complexity: O(1)
7+
*
8+
* @param {string} dir Floor directions.
9+
* @returns {number} Position of first character that reaches the basement.
10+
*/
11+
const findBasePos = (dir) => {
12+
let floor = 0
13+
14+
for (let idx = 0; idx < dir.length; idx++) {
15+
if (dir[idx] === '(') floor++
16+
else floor--
17+
18+
if (floor === -1) return idx + 1
19+
}
20+
21+
throw new Error('Basement was never reached')
22+
}
23+
24+
module.exports = {
25+
fun: findBasePos,
26+
id: 'for-loop'
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Finds the position of the first character that causes santa to enter the
3+
* basement (floor -1). Uses a while loop.
4+
*
5+
* Time complexity: O(n)
6+
* Space complexity: O(1)
7+
*
8+
* @param {string} dir Floor directions.
9+
* @returns {number} Position of first character that reaches the basement.
10+
*/
11+
const findBasePos = (dir) => {
12+
let floor = 0
13+
let idx = 0
14+
15+
while (idx < dir.length) {
16+
if (dir[idx] === '(') floor++
17+
else floor--
18+
19+
if (floor === -1) return idx + 1
20+
21+
idx++
22+
}
23+
24+
throw new Error('Basement was never reached')
25+
}
26+
27+
module.exports = {
28+
fun: findBasePos,
29+
id: 'while-loop'
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Finds the position of the first character that causes santa to enter the
3+
* basement (floor -1). Uses tail recursion.
4+
*
5+
* Time complexity: O(n)
6+
* Space complexity: O(n) (call stack size)
7+
*
8+
* @param {string} dir Floor directions.
9+
* @returns {number} Position of first character that reaches the basement.
10+
*/
11+
const findBasePos = (dir) => {
12+
/**
13+
* Recursive helper function.
14+
*
15+
* @param {number} idx Current index.
16+
* @param {number} sum Current sum.
17+
* @returns {number} Position of first character that reaches the basement.
18+
*/
19+
const recur = (idx, sum) => {
20+
if (sum === -1) return idx
21+
if (idx >= dir.length) throw new Error('Basement was never reached')
22+
23+
if (dir[idx] === '(') return recur(idx + 1, sum + 1)
24+
else return recur(idx + 1, sum - 1)
25+
}
26+
27+
return recur(0, 0)
28+
}
29+
30+
module.exports = {
31+
fun: findBasePos,
32+
id: 'tail-recursion'
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const nqlbWhileLoop = require('./nqlb-loop-while')
2+
const nqlbForLoop = require('./nqlb-loop-for')
3+
const nqlbTailRecursion = require('./nqlb-recursive-tail')
4+
5+
const solutions = [
6+
nqlbWhileLoop,
7+
nqlbForLoop,
8+
nqlbTailRecursion
9+
]
10+
11+
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('./nqlb.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 'Not Quite Lisp (part b)' solution '${id}'`, () => {
14+
it('throws error for empty string', () => {
15+
assert.throws(() => fun(''))
16+
})
17+
18+
it('solves string of length 1', () => {
19+
assert.equal(fun(')'), 1)
20+
})
21+
22+
it('solves big input', () => {
23+
assert.equal(fun(bigInput), 1783)
24+
})
25+
26+
it('throws error if basement is not reached', () => {
27+
assert.throws(() => fun('()((()'))
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 solutions = require('./nqlb.repo')
5+
const { timeAndReport } = require('../../../../../lib/time')
6+
7+
const bigInputPath = join(__dirname, '../input-big.txt')
8+
const bigInput = readFileSync(bigInputPath, 'utf-8')
9+
10+
const args = [bigInput]
11+
const runs = 10_000
12+
const id = 'Advent of Code "Not Quite Lisp (part b)"'
13+
14+
timeAndReport(solutions, args, runs, id)

0 commit comments

Comments
 (0)