-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path04.ts
61 lines (53 loc) · 1.84 KB
/
04.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { M } from "../../common/math.ts";
import { S } from "../../common/string.ts";
type Room = {
name: string;
sector: number;
checksum: string;
};
function parseRoom(line: string): Room {
const match = line.match(/(^\D+)(\d+)\[([a-z]{5})\]/);
return {
name: match?.[1] ?? "",
sector: parseInt(match?.[2] ?? ""),
checksum: match?.[3] ?? "",
};
}
// Sort character counts, breaking ties alphabetically
const sortCharEntries = (
[aChar, aNum]: [string, number],
[bChar, bNum]: [string, number],
) => aNum === bNum ? aChar.localeCompare(bChar) : bNum - aNum;
// Get Cesar Cipher shift function (i.e. 2 => "A" => "C")
const getCesarCipherShift = (shift: number) => (char: string): string =>
String.fromCharCode(((char.charCodeAt(0) - 97 + shift) % 26) + 97);
function decryptRoom(room: Room): Room {
const shift = getCesarCipherShift(room.sector);
return {
...room,
name: room.name.split("").map(shift).join(""),
};
}
function validRoom(room: Room): boolean {
const letters = room.name.replaceAll("-", "");
const charCounts = S.charCounts(letters);
const sorted = Object.entries(charCounts).toSorted(sortCharEntries);
const checksum = sorted.slice(0, 5).map(([c]) => c).join("");
return room.checksum === checksum;
}
// Find the sum of room sectors
export function part1(input: string) {
const rooms = input.split("\n").map(parseRoom);
const valid = rooms.filter(validRoom);
const sectorSum = M.sum(valid.map((r) => r.sector));
return sectorSum;
}
// Find sector of northpole object storage room
export function part2(input: string) {
const rooms = input.split("\n").map(parseRoom);
const valid = rooms.filter(validRoom);
const decrypted = valid.map(decryptRoom);
const target = decrypted.find((r) => r.name.includes("northpole"));
if (!target) throw new Error("Room not found");
return target.sector;
}