|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "bufio" |
| 5 | + "os" |
| 6 | + "strconv" |
| 7 | + "strings" |
| 8 | +) |
| 9 | + |
| 10 | +const boardSize = 5 |
| 11 | + |
| 12 | +type GameState struct { |
| 13 | + boards [][][]int |
| 14 | + boardNumbers map[int]map[int][]int // number to board id to [row col] |
| 15 | + boardResult [][]int // matrix id to [] with boardSize * 2 len. |
| 16 | +} |
| 17 | + |
| 18 | +/* * [01] -> inc (0 + row) inc (3 + col) |
| 19 | + [101] 2 |
| 20 | + [010] 2 |
| 21 | + [111] 3 |
| 22 | + 222 |
| 23 | +
|
| 24 | + [223222] |
| 25 | + boardResult = {0, {223222}} |
| 26 | +*/ |
| 27 | + |
| 28 | +func main() { |
| 29 | + file, _ := os.Open("input.txt") |
| 30 | + scanner := bufio.NewScanner(file) |
| 31 | + |
| 32 | + // numbers |
| 33 | + scanner.Scan() |
| 34 | + numbers := parseNumbersLine(scanner.Text()) |
| 35 | + |
| 36 | + // boards |
| 37 | + boards := parseBoards(*scanner) |
| 38 | + |
| 39 | + // init numbers map |
| 40 | + numbersMap := map[int]map[int][]int{} |
| 41 | + for i, board := range boards { |
| 42 | + for row := 0; row < boardSize; row++ { |
| 43 | + for col := 0; col < boardSize; col++ { |
| 44 | + n := board[row][col] |
| 45 | + if _, ok := numbersMap[n]; !ok { |
| 46 | + numbersMap[n] = map[int][]int{} |
| 47 | + } |
| 48 | + numbersMap[n][i] = []int{row, col} |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + boardResult := make([][]int, len(boards)) |
| 54 | + for i := 0; i < len(boards); i++ { |
| 55 | + boardResult[i] = make([]int, 2*boardSize) |
| 56 | + } |
| 57 | + |
| 58 | + gameState := GameState{ |
| 59 | + boards: boards, |
| 60 | + boardNumbers: numbersMap, |
| 61 | + boardResult: boardResult, |
| 62 | + } |
| 63 | + |
| 64 | + // process input |
| 65 | + calledNumbers := []int{} |
| 66 | + winner := -1 |
| 67 | + for _, n := range numbers { |
| 68 | + calledNumbers = append(calledNumbers, n) |
| 69 | + affectedBoards := gameState.boardNumbers[n] |
| 70 | + for boardId, rowcol := range affectedBoards { |
| 71 | + row := rowcol[0] |
| 72 | + col := rowcol[1] |
| 73 | + boardRes := gameState.boardResult[boardId] |
| 74 | + boardRes[row]++ |
| 75 | + boardRes[boardSize+col]++ |
| 76 | + if boardRes[row] == boardSize || boardRes[boardSize+col] == boardSize { |
| 77 | + winner = boardId |
| 78 | + break |
| 79 | + } |
| 80 | + } |
| 81 | + if winner != -1 { |
| 82 | + break |
| 83 | + } |
| 84 | + } |
| 85 | + println("Winner board id: " + strconv.Itoa(winner)) |
| 86 | + |
| 87 | + score := calculateScore(gameState.boards[winner], calledNumbers) |
| 88 | + println(score) |
| 89 | +} |
| 90 | + |
| 91 | +func parseNumbersLine(s string) []int { |
| 92 | + numbersStrings := strings.Split(s, ",") |
| 93 | + result := make([]int, len(numbersStrings)) |
| 94 | + for i := range numbersStrings { |
| 95 | + n, _ := strconv.Atoi(numbersStrings[i]) |
| 96 | + result[i] = n |
| 97 | + } |
| 98 | + return result |
| 99 | +} |
| 100 | + |
| 101 | +func parseBoards(s bufio.Scanner) [][][]int { |
| 102 | + result := [][][]int{} |
| 103 | + for s.Scan() { |
| 104 | + board := [][]int{} |
| 105 | + for i := 0; i < boardSize; i++ { |
| 106 | + s.Scan() |
| 107 | + line := parseBoardLine(s.Text()) |
| 108 | + board = append(board, line) |
| 109 | + } |
| 110 | + result = append(result, board) |
| 111 | + |
| 112 | + } |
| 113 | + return result |
| 114 | +} |
| 115 | + |
| 116 | +func parseBoardLine(s string) []int { |
| 117 | + numbersStrings := strings.Fields(s) |
| 118 | + result := make([]int, len(numbersStrings)) |
| 119 | + for i := range numbersStrings { |
| 120 | + n, _ := strconv.Atoi(numbersStrings[i]) |
| 121 | + result[i] = n |
| 122 | + } |
| 123 | + return result |
| 124 | +} |
| 125 | + |
| 126 | +func calculateScore(board [][]int, calledNumbers []int) int { |
| 127 | + winningNumber := calledNumbers[len(calledNumbers)-1] |
| 128 | + unmarkedNumbers := map[int]bool{} |
| 129 | + |
| 130 | + // at start all numbers are unmarked |
| 131 | + for row := 0; row < boardSize; row++ { |
| 132 | + for col := 0; col < boardSize; col++ { |
| 133 | + n := board[row][col] |
| 134 | + unmarkedNumbers[n] = true |
| 135 | + } |
| 136 | + } |
| 137 | + |
| 138 | + // exclude all called numbers |
| 139 | + for _, v := range calledNumbers { |
| 140 | + unmarkedNumbers[v] = false |
| 141 | + } |
| 142 | + |
| 143 | + unmkarkedSum := 0 |
| 144 | + for k, v := range unmarkedNumbers { |
| 145 | + if v { |
| 146 | + unmkarkedSum += k |
| 147 | + } |
| 148 | + } |
| 149 | + return unmkarkedSum * winningNumber |
| 150 | +} |
0 commit comments