199 lines
3.8 KiB
Go
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
|
|
|
|
} |