Skip to content

Commit 7f8a13f

Browse files
feat(2021-day-04): find the first board with a bingo
1 parent ac5fe27 commit 7f8a13f

File tree

6 files changed

+888
-1
lines changed

6 files changed

+888
-1
lines changed

2021/day-04/bingo.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const boards = []
2+
3+
const callNumber = (called) => {
4+
for (let x = 0; x < boards.length; x++) {
5+
markBoard(x, called)
6+
if (checkWinner(x) === 'winner') {
7+
console.debug(`Board ${x} is the winner`)
8+
return x
9+
}
10+
}
11+
}
12+
13+
const markBoard = (board, called) => {
14+
for (let x = 0; x < 5; x++) {
15+
for (let y = 0; y < 5; y++) {
16+
if (board[x][y] === called) {
17+
board[x][y] = 'x'
18+
// TODO: speed up break the loop, since only one of a number on each board
19+
// x = 6
20+
// y = 6
21+
}
22+
}
23+
}
24+
return board
25+
}
26+
27+
const checkWinner = (board) => {
28+
// TODO: This can be sped up by doing a check for at least 5 "x" before
29+
// validating horizontal/vertical explicitly. Another speedup would be to
30+
// zig-zag check parse through the array and break/resolve when there
31+
// isn't a match instead of checking all columns then checking all rows
32+
33+
// Look for a horizontal bingo
34+
for (let y = 0; y < 5; y++) {
35+
if (board[y].filter((val) => val === 'x').length === 5) {
36+
return 'winner'
37+
}
38+
}
39+
40+
// Look for a vertical bingo
41+
let match = 0
42+
for (let x = 0; x < 5; x++) {
43+
for (let y = 0; y < 5; y++) {
44+
if (board[y][x] === 'x') {
45+
match++
46+
47+
if (match === 5) {
48+
return 'winner'
49+
}
50+
}
51+
}
52+
match = 0 // reset so next row has a clean count
53+
}
54+
55+
// No bingo
56+
return 'no win'
57+
}
58+
59+
const scoreBoard = (board) => {
60+
return board.reduce((tally, row) => {
61+
tally += row.reduce((colTally, cell) => {
62+
if (cell !== 'x') {
63+
colTally += cell
64+
}
65+
return colTally
66+
}, 0)
67+
return tally
68+
}, 0)
69+
}
70+
71+
module.exports = {
72+
callNumber,
73+
scoreBoard,
74+
checkWinner,
75+
markBoard
76+
}

2021/day-04/bingo.test.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/* eslint-env mocha */
2+
const { expect } = require('chai')
3+
const { callNumber, scoreBoard, checkWinner, markBoard } = require('./bingo')
4+
const { parseData } = require('../../2018/inputParser')
5+
6+
const testData = `
7+
7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
8+
9+
22 13 17 11 0
10+
8 2 23 4 24
11+
21 9 14 16 7
12+
6 10 3 18 5
13+
1 12 20 15 19
14+
15+
3 15 0 2 22
16+
9 18 13 17 5
17+
19 8 7 25 23
18+
20 11 10 24 4
19+
14 21 16 12 6
20+
21+
14 21 17 24 4
22+
10 16 15 9 19
23+
18 8 23 26 20
24+
22 11 13 6 5
25+
2 0 12 3 7
26+
`
27+
// Deep copy to ensure we aren't mutating the original data
28+
const data = JSON.parse(JSON.stringify(testData))
29+
30+
// split up data
31+
const testDraws = parseData(data.shift())
32+
const testBoards = []
33+
for (let x = 0; x < data.length; x = x + 5) {
34+
testBoards.push(
35+
data.slice(x, x + 5).map(parseData)
36+
)
37+
}
38+
39+
describe('--- Day 4: Giant Squid ---', () => {
40+
describe('Part 1', () => {
41+
describe('markBoard()', () => {
42+
it('checks a board for a match and marks it', () => {
43+
const board = [
44+
[1, 2, 3, 4, 5],
45+
[9, 8, 7, 6, 5],
46+
['x', 'x', 'x', 'x', 'x'],
47+
[3, 6, 9, 1, 0],
48+
[1, 3, 5, 7, 9]
49+
]
50+
const expected = [
51+
[1, 2, 3, 4, 'x'],
52+
[9, 8, 7, 6, 'x'],
53+
['x', 'x', 'x', 'x', 'x'],
54+
[3, 6, 9, 1, 0],
55+
[1, 3, 'x', 7, 9]
56+
]
57+
expect(markBoard(board, 5)).to.deep.equal(expected)
58+
})
59+
it.skip('can be used in a loop to find', () => {
60+
// callNumber(7)
61+
// callNumber(4)
62+
// callNumber(9)
63+
// callNumber(5)
64+
// callNumber(11)
65+
// for(var x = 0; x < testBoards)
66+
// expect(boards[0]).to.deep.equal(board0)
67+
// expect(boards[1]).to.deep.equal(board1)
68+
// expect(boards[2]).to.deep.equal(board2)
69+
// callNumber(17)
70+
// callNumber(23)
71+
// callNumber(2)
72+
// callNumber(0)
73+
// callNumber(14)
74+
// callNumber(21)
75+
// expect(boards[0]).to.deep.equal(board0)
76+
// expect(boards[1]).to.deep.equal(board1)
77+
// expect(boards[2]).to.deep.equal(board2)
78+
})
79+
it.skip('identifies the winner', () => {
80+
expect(callNumber(24)).to.equal(3)
81+
})
82+
})
83+
describe('findWinner()', () => {
84+
it.skip('loops through the boards and checks for a winner', () => {
85+
86+
})
87+
})
88+
describe('checkWinner()', () => {
89+
it('checks to see if a board has a horizontal bingo', () => {
90+
const board = [
91+
[1, 2, 3, 4, 5],
92+
[9, 8, 7, 6, 5],
93+
['x', 'x', 'x', 'x', 'x'],
94+
[3, 6, 9, 1, 0],
95+
[1, 3, 5, 7, 9]
96+
]
97+
expect(checkWinner(board)).to.equal('winner')
98+
})
99+
it('checks to see if a board has a vertical bingo', () => {
100+
const board = [
101+
[1, 2, 3, 'x', 5],
102+
[9, 8, 7, 'x', 5],
103+
[2, 4, 6, 'x', 8],
104+
[3, 6, 9, 'x', 0],
105+
[1, 3, 5, 'x', 7]
106+
]
107+
expect(checkWinner(board)).to.equal('winner')
108+
})
109+
it('identifies a board is not yet a winner', () => {
110+
const board = [
111+
[1, 'x', 3, 4, 5],
112+
[9, 8, 7, 'x', 5],
113+
['x', 'x', 3, 7, 11],
114+
[3, 6, 9, 'x', 'x'],
115+
[1, 3, 5, 7, 'x']
116+
]
117+
expect(checkWinner(board)).to.equal('no win')
118+
})
119+
})
120+
describe('scoreBoard()', () => {
121+
it('gets the sum of the unmarked squares on the board', () => {
122+
const board = [
123+
['x', 'x', 'x', 'x', 'x'],
124+
[10, 16, 15, 'x', 19],
125+
[18, 8, 'x', 26, 20],
126+
[22, 'x', 13, 6, 'x'],
127+
['x', 'x', 12, 3, 'x']
128+
]
129+
expect(scoreBoard(board)).to.equal(188)
130+
})
131+
})
132+
})
133+
})

2021/day-04/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// eslint-disable-next-line no-unused-vars
2+
const console = require('../helpers')
3+
require('./solution')

0 commit comments

Comments
 (0)