Skip to content

Commit 672e1cd

Browse files
refactor(2020-day-01): use recursion for expense records checksum search
This will allow for 2020 Day 01 Part 2 to specify an arbitrary number of expense reports
1 parent b2990e7 commit 672e1cd

File tree

1 file changed

+48
-11
lines changed

1 file changed

+48
-11
lines changed

2020/day-01/expenseValidation.js

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,62 @@
22
/**
33
* Validates a list of records by comparing every combination
44
* to the checksum. Stops when the first match is found
5+
* @param {array} records List of records to check
6+
* @param {int} checksum The target sum that records should add up to
7+
* @param {int} goal The number of records we hope to find
58
*/
6-
const validateRecords = (records, checksum = 2020) => {
9+
const validateRecords = (records, checksum = 2020, goal = 2) => {
710
const results = []
811

9-
// We're using Array.find() at each level so it stops looping
10-
// onced matched. This game has a habit of throwing huge
11-
// data sets to discourage brute-forcing
12-
const matcher = records.find((record) => {
13-
const match = records.find(matchRec => record + matchRec === checksum)
14-
if (match) {
15-
results.push(match)
12+
const obj = { foo: 'bar' }
13+
// Intentionally using `function()` instead of `() =>` because
14+
// the thisArg won't get passed to the find callback otherwise
15+
// https://stackoverflow.com/questions/46639131/javascript-array-prototype-find-second-argument-thisarg-not-working
16+
function testRecursive (record, idx, arr, parent) {
17+
console.log(`recurse check ${record} - `, parent)
18+
console.log(this)
19+
}
20+
records.find(testRecursive, obj)
21+
22+
function matcher (record) {
23+
this.depth = this.depth || 1 // depth tracking starts at level 1
24+
this.tracker = this.tracker || 0 // for basic sums, start counter at 0
25+
const subTotal = this.tracker + record
26+
// Found a match, don't keep searching!
27+
if (subTotal === this.target) {
28+
results.push(record)
1629
return true
1730
}
31+
// When subtotal exceeds target, return immediately and don't waste time
32+
// on more loops that won't get results
33+
if (subTotal > this.target) {
34+
return false
35+
}
36+
// If we're already at max depth, don't waste time on more loops
37+
if (this.depth >= this.maxDepth) {
38+
return false
39+
}
40+
// Check the next level down
41+
const res = records.find(matcher, {
42+
maxDepth: this.maxDepth,
43+
target: this.target,
44+
depth: this.depth + 1,
45+
tracker: this.tracker + record
46+
})
47+
// Children matched, so record this one as well
48+
if (res) {
49+
results.push(record)
50+
return true
51+
}
52+
// Nothing found with this combo, step to the next sibling
1853
return false
19-
})
20-
if (matcher) {
21-
results.push(matcher)
2254
}
2355

56+
records.find(matcher, {
57+
maxDepth: goal,
58+
target: checksum
59+
})
60+
2461
if (results.length < 2) {
2562
throw new Error('Couldn\'t find a checksum match')
2663
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy