Public
Edited
Dec 8, 2023
Insert cell
Insert cell
Insert cell
function parse(input, jack = "b") {
return input.split("\n").map((line) => {
const [hand, bid] = line.split(/\s+/);
return {
hand: hand
.replaceAll("A", "e")
.replaceAll("K", "d")
.replaceAll("Q", "c")
.replaceAll("J", jack)
.replaceAll("T", "a"),
bid: Number(bid)
};
});
}
Insert cell
Insert cell
function type1(hand) {
// Find the number of cards of each type
const fTable = new Map();
[...hand].forEach((card) => AOC.addToFreqTable(fTable, card));
const counts = [...fTable.values()];

// Type of hand can largely be determined by testing for the highest frequency in max to min order.
if (counts.includes(5)) {
return 7; // Five of a kind
}
if (counts.includes(4)) {
return 6; // Four of a kind
}
if (counts.length === 2) {
return 5; // Full house
}
if (counts.includes(3)) {
return 4; // Three of a kind
}
if (counts.filter((n) => n === 2).length === 2) {
return 3; // Two pairs
}
if (counts.length === 4) {
return 2; // One pair
}
return 1; // High card
}
Insert cell
Insert cell
function cardSort(type, hand1, hand2) {
const [h1, h2] = [hand1.hand, hand2.hand];
const [t1, t2] = [type(h1), type(h2)];
return t1 === t2 ? (h1 < h2 ? -1 : h1 > h2 ? 1 : 0) : t1 - t2;
}
Insert cell
Insert cell
function part1(input) {
return AOC.sum(
parse(puzzleInput)
.sort(AOC.partial(cardSort, type1))
.map(({ h, bid }, i) => bid * (i + 1))
);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function type2(hand) {
// If there are no Jokers in hand, this behaves as part1.
const numJokers = (hand.match(/0/g) || []).length;
if (numJokers === 0) {
return type1(hand);
}

// Find the number of cards of each type excluding Jokers
const handWithoutJokers = hand.replace(/0/g, "");
const fTable = new Map();
[...handWithoutJokers].forEach((card) => AOC.addToFreqTable(fTable, card));
const counts = [...fTable.values()];

// Use the maximum count of any card including use of Jokers to calculate the hand type
switch (Math.max(...counts, 0) + numJokers) {
case 5:
return 7; // Five of a kind
case 4:
return 6; // Four of a kind
case 3:
return counts.length <= 3 - numJokers ? 5 : 4; // Full house or Three of a kind
default:
return 2; // Pair
}
}
Insert cell
Insert cell
function part2(input) {
return AOC.sum(
parse(puzzleInput, "0")
.sort(AOC.partial(cardSort, type2))
.map(({ h, bid }, i) => bid * (i + 1))
);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more