157 lines
3.6 KiB
Go
157 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"AOC2021/src/helper"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type bingoField struct {
|
|
number int
|
|
checked bool
|
|
}
|
|
|
|
type bingoGame struct {
|
|
winState []int
|
|
currentRound int
|
|
numbers []int
|
|
boards [][][]bingoField
|
|
}
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
input, err := helper.GetInput(args[0])
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
bingoNumbers, _ := helper.MapToNumber(strings.Split(input[0], ","))
|
|
bingoBoards := parseBoards(input)
|
|
|
|
part1(bingoNumbers, bingoBoards)
|
|
part2(bingoNumbers, bingoBoards)
|
|
}
|
|
|
|
func part1(bingoNumbers []int, bingoBoards [][][]bingoField) {
|
|
game := bingoGame{[]int{}, 0, bingoNumbers, bingoBoards}
|
|
for len(game.winState) == 0 {
|
|
game.playRound()
|
|
}
|
|
fmt.Println(getSumOfUncheckedField(game.boards[game.winState[0]]) * game.numbers[game.currentRound-1])
|
|
}
|
|
|
|
func part2(bingoNumbers []int, bingoBoards [][][]bingoField) {
|
|
game := bingoGame{[]int{}, 0, bingoNumbers, bingoBoards}
|
|
for len(game.winState) < len(game.boards) {
|
|
game.playRound()
|
|
}
|
|
fmt.Println(getSumOfUncheckedField(game.boards[game.winState[len(game.winState)-1]]) * game.numbers[game.currentRound-1])
|
|
}
|
|
|
|
func parseBoards(input []string) [][][]bingoField {
|
|
var bingoBoards [][][]bingoField
|
|
for i := 0; i*6 + 6 <= len(input); i++ {
|
|
begin := 2 + i*6
|
|
end := 7 + i*6
|
|
bingoBoards = append(bingoBoards,parseBoard(input[begin:end]) )
|
|
}
|
|
return bingoBoards
|
|
}
|
|
|
|
func parseBoard(input []string) [][]bingoField{
|
|
bingoBoard := make([][]bingoField, len(input))
|
|
for i, line := range input {
|
|
numberStrings := strings.Split(line, " ")
|
|
numberStrings = helper.RemoveElementFromStringArray(numberStrings, "")
|
|
numbers, _ := helper.MapToNumber(numberStrings)
|
|
row := make([]bingoField, len(numbers))
|
|
for i, number := range numbers {
|
|
row[i] = bingoField{number, false}
|
|
}
|
|
bingoBoard[i] = row
|
|
}
|
|
return bingoBoard
|
|
}
|
|
|
|
func (game* bingoGame) playRound () {
|
|
drawnNumber := game.numbers[game.currentRound]
|
|
for _, board := range game.boards {
|
|
markFields(&board, drawnNumber)
|
|
}
|
|
for i, board := range game.boards {
|
|
if !helper.Contains(i, game.winState) && checkWinCondition(board){
|
|
game.winState = append(game.winState, i)
|
|
}
|
|
}
|
|
game.currentRound++
|
|
}
|
|
|
|
func markFields(board *[][]bingoField, drawnNumber int) {
|
|
for i,row := range *board {
|
|
for j,field := range row {
|
|
if field.number == drawnNumber {
|
|
(*board)[i][j] = bingoField{drawnNumber, true}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func checkWinCondition(board [][]bingoField) bool{
|
|
winConditionBoard := make([][]int, len(board))
|
|
for i,row := range board {
|
|
for _,field := range row {
|
|
if field.checked {
|
|
winConditionBoard[i] = append(winConditionBoard[i], 1)
|
|
} else {
|
|
winConditionBoard[i] = append(winConditionBoard[i], 0)
|
|
}
|
|
}
|
|
}
|
|
if checkWinConditionRows(winConditionBoard) || checkWinConditionRows(helper.Transpose(winConditionBoard)) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func checkWinConditionRows(rows [][]int) bool{
|
|
for _, row := range rows {
|
|
if helper.AddNummbers(row...) == len(row) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func checkWinConditionDiagonals(rows [][]int) bool{
|
|
return checkWinConditionDiagonal(rows) || checkWinConditionDiagonalInverse(rows)
|
|
}
|
|
|
|
func checkWinConditionDiagonal(rows [][]int,) bool {
|
|
for i := 0; i < len(rows); i++ {
|
|
if rows[i][i] == 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func checkWinConditionDiagonalInverse(rows [][]int) bool {
|
|
for i := 0; i < len(rows); i++ {
|
|
if rows[4-i][i] == 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func getSumOfUncheckedField(board [][]bingoField) int {
|
|
sum := 0
|
|
for _, row := range board {
|
|
for _, field := range row {
|
|
if !field.checked {
|
|
sum += field.number
|
|
}
|
|
}
|
|
}
|
|
return sum
|
|
} |