package day03 import ( "strconv" "strings" ) type Claim struct { ID int Overlaps bool x1 int y1 int x2 int y2 int } // PopulateGrid takes a series of claims and 'draws' them on a 2d // array, writing the claim ID to each cell. If an overlap happens, // the value -1 is written instead. // It also flags the claim object as 'overwritten' when this happens. func PopulateGrid(data map[int]*Claim, maxX, maxY int) [][]int { grid := make([][]int, maxY) for i := 0; i < maxY; i++ { grid[i] = make([]int, maxX) } for _, claim := range data { for y := claim.y1; y < claim.y2; y++ { for x := claim.x1; x < claim.x2; x++ { if grid[y][x] != 0 { if grid[y][x] != -1 { data[grid[y][x]].Overlaps = true } grid[y][x] = -1 data[claim.ID].Overlaps = true } else { grid[y][x] = claim.ID } } } } return grid } // ParseClaims takes our input data and creates some usable, structured data from it. // Unfortunately the input data is ugly, and so this function reflects that. // Returns a list of Claim objects, the highest seen X value, and the highest seen Y value. func ParseClaims(rawData []string) (map[int]*Claim, int, int) { claims := make(map[int]*Claim) maxX := 0 maxY := 0 for _, line := range rawData { // Split the data on spaces, since that's the top-order delimiter. data := strings.Split(line, " ") id, _ := strconv.Atoi(data[0][1:]) // The coordinate chunk (data[2]) needs the last character chopped off, since it is an unused ':' // That's what [:len(data[2])-1] is doing. coords := strings.Split(data[2][:len(data[2])-1], ",") x1, _ := strconv.Atoi(coords[0]) y1, _ := strconv.Atoi(coords[1]) size := strings.Split(data[3], "x") width, _ := strconv.Atoi(size[0]) height, _ := strconv.Atoi(size[1]) claim := &Claim{ ID: id, x1: x1, x2: x1 + width, y1: y1, y2: y1 + height, Overlaps: false, } claims[id] = claim if claim.y2 > maxY { maxY = claim.y2 } if claim.x2 > maxX { maxX = claim.x2 } } return claims, maxX, maxY }