From 07b36d66d57056d698a6e4b06329a805af222774 Mon Sep 17 00:00:00 2001 From: Bas Dado Date: Thu, 16 Dec 2021 20:06:08 +0100 Subject: [PATCH] [TASK] Solved Day 14 --- functions/src/day14.ts | 151 ++++++++++++++++++++++++++++++++++++++ functions/src/index.ts | 2 + functions/src/utils.ts | 10 ++- input/day/14-example.http | 23 ++++++ input/day/14.http | 107 +++++++++++++++++++++++++++ 5 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 functions/src/day14.ts create mode 100644 input/day/14-example.http create mode 100644 input/day/14.http diff --git a/functions/src/day14.ts b/functions/src/day14.ts new file mode 100644 index 0000000..ec375b2 --- /dev/null +++ b/functions/src/day14.ts @@ -0,0 +1,151 @@ +import Day from "./day"; +import Utils from "./utils"; + +type CharCounts = {[key: string]: bigint}; + +class Day14 implements Day { + + part1(input: string[]): number | string { + + const { orig, mapping } = Day14.parseInput(input); + + let current = orig; + for (let step = 0; step < 10; step++) { + current = this.executeStep(current, mapping); + } + + const counts: {[key: string]: number} = {}; + for (const c of current) { + if (c in counts) { + counts[c]++; + } else { + counts[c] = 1; + } + } + + + return Math.max(...Object.values(counts)) - Math.min(...Object.values(counts)); + } + + private static parseInput(input: string[]): { orig: string, mapping: Map>} { + const orig = input[0]; + + const mapping = new Map>(); + for (const line of input.slice(2)) { + + const splitIndex = line.indexOf("->"); + const from = line.substr(0, splitIndex).trim(); + const firstChar = from[0]; + const secondChar = from[1]; + const to = line.substr(splitIndex + 2).trim(); + + const existingMapping = mapping.get(firstChar); + if (existingMapping) { + existingMapping.set(secondChar, to); + } else { + mapping.set(firstChar, new Map([[secondChar, to]])); + } + } + + return { orig, mapping }; + } + + private executeStep(orig: string, mapping: Map>): string { + + let res = ""; + for (let i = 0; i < orig.length - 1; i++) { + + const char = orig[i]; + res += char; + const firstCharMatch = mapping.get(char); + if (firstCharMatch) { + const secondChar = orig[i + 1]; + const toAdd = firstCharMatch.get(secondChar); + if (toAdd) { + res += toAdd; + } + } + } + // Add the last character as it's not included in the result + res += orig[orig.length - 1]; + + return res; + } + + part2(input: string[]): number | string { + + const { orig, mapping } = Day14.parseInput(input); + + let counts: CharCounts = {}; + const cache = new Map(); + for (let i = 0; i < orig.length - 1; i++) { + + const firstChar = orig[i]; + const secondChar = orig[i + 1]; + + this.addOne(firstChar, counts); + this.mergeIntoLeft(counts, this.calculateRecursive(firstChar, secondChar, mapping, 40, cache)); + + } + this.addOne(orig[orig.length - 1], counts); + + return (Utils.bigMax(Object.values(counts)) - Utils.bigMin(Object.values(counts))).toString(); + } + + /** + * Returns the amount of added element of each type + */ + calculateRecursive(firstChar: string, secondChar: string, mappings: Map>, stepsLeft: number, cache: Map): CharCounts { + + if (stepsLeft === 0) return {}; + + const cacheKey = firstChar + secondChar + stepsLeft; + const cachedResult = cache.get(cacheKey); + if (cachedResult) return cachedResult; + + const res = {}; + + const firstCharMatch = mappings.get(firstChar); + if (firstCharMatch) { + const toAdd = firstCharMatch.get(secondChar); + if (toAdd) { + this.addOne(toAdd, res); + this.mergeIntoLeft(res, this.calculateRecursive(firstChar, toAdd, mappings, stepsLeft - 1, cache)); + this.mergeIntoLeft(res, this.calculateRecursive(toAdd, secondChar, mappings, stepsLeft - 1, cache)); + } + } + + cache.set(cacheKey, res); + return res; + + } + + mergeIntoLeft(left: CharCounts, right: CharCounts) { + + for (const rightKey in right) { + if (rightKey in left) { + left[rightKey] += right[rightKey]; + } else { + left[rightKey] = right[rightKey]; + } + } + } + + addOne(char: string, counts: CharCounts) { + + if (char in counts) { + counts[char]++; + } else { + counts[char] = 1n; + } + } + + // calculateCounts(pair: string, mappings: Map>, cache: Map>): {[key: string]: bigint} { + // + // + // + // } + +} + +export default Day14; diff --git a/functions/src/index.ts b/functions/src/index.ts index 3d1beda..72cba95 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -15,6 +15,7 @@ import Day10 from "./day10"; import Day11 from "./day11"; import Day12 from "./day12"; import Day13 from "./day13"; +import Day14 from "./day14"; // // Start writing Firebase Functions @@ -44,6 +45,7 @@ export const day = { 11: functions.region("europe-west1").https.onRequest((request, response) => { processDay(new Day11(), request, response) }), 12: functions.region("europe-west1").https.onRequest((request, response) => { processDay(new Day12(), request, response) }), 13: functions.region("europe-west1").https.onRequest((request, response) => { processDay(new Day13(), request, response) }), + 14: functions.region("europe-west1").https.onRequest((request, response) => { processDay(new Day14(), request, response) }), } diff --git a/functions/src/utils.ts b/functions/src/utils.ts index 3c81a3f..8a09f20 100644 --- a/functions/src/utils.ts +++ b/functions/src/utils.ts @@ -21,6 +21,14 @@ class Utils { return values.reduce((a, b) => a + b); } + static bigMax(values: bigint[]): bigint { + return values.reduce((a, b) => a > b ? a : b); + } + + static bigMin(values: bigint[]): bigint { + return values.reduce((a, b) => a < b ? a : b); + } + static zeroes(length: number): number[] { const res = []; @@ -31,4 +39,4 @@ class Utils { } } -export default Utils; \ No newline at end of file +export default Utils; diff --git a/input/day/14-example.http b/input/day/14-example.http new file mode 100644 index 0000000..26f590f --- /dev/null +++ b/input/day/14-example.http @@ -0,0 +1,23 @@ +POST http://localhost:5001/advent-of-code-2021-911a8/europe-west1/day-14 +Content-Type: text/plain + +NNCB + +CH -> B +HH -> N +CB -> H +NH -> C +HB -> C +HC -> B +HN -> C +NN -> C +BH -> H +NC -> B +NB -> B +BN -> B +BB -> N +BC -> B +CC -> N +CN -> C + +### diff --git a/input/day/14.http b/input/day/14.http new file mode 100644 index 0000000..77cc312 --- /dev/null +++ b/input/day/14.http @@ -0,0 +1,107 @@ +POST http://localhost:5001/advent-of-code-2021-911a8/europe-west1/day-14 +Content-Type: text/plain + +CNBPHFBOPCSPKOFNHVKV + +CS -> S +FB -> F +VK -> V +HO -> F +SO -> K +FK -> B +VS -> C +PS -> H +HH -> P +KH -> V +PV -> V +CB -> N +BB -> N +HB -> B +HV -> O +NC -> H +NF -> B +HP -> B +HK -> S +SF -> O +ON -> K +VN -> V +SB -> H +SK -> H +VH -> N +KN -> C +CC -> N +BF -> H +SN -> N +KP -> B +FO -> N +KO -> V +BP -> O +OK -> F +HC -> B +NH -> O +SP -> O +OO -> S +VC -> O +PC -> F +VB -> O +FF -> S +BS -> F +KS -> F +OV -> P +NB -> O +CF -> F +SS -> V +KV -> K +FP -> F +KC -> C +PF -> C +OS -> C +PN -> B +OP -> C +FN -> F +OF -> C +NP -> C +CK -> N +BN -> K +BO -> K +OH -> S +BH -> O +SH -> N +CH -> K +PO -> V +CN -> N +BV -> F +FV -> B +VP -> V +FS -> O +NV -> P +PH -> C +HN -> P +VV -> C +NK -> K +CO -> N +NS -> P +VO -> P +CP -> V +OC -> S +PK -> V +NN -> F +SC -> P +BK -> F +BC -> P +FH -> B +OB -> O +FC -> N +PB -> N +VF -> N +PP -> S +HS -> O +HF -> N +KK -> C +KB -> N +SV -> N +KF -> K +CV -> N +NO -> P + +###