import fs from 'node:fs' /* https://adventofcode.com/2023/day/7 Camel Cards 32T3K 765 T55J5 684 KK677 28 KTJJT 220 QQQJA 483 33332 100 2AAAA 100 77888 100 77788 100 */ function init() { const data = fs.readFileSync('input.txt', { encoding: 'utf-8' }, data => data) const games = data.split('\n') const poker = new Poker() for (let game of games) { poker.hand = game.split(' ')[0].split('') poker.bid = parseInt(game.split(' ')[1]) poker.jokerrule = true poker.play() } poker.score() } class Poker { constructor(hand, bid) { this.hand = [] this.ranking = [] this.bid = 0 this.results = 0 this.jokerrule = true this.order = [ { name: 'A', value: 14 }, { name: 'K', value: 13 }, { name: 'Q', value: 12 }, { name: 'J', value: this.jokerrule ? 1 : 11 }, { name: 'T', value: 10 }, { name: '9', value: 9 }, { name: '8', value: 8 }, { name: '7', value: 7 }, { name: '6', value: 6 }, { name: '5', value: 5 }, { name: '4', value: 4 }, { name: '3', value: 3 }, { name: '2', value: 2 } ] } getOccurences() { let j = this.jokerrule ? this.hasJokers() : 0 return this.hand.reduce((acc, curr) => { return acc[`${curr}`] ? ++acc[curr] : acc[`${curr}`] = j + 1, acc }, new Object()) } getValueOfCard(card) { return this.order.find(c => c.name === card).value } isTwoPair() { const result = this.getOccurences() return Object.values(result) .filter(numbers => numbers === 2) .length === 2 } isFullHouse() { const result = this.getOccurences() return Object.values(result).indexOf(3) > -1 && Object.values(result).indexOf(2) > -1 } hasMultiple(number) { const result = this.getOccurences() return Object.values(result).indexOf(number) > -1 } hasJokers() { const result = this.hand.reduce((acc, curr) => { return acc[`${curr}`] ? ++acc[curr] : acc[`${curr}`] = 1, acc }, new Object()) return result.hasOwnProperty('J') ? result.J : 0 } testResults() { return { 'FiveOfAKind': this.hasMultiple(5), 'FourOfAKind': this.hasMultiple(4), 'FullHouse': this.isFullHouse(), 'ThreeOfAKind': this.hasMultiple(3), 'TwoPair': this.isTwoPair(), 'OnePair': this.hasMultiple(2), 'HasJokers': this.hasJokers() } } rank() { const results = this.testResults() let rank = 0 switch (true) { case results.FiveOfAKind || results.HasJokers === 5: rank = 7_000_000_000_000 break case results.FourOfAKind: rank = 6_000_000_000_000 break case results.FullHouse: rank = 5_000_000_000_000 break case results.ThreeOfAKind: rank = 4_000_000_000_000 break case results.TwoPair: rank = 3_000_000_000_000 break case results.OnePair: rank = 2_000_000_000_000 break default: rank = 1_000_000_000_000 break } return rank } score() { const sorted_list = this.ranking.sort((a, b) => a.rank - b.rank) for (let i = 0; i < sorted_list.length; i++) { this.results += (i + 1) * sorted_list[i].bid console.log(sorted_list[i]) } console.log(this.results) } play() { let rank = this.rank() const cardValues = this.hand.map(card => this.getValueOfCard(card)) /* This did only work on the input example. Quirkier solution is to simply map card values to their string representation with padded 0 and pass that to the ranking. for (let i = 0; i < cardValues.length; i++) { let cardValue = cardValues[i] rank += cardValue * (cardValues.length - i) * 10 ** (cardValues.length - i) } */ let stringValues = cardValues.map(value => String(value).padStart(2, 0)) rank += parseInt(stringValues.join("")) this.ranking.push({ rank: rank, bid: this.bid, cards: this.hand.join(""), jokers: this.hasJokers() }) } rankPosition(position, iterator) { return (position - iterator) * 10 ** position } } init()