mirror of
https://github.com/peter-tanner/advent-of-code-2023.git
synced 2024-11-30 14:00:16 +08:00
Day 7 solutions ☀☀☀
This commit is contained in:
parent
900d67e6ff
commit
4f57e185fe
27
day_7/compare.ts
Normal file
27
day_7/compare.ts
Normal 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
15
day_7/parser.ts
Normal 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
65
day_7/part_1.ts
Normal 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
82
day_7/part_2.ts
Normal 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)
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user