Skip to content

Instantly share code, notes, and snippets.

@shaun-jacks
Created December 4, 2021 08:48
Show Gist options
  • Save shaun-jacks/b41178e47fd56aca1a7c7d39664f3692 to your computer and use it in GitHub Desktop.
Save shaun-jacks/b41178e47fd56aca1a7c7d39664f3692 to your computer and use it in GitHub Desktop.
Advent of Code 2021 Day 4 Part 2 - RXJS solution
import * as fs from 'fs'
import * as path from 'path'
import * as process from 'process'
const inputDir = path.join(process.cwd(), 'day4', 'input');
import { BehaviorSubject, combineLatest, concatMap, Observable, Subject } from 'rxjs'
function parseDraws(): number[] {
const drawsString = fs.readFileSync(path.join(inputDir, 'random_numbers.txt'), 'utf-8').toString();
return drawsString.split(",").map(num => parseInt(num, 10))
}
function parseBoards(): number[][][] {
const boardsBuffer = fs.readFileSync(path.join(inputDir, 'boards.txt'), 'utf-8')
return boardsBuffer.toString()
.split('\n\n')
.map(boardString =>
boardString
.split("\n")
.map(line =>
line.split(" ")
.filter(el => el !== '')
.map(el => parseInt(el, 10))))
}
class Board {
data: number[][] = []
idx: number = -1;
bingoed = false
bingo$ = new Subject<{ draw: number; idx: number; drawId: number }>();
constructor(data: number[][], idx: number){
this.idx = idx;
this.data = data
this.bingo$.subscribe(() => {
this.bingoed = true;
})
}
mark(draw: number, drawId: number) {
const rows = this.data.length
const cols = this.data[0].length
const location = { row: 0, col: 0 }
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
if(this.data[row][col] === draw) {
this.data[row][col] = -1
location.row = row
location.col = col
this.checkIfBingo(draw, location, drawId);
}
}
}
}
checkIfBingo(draw: number, location: { row: number; col: number }, drawId: number) {
if (this.data[location.row].every(col => col === -1)) {
this.bingo$.next({ idx: this.idx, draw, drawId })
}
if (this.data.every(row => row[location.col] === -1)) {
this.bingo$.next({ idx: this.idx, draw, drawId })
}
}
getUnmarkedSum() {
return this.data.reduce((acc, row) => acc +
row.reduce((acc, num) => num === -1 ? acc : acc + num,0),
0)
}
}
class BingoGame {
boards: Board[];
draw$ = new Subject<number>()
winners: {
boardId: number;
draw: number;
}[] = []
drawId = 0;
constructor(boards: Board[]) {
this.boards = boards;
this.draw$.subscribe(draw => {
this.boards.forEach((board, i) => {
if (!board.bingoed) {
board.mark(draw, this.drawId)
this.drawId += 1
}
})
})
combineLatest(this.boards.map(board => board.bingo$)).subscribe(winners => {
let maxDrawid = winners.reduce((acc, winner) => acc > winner.drawId ? acc : winner.drawId, 0)
const lastWinner = winners.find(winner => winner.drawId === maxDrawid)
console.log(this.boards[lastWinner!.idx].getUnmarkedSum() * lastWinner!.draw)
})
}
draw(draw:number) {
this.draw$.next(draw)
}
}
function main() {
const draws = parseDraws()
const parsedBoards = parseBoards()
const boards = parsedBoards.map((board, i) => new Board(board, i))
const game = new BingoGame(boards)
for (const draw of draws) {
game.draw(draw)
}
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment