type CardHand = string;

const BidOfHand = ["2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"];
const StrengthOfHand = {
    "2": 0,
    "3": 1,
    "4": 2,
    "5": 3,
    "6": 4,
    "7": 5,
    "8": 6,
    "9": 7,
    "T": 8,
    "J": 9,
    "Q": 10,
    "K": 11,
    "A": 12
}

enum HandType {
    FiveOfAKind = 6,
    FourOfAKind = 5,
    FullHouse = 4,
    ThreeOfAKind = 3,
    TwoPair = 2,
    OnePair = 1,
    HighCard = 0
}

function getTypeOfHand(hand: CardHand): HandType{
    const cards = hand.split("");
    const counter = new Array(13).fill(0);
    for (let i = 0; i < cards.length; i++){
        const card = cards[i];
        if (!(card in StrengthOfHand)) {
            throw new Error(`invalid card: ${card}`);
        }
        const index = StrengthOfHand[card as keyof typeof StrengthOfHand];
        counter[index] += 1;
    }
    const sorted = counter.sort((a, b) => b - a);
    // five of a kind
    if (sorted[0] === 5) return HandType.FiveOfAKind;
    // four of a kind
    if (sorted[0] === 4) return HandType.FourOfAKind;
    // full house
    if (sorted[0] === 3 && sorted[1] === 2) return HandType.FullHouse;
    // three of a kind
    if (sorted[0] === 3) return HandType.ThreeOfAKind;
    // two pair
    if (sorted[0] === 2 && sorted[1] === 2) return HandType.TwoPair;
    // one pair
    if (sorted[0] === 2) return HandType.OnePair;
    // high card
    return HandType.HighCard;
}

function handCompare(a: CardHand, b: CardHand) {
    const aType = getTypeOfHand(a);
    const bType = getTypeOfHand(b);
    if (aType < bType) return -1;
    if (aType > bType) return 1;
    
    // aType === bType
    
    for (let i = 0; i < a.length; i++){
        const aStrength = StrengthOfHand[a[i] as keyof typeof StrengthOfHand];
        const bStrength = StrengthOfHand[b[i] as keyof typeof StrengthOfHand];
        if (aStrength < bStrength) return -1;
        if (aStrength > bStrength) return 1;
    }
    // aStrength === bStrength
    return 0;
}

const input = await Deno.readTextFile("example.txt");

const lines = input.split("\n").map(x => x.trim()).filter(x => x.length > 0)
const data = lines.map(x => {
    const [hands, bid] = x.split(" ");
    return {hands, bid:parseInt(bid)};
});

data.sort((a, b) => handCompare(a.hands, b.hands));

console.log(data)

const sum = data.map((x,i)=> x.bid * i).reduce((a, b) => a + b, 0);
console.log(sum);