Day 7 solutions ☀☀☀

This commit is contained in:
Peter 2023-12-08 03:20:36 +08:00
parent 900d67e6ff
commit 4f57e185fe
4 changed files with 189 additions and 0 deletions

27
day_7/compare.ts Normal file
View File

@ -0,0 +1,27 @@
export enum RANK {
FIVE_OF_A_KIND,
FOUR_OF_A_KIND,
FULL_HOUSE,
THREE_OF_A_KIND,
TWO_PAIR,
ONE_PAIR,
HIGH_CARD,
}
export const cmp_by_card = (
hand1: string,
hand2: string,
strength_order: Map<string, number>
) => {
for (var i = 0; i < hand1.length; i++) {
const s1 = strength_order.get(hand1[i]);
const s2 = strength_order.get(hand2[i]);
if (undefined === s1 || undefined === s2) {
console.error("ERROR", i, hand1[i], hand2[i]);
return 0;
}
if (s1 > s2) return -1;
if (s1 < s2) return 1;
}
return 0;
};

15
day_7/parser.ts Normal file
View File

@ -0,0 +1,15 @@
import * as fs from "fs";
export interface HandBid {
hand: string;
bid: number;
}
export const read_file = (): HandBid[] =>
fs
.readFileSync("input", "ascii")
.split("\n")
.map((line) => {
const [hand, bid] = line.split(" ");
return { hand: hand, bid: Number.parseInt(bid) };
});

65
day_7/part_1.ts Normal file
View File

@ -0,0 +1,65 @@
import { RANK, cmp_by_card } from "./compare";
import { HandBid, read_file } from "./parser";
const rank_hand = (hand: string) => {
const cards = hand.split("");
const card_count = cards.reduce((count, char) => {
const c = count.get(char);
return c ? count.set(char, c + 1) : count.set(char, 1);
}, new Map<string, number>());
const unique_cards = Array.from(card_count.keys());
if (unique_cards.length === 1) return RANK.FIVE_OF_A_KIND;
if (unique_cards.length === 4) return RANK.ONE_PAIR;
if (unique_cards.length === 5) return RANK.HIGH_CARD;
if (
unique_cards.length === 2 &&
[1, 4].includes(card_count.get(unique_cards[0]) || 0)
)
return RANK.FOUR_OF_A_KIND;
if (
unique_cards.length === 2 &&
[2, 3].includes(card_count.get(unique_cards[0]) || 0)
)
return RANK.FULL_HOUSE;
if (
unique_cards.length === 3 &&
unique_cards.reduce((c, card) => card_count.get(card) === 3 || c, false)
)
return RANK.THREE_OF_A_KIND;
return RANK.TWO_PAIR;
};
const STRENGTH = new Map<string, number>(
Object.entries({
A: 0,
K: 1,
Q: 2,
J: 3,
T: 4,
"9": 5,
"8": 6,
"7": 7,
"6": 8,
"5": 9,
"4": 10,
"3": 11,
"2": 12,
})
);
const cmp_hand = (hand_bid1: HandBid, hand_bid2: HandBid) => {
if (rank_hand(hand_bid1.hand) > rank_hand(hand_bid2.hand)) return -1;
if (rank_hand(hand_bid1.hand) < rank_hand(hand_bid2.hand)) return 1;
return cmp_by_card(hand_bid1.hand, hand_bid2.hand, STRENGTH);
};
const hand_bids = read_file();
console.log(
hand_bids
.sort(cmp_hand)
.reduce((sum, hand_bid, i) => sum + hand_bid.bid * (1 + i), 0)
);

82
day_7/part_2.ts Normal file
View File

@ -0,0 +1,82 @@
import { RANK, cmp_by_card } from "./compare";
import { HandBid, read_file } from "./parser";
const rank_hand = (hand: string) => {
const cards = hand.split("");
const card_count = cards.reduce((count, char) => {
const c = count.get(char);
return c ? count.set(char, c + 1) : count.set(char, 1);
}, new Map<string, number>(Object.entries({ J: 0 })));
// It is always the most optimal choice to greedily substitute J for the card with the most occurrences.
var max_card = "?";
Array.from(card_count.keys()).forEach((card) => {
if (
card !== "J" &&
(card_count.get(card) || 0) > (card_count.get(max_card) || 0)
) {
max_card = card;
}
});
card_count.set(
max_card,
(card_count.get(max_card) || 0) + (card_count.get("J") || 0)
);
card_count.delete("J");
const unique_cards = Array.from(card_count.keys()).filter(
(card) => card !== "J"
);
if (unique_cards.length === 1) return RANK.FIVE_OF_A_KIND;
if (unique_cards.length === 4) return RANK.ONE_PAIR;
if (unique_cards.length === 5) return RANK.HIGH_CARD;
if (
unique_cards.length === 2 &&
[1, 4].includes(card_count.get(unique_cards[0]) || 0)
)
return RANK.FOUR_OF_A_KIND;
if (
unique_cards.length === 2 &&
[2, 3].includes(card_count.get(unique_cards[0]) || 0)
)
return RANK.FULL_HOUSE;
if (
unique_cards.length === 3 &&
unique_cards.reduce((c, card) => card_count.get(card) === 3 || c, false)
)
return RANK.THREE_OF_A_KIND;
return RANK.TWO_PAIR;
};
const STRENGTH = new Map<string, number>(
Object.entries({
A: 0,
K: 1,
Q: 2,
T: 3,
"9": 4,
"8": 5,
"7": 6,
"6": 7,
"5": 8,
"4": 9,
"3": 10,
"2": 11,
J: 12,
})
);
const cmp_hand = (hand_bid1: HandBid, hand_bid2: HandBid) => {
if (rank_hand(hand_bid1.hand) > rank_hand(hand_bid2.hand)) return -1;
if (rank_hand(hand_bid1.hand) < rank_hand(hand_bid2.hand)) return 1;
return cmp_by_card(hand_bid1.hand, hand_bid2.hand, STRENGTH);
};
console.log(
read_file()
.sort(cmp_hand)
.reduce((sum, hand_bid, i) => sum + hand_bid.bid * (1 + i), 0)
);