Created
December 4, 2021 08:48
-
-
Save shaun-jacks/b41178e47fd56aca1a7c7d39664f3692 to your computer and use it in GitHub Desktop.
Advent of Code 2021 Day 4 Part 2 - RXJS solution
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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