AoC2021/src/day4/day4.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
}