Are you participating in the Advent of code this year?
If you don't know what the advent of code is, it's a website where you'll find a daily challenge (every day it gets harder). It's a really fun event, you should participate!
I try to solve the exercises using either JavaScript or TypeScript and will share my solutions daily (with one day delay so no one can cheat!). I only share the solution for the second part.
Interesting day! Nothing too complex, no hidden tricks, completely doable step by step. Fun fact, in order to complete the challenge I created a test file with the description of the game (the sample), and made my code return logs instead of the result. Once I had the exact same logs as the sample, I ran the code, and voilà, the solution appeared!
Here is my solution for day #22:
export class RecursiveGame {
player1: number[]
player2: number[]
logs: string[] = []
played = new Set<string>()
constructor(deck1: number[], deck2: number[]) {
this.player1 = deck1
this.player2 = deck2
}
isFinished(): boolean {
return this.player1.length === 0 || this.player2.length === 0
}
playAll() {
while (!this.isFinished()) {
this.playTurn()
}
}
playTurn() {
// if already happened, game end for player 1
const key = `${this.player1}|${this.player2}`
if (this.played.has(key)) {
this.player2.length = 0
return
}
this.played.add(key)
const cardPlayer1 = this.player1.shift()
const cardPlayer2 = this.player2.shift()
if (!cardPlayer1 || !cardPlayer2) throw new Error('game already finished')
let winner: 1 | 2 | null
if (this.player1.length >= cardPlayer1 && this.player2.length >= cardPlayer2) {
const subGame = new RecursiveGame(this.player1.slice(0, cardPlayer1), this.player2.slice(0, cardPlayer2))
subGame.playAll()
winner = subGame.getWinner()
} else {
if (cardPlayer1 > cardPlayer2) {
winner = 1
} else {
winner = 2
}
}
if (winner === null) throw new Error('winner cant be found')
if (winner === 1) {
this.player1.push(cardPlayer1, cardPlayer2)
} else {
this.player2.push(cardPlayer2, cardPlayer1)
}
}
getWinner(): 1 | 2 {
if (this.player1.length === 0) return 2
if (this.player2.length === 0) return 1
throw new Error('not over yet')
}
getWinnerDeck(): number[] {
const winner = [this.player1, this.player2].find((deck) => deck.length !== 0)
if (!winner) throw new Error('Game not finished yet')
return winner
}
}
function resolve(input: string) {
const [deck1, deck2] = input.split('\n\n').map((deck) => {
return deck
.split('\n')
.slice(1)
.map((card) => parseInt(card, 10))
})
const game = new RecursiveGame(deck1, deck2)
game.playAll()
console.log(
game.getWinnerDeck().reduce((acc, card, index, deck) => {
return acc + (deck.length - index) * card
}, 0),
)
}
resolve(input)
Feel free to share your solution in the comments!
Photo by Markus Spiske on Unsplash
Top comments (0)