Add day four Bingo player

This commit is contained in:
2021-12-04 14:03:47 +00:00
parent 5fc7348bdf
commit f6862dc302
6 changed files with 937 additions and 0 deletions

216
four/bingo.go Normal file
View File

@@ -0,0 +1,216 @@
package four
import (
"bufio"
"os"
"strconv"
"strings"
)
type cell struct {
value int
called bool
}
type board struct {
cells [5][5]cell
bingo bool
}
type bingo struct {
calls []int
boards []board
}
func (b *bingo) read(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
// Read the first line
scanner.Scan()
calls := strings.Split(scanner.Text(), ",")
for _, n := range calls {
number, err := strconv.Atoi(n)
if err != nil {
return err
}
b.calls = append(b.calls, number)
}
// Read the game boards
line := 0
var current board
for scanner.Scan() {
if scanner.Text() == "" {
if line > 0 {
b.boards = append(b.boards, current)
}
line = 0
current = board{}
continue
}
withoutWhitespace := strings.Fields(scanner.Text())
for i, n := range withoutWhitespace {
number, err := strconv.Atoi(n)
if err != nil {
return err
}
current.cells[line][i].value = number
}
line++
}
if line > 0 {
b.boards = append(b.boards, current)
}
return nil
}
func (b *bingo) reset() {
for i := range b.boards {
b.boards[i].bingo = false
for row := 0; row < 5; row++ {
for column := 0; column < 5; column++ {
b.boards[i].cells[row][column].called = false
}
}
}
}
func (b *bingo) play() (int, int) {
winningCall := -1
score := -1
for _, call := range b.calls {
for i := range b.boards {
bingo := b.boards[i].called(call)
if bingo {
score := 0
for row := 0; row < 5; row++ {
for column := 0; column < 5; column++ {
if !b.boards[i].cells[row][column].called {
score += b.boards[i].cells[row][column].value
}
}
}
return score, call
}
}
}
return score, winningCall
}
func (b *bingo) slowPlay() (int, int) {
winningCall := -1
score := -1
callingBoards := b.boards
for _, call := range b.calls {
filteredBoards := []board{}
for i := range callingBoards {
bingo := callingBoards[i].called(call)
if !bingo {
filteredBoards = append(filteredBoards, callingBoards[i])
} else if len(callingBoards) == 1 {
score := 0
for row := 0; row < 5; row++ {
for column := 0; column < 5; column++ {
if !callingBoards[i].cells[row][column].called {
score += callingBoards[i].cells[row][column].value
}
}
}
return score, call
}
}
callingBoards = filteredBoards
}
return score, winningCall
}
func (b *board) called(number int) bool {
// Mark the called number
found := false
for row := 0; row < 5; row++ {
for column := 0; column < 5; column++ {
if b.cells[row][column].value == number {
b.cells[row][column].called = true
found = true
break
}
}
if found {
break
}
}
// Check to see if there is a win
// Check rows
found = false
for row := 0; row < 5; row++ {
winner := true
for column := 0; column < 5; column++ {
if !b.cells[row][column].called {
winner = false
}
}
if winner {
b.bingo = true
return b.bingo
}
}
// Check columns
for column := 0; column < 5; column++ {
winner := true
for row := 0; row < 5; row++ {
if !b.cells[row][column].called {
winner = false
}
}
if winner {
b.bingo = true
return b.bingo
}
}
// // Check left diagonal
// winner := true
// for index := 0; index < 5; index++ {
// if !b.cells[index][index].called {
// winner = false
// break
// }
// }
// if winner {
// b.bingo = true
// return b.bingo
// }
// // Check right diagonal
// winner = true
// for index := 0; index < 5; index++ {
// if !b.cells[index][4-index].called {
// winner = false
// break
// }
// }
// if winner {
// b.bingo = true
// return b.bingo
// }
return b.bingo
}