-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
271 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
interface Requirement { | ||
product: string; | ||
quantity: number; | ||
} | ||
|
||
interface Reaction { | ||
quantity: number; | ||
requirements: Requirement[]; | ||
} | ||
|
||
const parseReaction = (input: string): Record<string, Reaction> => { | ||
const [requirementList, product] = input.split(' => '); | ||
const [quantity, productName] = product.split(' '); | ||
const requirements = requirementList.split(', ').map((r) => ({ | ||
product: r.split(' ')[1], | ||
quantity: parseInt(r.split(' ')[0]), | ||
})); | ||
|
||
return { | ||
[productName]: { | ||
quantity: parseInt(quantity), | ||
requirements, | ||
}, | ||
}; | ||
}; | ||
|
||
export const parseReactions = (input: string): Record<string, Reaction> => { | ||
const reactions = input.split('\n').map(parseReaction); | ||
return reactions.reduce((prev, curr) => Object.assign(curr, prev), {}); | ||
}; | ||
|
||
export const getOreCount = ( | ||
reactions: Record<string, Reaction>, | ||
fuelRequired = 1 | ||
): number => { | ||
const stockpile: Record<string, number> = Object.keys(reactions).reduce( | ||
(prev, curr) => ({ ...prev, [curr]: 0 }), | ||
{} | ||
); | ||
|
||
const requirements = reactions['FUEL'].requirements.map((r) => ({ | ||
...r, | ||
quantity: r.quantity * fuelRequired, | ||
})); | ||
|
||
let oreCount = 0; | ||
|
||
while (requirements.length) { | ||
const requirement = requirements.pop() as Requirement; | ||
const product = requirement.product; | ||
const stock = stockpile[product]; | ||
let quantity = requirement.quantity; | ||
|
||
// Take fully from stockpile. | ||
if (quantity <= (stockpile[product] ?? 0)) { | ||
stockpile[product] -= quantity; | ||
continue; | ||
} | ||
|
||
// Take partially from stockpile. | ||
quantity -= stock; | ||
delete stockpile[product]; | ||
|
||
// Calculate number of reactions required. | ||
const productProduced = reactions[product].quantity; | ||
const reactionCount = Math.ceil(quantity / productProduced); | ||
|
||
// Leftovers. | ||
const leftover = productProduced * reactionCount - quantity; | ||
stockpile[product] = (stockpile[product] ?? 0) + leftover; | ||
|
||
for (const reactionProduct of reactions[product].requirements) { | ||
if (reactionProduct.product === 'ORE') { | ||
oreCount += reactionCount * reactionProduct.quantity; | ||
} else { | ||
let requirementUpdated = false; | ||
|
||
// Update requirement if exists. | ||
for (const current of requirements) { | ||
if (current.product === reactionProduct.product) { | ||
current.quantity += reactionCount * reactionProduct.quantity; | ||
requirementUpdated = true; | ||
break; | ||
} | ||
} | ||
|
||
// Create new requirement. | ||
if (!requirementUpdated) { | ||
requirements.push({ | ||
...reactionProduct, | ||
quantity: reactionProduct.quantity * reactionCount, | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return oreCount; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { day14p1 } from './p1'; | ||
import { day14p2 } from './p2'; | ||
import { getPuzzle } from '@utilities/getPuzzle'; | ||
|
||
const { example, example2, example3, input } = getPuzzle(__dirname); | ||
|
||
describe('Day 14 Puzzle', () => { | ||
test('Part 1 Example', () => { | ||
expect(day14p1(example)).toBe(13312); | ||
}); | ||
|
||
test('Part 1 Example 2', () => { | ||
expect(day14p1(example2)).toBe(180697); | ||
}); | ||
|
||
test('Part 1 Example 3', () => { | ||
expect(day14p1(example3)).toBe(2_210_736); | ||
}); | ||
|
||
test('Part 1 Input', () => { | ||
expect(day14p1(input)).toBe(397771); | ||
}); | ||
|
||
test('Part 2 Example', () => { | ||
expect(day14p2(example)).toBe(82_892_753); | ||
}); | ||
|
||
test('Part 2 Example 2', () => { | ||
expect(day14p2(example2)).toBe(5_586_022); | ||
}); | ||
|
||
test('Part 2 Example 3', () => { | ||
expect(day14p2(example3)).toBe(460664); | ||
}); | ||
|
||
test('Part 2 Input', () => { | ||
expect(day14p2(input)).toBe(3_126_714); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
157 ORE => 5 NZVS | ||
165 ORE => 6 DCFZ | ||
44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL | ||
12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ | ||
179 ORE => 7 PSHF | ||
177 ORE => 5 HKGWZ | ||
7 DCFZ, 7 PSHF => 2 XJWVT | ||
165 ORE => 2 GPVTF | ||
3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG | ||
17 NVRVD, 3 JNWZP => 8 VPVL | ||
53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL | ||
22 VJHF, 37 MNCFX => 5 FWMGM | ||
139 ORE => 4 NVRVD | ||
144 ORE => 7 JNWZP | ||
5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC | ||
5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV | ||
145 ORE => 6 MNCFX | ||
1 NVRVD => 8 CXFTF | ||
1 VJHF, 6 MNCFX => 4 RFSQX | ||
176 ORE => 6 VJHF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
171 ORE => 8 CNZTR | ||
7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL | ||
114 ORE => 4 BHXH | ||
14 VRPVC => 6 BMBT | ||
6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL | ||
6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT | ||
15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW | ||
13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW | ||
5 BMBT => 4 WPTQ | ||
189 ORE => 9 KTJDG | ||
1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP | ||
12 VRPVC, 27 CNZTR => 2 XDBXC | ||
15 KTJDG, 12 BHXH => 5 XCVML | ||
3 BHXH, 2 VRPVC => 7 MZWV | ||
121 ORE => 7 VRPVC | ||
7 XCVML => 6 RJRHP | ||
5 BHXH, 4 VRPVC => 5 LTCX |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
8 LHFV => 3 PMVMQ | ||
2 ZXNM, 1 PSVLS, 4 GRDNT, 26 GLZH, 3 VHJX, 16 BGPF, 1 LHVTN => 4 BTQL | ||
10 NKHSG, 20 FCPC, 11 GRDNT => 5 HDJB | ||
6 WPZN, 1 LHFV => 7 BGPF | ||
1 WDXT, 1 PLCNZ => 3 QHFKR | ||
12 LCHZ => 1 TPXCK | ||
11 LSNG => 4 XFGH | ||
195 ORE => 4 GRNC | ||
8 XFGQ => 1 GRDNT | ||
1 FBRG => 5 LCHZ | ||
7 XZBJ, 8 RSZF, 9 SVDX => 9 LWDP | ||
20 WDXT => 5 RQFRT | ||
1 LXQWG, 1 GLZH => 6 SDLJ | ||
4 XFGH => 1 GCZLZ | ||
1 WPZN => 1 FBRG | ||
19 XZBJ => 5 WXGV | ||
1 GDXC => 6 WDXT | ||
1 WXGV, 1 NKHSG, 2 LWDP => 5 FCNPB | ||
4 LWDP, 5 BGPF => 9 KLRB | ||
1 GMRN => 4 GLZH | ||
1 RQFRT => 5 SVDX | ||
2 HWKG => 7 LHFV | ||
2 LCHZ, 13 JTJT, 10 TPXCK => 3 RSZF | ||
29 MZTVH => 6 TSGR | ||
9 NRFLK, 1 SVDX => 5 NKHSG | ||
123 ORE => 9 GDXC | ||
1 PZPBV, 21 PMVMQ, 1 GCZLZ => 8 SKZGB | ||
3 GRNC, 5 GDXC => 8 QZVM | ||
6 VTDQ, 13 TCQW, 3 FCNPB, 48 PSVLS, 3 RLNF, 73 BTQL, 5 MHRVG, 26 BGPF, 26 HDJB, 5 XFGQ, 6 HTFL => 1 FUEL | ||
5 QZVM, 2 JTJT => 1 PXKHG | ||
3 LSNG, 1 PMVMQ => 8 VTDQ | ||
31 XFGH => 1 FCPC | ||
9 PSVLS => 8 FWGTF | ||
1 GRNC => 3 WPZN | ||
16 JBXDX, 4 GRNC => 6 HWKG | ||
1 SKZGB, 5 RSZF => 4 XZBJ | ||
134 ORE => 9 CTDRZ | ||
1 SVDX, 2 TPXCK => 7 JTJT | ||
6 RQFRT, 4 KBCW => 3 BGNLR | ||
12 KLRB, 12 LHFV => 4 HTFL | ||
2 GMRN => 6 XFGQ | ||
16 WNSW, 12 SKZGB => 8 LXQWG | ||
2 NRFLK, 2 CTDRZ => 9 JBXDX | ||
1 PZPBV => 8 RLNF | ||
2 JTJT, 5 GCZLZ => 3 WNSW | ||
5 WXGV, 2 LCHZ => 2 SCDS | ||
1 QHFKR => 3 GMRN | ||
10 JTJT, 2 HRCG => 8 KBCW | ||
7 HWKG => 4 PSVLS | ||
7 WNSW, 1 PXKHG, 3 BGNLR => 9 MZTVH | ||
15 TPXCK, 11 LHFV => 5 HRCG | ||
1 LSNG, 1 HWKG => 3 PZPBV | ||
7 BGPF => 9 PLCNZ | ||
1 ZGWT => 6 ZXNM | ||
26 NKHSG, 1 LHFV, 2 JTJT, 26 WXGV, 6 SDLJ, 1 KLRB, 1 TSGR => 8 TCQW | ||
154 ORE => 4 NRFLK | ||
1 GMRN => 3 VHJX | ||
5 QZVM, 3 GDXC => 7 LSNG | ||
5 WNSW => 5 ZGWT | ||
6 QHFKR, 8 PZPBV, 10 FBRG, 13 FWGTF, 1 LHVTN, 4 SCDS, 8 VHJX, 7 TSGR => 6 MHRVG | ||
12 GLZH => 5 LHVTN |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { getPuzzle } from '@utilities/getPuzzle'; | ||
import { run } from '@utilities/run'; | ||
import { getOreCount, parseReactions } from './day14.helper'; | ||
|
||
export const day14p1 = (input: string) => { | ||
const reactions = parseReactions(input); | ||
return getOreCount(reactions); | ||
}; | ||
|
||
const input = getPuzzle(__dirname).input; | ||
run(() => day14p1(input)); // 397771 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { getPuzzle } from '@utilities/getPuzzle'; | ||
import { run } from '@utilities/run'; | ||
import { getOreCount, parseReactions } from './day14.helper'; | ||
|
||
export const day14p2 = (input: string) => { | ||
const reactions = parseReactions(input); | ||
const singleFuelCost = getOreCount(reactions); | ||
const oreCount = 1_000_000_000_000; | ||
const lowerBound = Math.ceil(oreCount / singleFuelCost); | ||
|
||
let fuelCount = lowerBound; | ||
let remaining = oreCount; | ||
|
||
while (remaining > singleFuelCost) { | ||
remaining = oreCount - getOreCount(reactions, fuelCount); | ||
fuelCount += Math.floor(remaining / singleFuelCost); | ||
} | ||
|
||
return fuelCount; | ||
}; | ||
|
||
const input = getPuzzle(__dirname).input; | ||
run(() => day14p2(input)); // 3126714 |