[TASK] Solved Day 14
This commit is contained in:
151
functions/src/day14.ts
Normal file
151
functions/src/day14.ts
Normal file
@@ -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<string, Map<string, string>>} {
|
||||||
|
const orig = input[0];
|
||||||
|
|
||||||
|
const mapping = new Map<string, Map<string, string>>();
|
||||||
|
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<string, string>([[secondChar, to]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { orig, mapping };
|
||||||
|
}
|
||||||
|
|
||||||
|
private executeStep(orig: string, mapping: Map<string, Map<string, string>>): 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<string, CharCounts>();
|
||||||
|
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<string, Map<string, string>>, stepsLeft: number, cache: Map<string, CharCounts>): 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<string, Map<string, string>>, cache: Map<string, Map<number, {[key: string]: bigint}>>): {[key: string]: bigint} {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Day14;
|
||||||
@@ -15,6 +15,7 @@ import Day10 from "./day10";
|
|||||||
import Day11 from "./day11";
|
import Day11 from "./day11";
|
||||||
import Day12 from "./day12";
|
import Day12 from "./day12";
|
||||||
import Day13 from "./day13";
|
import Day13 from "./day13";
|
||||||
|
import Day14 from "./day14";
|
||||||
|
|
||||||
|
|
||||||
// // Start writing Firebase Functions
|
// // 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) }),
|
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) }),
|
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) }),
|
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) }),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ class Utils {
|
|||||||
return values.reduce((a, b) => a + b);
|
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[] {
|
static zeroes(length: number): number[] {
|
||||||
|
|
||||||
const res = [];
|
const res = [];
|
||||||
|
|||||||
23
input/day/14-example.http
Normal file
23
input/day/14-example.http
Normal file
@@ -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
|
||||||
|
|
||||||
|
###
|
||||||
107
input/day/14.http
Normal file
107
input/day/14.http
Normal file
@@ -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
|
||||||
|
|
||||||
|
###
|
||||||
Reference in New Issue
Block a user