github.com/cycloss/advent-of-code@v0.0.0-20221210145555-15039b95faa6/2021/day4/day4parse.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"log"
     6  	"os"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  type bingo struct {
    12  	numbers []int
    13  	boards  []*board
    14  }
    15  
    16  type board struct {
    17  	// non zero indexed
    18  	boardWidth, boardHeight int
    19  	won                     bool
    20  	grid                    []bool
    21  	remainingNumbers        map[int]*coordinate
    22  }
    23  
    24  type coordinate struct {
    25  	// start from top left at 0, 0
    26  	x, y int
    27  }
    28  
    29  func newBingoFromFile(f *os.File) *bingo {
    30  	var buff = bufio.NewScanner(f)
    31  	var nums = getNumbers(buff)
    32  	var boards = []*board{}
    33  	for nextBoard := getNextBoard(buff); nextBoard != nil; {
    34  		boards = append(boards, nextBoard)
    35  		nextBoard = getNextBoard(buff)
    36  
    37  	}
    38  	return &bingo{nums, boards}
    39  }
    40  
    41  func getNumbers(buff *bufio.Scanner) []int {
    42  	var nums = []int{}
    43  	buff.Scan()
    44  	var line = buff.Text()
    45  	var rawNums = strings.Split(line, ",")
    46  	buff.Scan() // consume next
    47  	for _, v := range rawNums {
    48  		var num, err = strconv.Atoi(v)
    49  		if err != nil {
    50  			log.Fatalf("Couldn't parse into number: %s. Error: %v", v, err)
    51  		}
    52  		nums = append(nums, num)
    53  	}
    54  	return nums
    55  }
    56  
    57  func getNextBoard(buff *bufio.Scanner) *board {
    58  	var width, height = 0, 0
    59  	var nums = []int{}
    60  	for scanned := buff.Scan(); scanned; {
    61  		if !scanned { // hit end of file
    62  			break
    63  		}
    64  		var line = buff.Text()
    65  
    66  		if line == "" || !scanned { // hit end of board
    67  			break
    68  		}
    69  		var row = generateNumsFromLine(line)
    70  		nums = append(nums, row...)
    71  		width = len(row)
    72  		height++
    73  		scanned = buff.Scan()
    74  
    75  	}
    76  	if len(nums) == 0 {
    77  		return nil
    78  	}
    79  	var grid = make([]bool, len(nums))
    80  	var coords = createCoordinateMap(width, height, nums)
    81  	return &board{width, height, false, grid, coords}
    82  }
    83  
    84  func generateNumsFromLine(line string) []int {
    85  	var lineNums = strings.Fields(line)
    86  	var nums = []int{}
    87  	for _, v := range lineNums {
    88  		var num, err = strconv.Atoi(v)
    89  		if err != nil {
    90  			log.Fatalf("Couldn't parse into number: %s. Error: %v", v, err)
    91  		}
    92  		nums = append(nums, num)
    93  	}
    94  	return nums
    95  }
    96  
    97  func createCoordinateMap(width, height int, nums []int) map[int]*coordinate {
    98  	var coords = map[int]*coordinate{}
    99  	var i = 0
   100  	for row := 0; row < height; row++ {
   101  		for column := 0; column < width; column++ {
   102  			var num = nums[i]
   103  			coords[num] = &coordinate{column, row}
   104  			i++
   105  		}
   106  	}
   107  	return coords
   108  }