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 }