120 lines
2.6 KiB
Go
120 lines
2.6 KiB
Go
package aoc
|
|
|
|
import (
|
|
"os"
|
|
"io"
|
|
"errors"
|
|
"bufio"
|
|
"strings"
|
|
"strconv"
|
|
)
|
|
|
|
type Field struct {
|
|
Marked bool
|
|
Value int
|
|
}
|
|
|
|
type Board struct {
|
|
Fields [5][5]Field
|
|
Completed bool
|
|
}
|
|
|
|
const (
|
|
READ_NUMBERS = 0
|
|
READ_BOARD = 1
|
|
)
|
|
|
|
func strs_to_ints(num_strs []string) []int {
|
|
var numbers []int
|
|
|
|
for _, num_str := range num_strs {
|
|
i, _ := strconv.Atoi(num_str)
|
|
numbers = append(numbers, i)
|
|
}
|
|
|
|
return numbers
|
|
}
|
|
|
|
func ReadFile(path string) ([]int, []Board, error) {
|
|
file, err := os.Open(path)
|
|
defer file.Close()
|
|
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
reader := bufio.NewReader(file)
|
|
|
|
var state = READ_NUMBERS
|
|
|
|
var numbers []int
|
|
|
|
var boards []Board
|
|
var cur_fields [5][5]Field
|
|
var row_idx = 0
|
|
|
|
reader:for {
|
|
line, err := reader.ReadString('\n')
|
|
var end_of_file = errors.Is(err, io.EOF)
|
|
if err != nil && !end_of_file { break }
|
|
|
|
var state_change = line == "\n" || end_of_file
|
|
line = strings.TrimRight(line, "\n")
|
|
|
|
switch state {
|
|
case READ_NUMBERS:
|
|
if state_change {
|
|
state = READ_BOARD
|
|
continue
|
|
}
|
|
var num_strs = strings.Split(line, ",")
|
|
numbers = strs_to_ints(num_strs)
|
|
case READ_BOARD:
|
|
if state_change {
|
|
var board = Board{Fields: cur_fields, Completed: false}
|
|
boards = append(boards, board)
|
|
row_idx = 0
|
|
if end_of_file { break reader }
|
|
continue
|
|
}
|
|
var num_strs = strings.Fields(line)
|
|
for col_idx, value := range strs_to_ints(num_strs) {
|
|
cur_fields[row_idx][col_idx] = Field{Value: value, Marked: false}
|
|
}
|
|
row_idx += 1
|
|
}
|
|
}
|
|
|
|
return numbers, boards, nil
|
|
}
|
|
|
|
func check_row(i int, board *Board) bool {
|
|
for _, field := range board.Fields[i] {
|
|
if !field.Marked { return false }
|
|
}
|
|
return true
|
|
}
|
|
|
|
func check_col(j int, board *Board) bool {
|
|
for _, row := range board.Fields {
|
|
if !row[j].Marked { return false }
|
|
}
|
|
return true
|
|
}
|
|
|
|
func MarkBoard(board *Board, number int) bool {
|
|
for i, row := range board.Fields {
|
|
for j, _ := range row {
|
|
var field = &board.Fields[i][j]
|
|
if field.Value == number {
|
|
field.Marked = true
|
|
if check_row(i, board) || check_col(j, board) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|