199 lines
3.8 KiB
Go

package day4
import (
"strconv"
"strings"
)
func Run(dat []byte) (int, int) {
stringData := string(dat)
lines := strings.Split(stringData, "\n")
numbersDrawn := strings.Split(lines[0], ",")
lines = lines[2:]
currentBoard := make([][]int, 0)
boards := make([][][]int, 0)
for _, line := range lines {
if len(line) == 0 {
boards = append(boards, currentBoard)
currentBoard = make([][]int, 0)
} else {
currentLine := strings.Split(line, " ")
intLine := make([]int, 5)
counter := 0
for i := 0; i < len(currentLine); i++ {
if (len(currentLine[i]) > 0) {
intLine[counter], _ = strconv.Atoi(currentLine[i])
counter++
}
}
currentBoard = append(currentBoard, intLine)
}
}
/**
* There is probably a better way of doing this
*/
boardCheck := make([][][]int, 0)
for i := 0; i < len(boards); i++ {
boardCheck = append(boardCheck, [][]int{{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}})
}
boardComplete := false
winningIndex := 0
calledNumber := 0
//Part 1
for i := 0; i < len(numbersDrawn) && !boardComplete; i++ {
intNumber, _ := strconv.Atoi(numbersDrawn[i])
for i, board := range boards {
checkBoard(board, intNumber, &boardCheck[i])
if checkComplete(boardCheck[i]) {
boardComplete = true
winningIndex = i
calledNumber = intNumber
break
}
}
}
boardCheck = make([][][]int, 0)
for i := 0; i < len(boards); i++ {
boardCheck = append(boardCheck, [][]int{{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}})
}
completedBoards := make([]int, 0)
lastFound := -1
part2Num := 0
for i := 0; i < len(numbersDrawn) && lastFound == -1; i++ {
intNumber, _ := strconv.Atoi(numbersDrawn[i])
for i, board := range boards {
if !contains(completedBoards, i) {
checkBoard(board, intNumber, &boardCheck[i])
if checkComplete(boardCheck[i]) {
completedBoards = append(completedBoards, i)
if len(completedBoards) == len(boards) {
part2Num = intNumber
lastFound = i
break
}
}
}
}
}
unmarkedNumbers := 0
partUnmarkedNumbers := 0
for i := 0; i < len(boards[winningIndex]); i++ {
for j := 0; j < len(boards[winningIndex][0]); j++ {
if boardCheck[winningIndex][i][j] == 0 {
unmarkedNumbers += boards[winningIndex][i][j]
}
}
}
for i := 0; i < len(boards[lastFound]); i++ {
for j := 0; j < len(boards[lastFound][0]); j++ {
if boardCheck[lastFound][i][j] == 0 {
partUnmarkedNumbers += boards[lastFound][i][j]
}
}
}
return calledNumber * unmarkedNumbers, part2Num * partUnmarkedNumbers
}
func contains(arr []int, num int) bool {
for _, e := range arr {
if e == num {
return true
}
}
return false
}
func checkBoard(board [][]int, numberDrawn int, boardCheck *[][]int) {
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[0]); j++ {
if board[i][j] == numberDrawn {
(*boardCheck)[i][j] = 1
}
}
}
}
//Return -1 if board is not complete
func checkComplete(boardCheck [][]int) bool {
//Check rows
for i := 0; i < len(boardCheck); i++ {
rowComplete := true
for j := 0; j < len(boardCheck[0]); j++ {
if boardCheck[i][j] == 0 {
rowComplete = false
}
}
if rowComplete {
return true
}
}
//Check cols
for i := 0; i < len(boardCheck); i++ {
colComplete := true
for j := 0; j < len(boardCheck[0]); j++ {
if boardCheck[j][i] == 0 {
colComplete = false
}
}
if colComplete {
return true
}
}
return false
}