Skip to content

Commit 17a60e2

Browse files
perf(2020-day-07): simplify recursion logic
Solves part 2 Logic was overly complicated. Refactoring to pass the multiplier through each level made the recursion much simpler (multiplying can be done before returning to parent). Reduces code, and fixes the bug that was showing up in real data but not showing up with test data.
1 parent 90f656e commit 17a60e2

File tree

1 file changed

+25
-62
lines changed

1 file changed

+25
-62
lines changed

2020/day-7/bagRules.js

Lines changed: 25 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -53,30 +53,27 @@ const findAllowedOuter = (rules, color) => {
5353
return allowed
5454
}
5555

56-
const countInner = (rules, color) => {
56+
const countInner = (rules, color, count = 1) => {
5757
// const children = {}
5858
/** checks if rule matches color */
5959
const matchesColor = ({ outer }) => outer === color
60-
/** checks if an object has keys */
61-
// const hasKeys = (obj) => (Object.keys(obj).length > 0)
60+
/** checks if rule has child bags */
61+
const hasChildren = ({ inner }) => (inner) && inner.length > 0
62+
63+
const getChildrenBags = ({ inner }, multiplier = 1) => {
64+
const res = {}
65+
// Convert into structured list
66+
inner.forEach(({ color, count }) => {
67+
res[color] = count * multiplier
68+
})
69+
return res
70+
}
6271
/** type-safe addition */
6372
const add = (a, b) => {
6473
a = (typeof a === 'number') ? a : 0
6574
b = (typeof b === 'number') ? b : 0
6675
return a + b
6776
}
68-
/** type-safe multiplication */
69-
const multiply = (a, b) => {
70-
a = (typeof a === 'number') ? a : 1
71-
b = (typeof b === 'number') ? b : 1
72-
return a * b
73-
}
74-
/** multiply all keys in an object by a value */
75-
const multiplyObjKeys = (object, value) => {
76-
for (const key in object) {
77-
object[key] = multiply(object[key], value)
78-
}
79-
}
8077
/** combine two objects using the specified operator method for collsions */
8178
const combineObjects = (a = {}, b = {}, operator) => {
8279
const c = {}
@@ -90,55 +87,21 @@ const countInner = (rules, color) => {
9087
console.debug('matching', color)
9188

9289
// Loop through the rules to find first level children
93-
const children = rules.filter(matchesColor) // find all matches for the color
94-
.filter(({ inner }) => (inner) && inner.length > 0) // filter for matches that have children
95-
.map(({ inner }) => {
96-
const res = {}
97-
// Convert into structured list
98-
inner.forEach(({ color, count }) => {
99-
res[color] = count
100-
})
101-
return res
102-
})
103-
.reduce((res, match) => {
104-
return combineObjects(res, match, add)
105-
}, {})
90+
return rules
91+
.filter(matchesColor) // find all matches for the color
92+
.filter(hasChildren) // filter for matches that have children
93+
.map(rule => getChildrenBags(rule, count)) // get the counts from the children
94+
.reduce((res, children) => {
95+
// Add everything back together
96+
const childrensChildren = Object.entries(children)
97+
.map(([key, value]) => countInner(rules, key, value))
98+
.reduce((r, c) => combineObjects(r, c, add), {})
10699

107-
console.debug('First level match found', children)
108-
console.debug(`check the children of ${Object.keys(children).length} immediate child bags recursively`)
109-
// Take the list immediate children, and recursively tally the children in each
110-
const childResults = Object.entries(children)
111-
.map(([color, count]) => {
112-
// find the child's children
113-
const childChildren = countInner(rules, color)
114-
// multilply each of the child's children by the child amount
115-
multiplyObjKeys(childChildren, count)
116-
return childChildren
117-
})
118-
// .filter(hasKeys) // Drop empties
119-
.reduce((res, matches, idx) => {
120-
console.debug(matches)
121-
console.debug(
122-
'----------------------\n',
123-
`${idx}: child result ${color}:`, '\n',
124-
combineObjects(res, matches, add), '\n',
125-
'----------------------\n'
126-
)
127-
return combineObjects(res, matches, add)
128-
}, {})
100+
res = combineObjects(res, children, add)
101+
res = combineObjects(res, childrensChildren, add)
129102

130-
console.debug(
131-
'---------------------\n',
132-
'results with children\n',
133-
'children:', children, '\n',
134-
'childResults:', childResults, '\n',
135-
'combined:',
136-
combineObjects(children, childResults, multiply), '\n',
137-
'---------------------\n\n'
138-
)
139-
140-
// Multiply the child results with the current level
141-
return combineObjects(children, childResults, multiply)
103+
return res
104+
}, {})
142105
}
143106

144107
module.exports = {

0 commit comments

Comments
 (0)