package main import ( "bufio" "fmt" "os" "time" ) func main() { start := time.Now() partOne() duration := time.Since(start) partTwo() duration2 := time.Since(start) fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) } // Our grid is a hex, so let's represent that as follows: // x runs east-west, y runs north-south. Yes, these coordinates here are backward. // 2,-2 2,0 2,2 2,4 // 1,-2 1,-1 1,1 1,2 // 0,-2 0,0 0,2 0,4 // -1,-2 -1,-1 -1,1 -1,2 // -2,-2 -2,0 -2,2 -2,4 // 0,0 -> e -> 0, 2 // -> w -> 0,-2 // -> se -> -1, 1 // -> sw -> -1,-1 // -> ne -> 1, 1 // -> nw -> 1,-1 // 0 == white, 1 == black type tiles map[coord]int type coord struct { x int y int } func walkGrid(directions []string) (int, int) { var y, x int for _, d := range directions { switch d { case "e": x = x + 2 case "se": y = y - 1 x = x + 1 case "sw": y = y - 1 x = x - 1 case "w": x = x - 2 case "ne": y = y + 1 x = x + 1 case "nw": y = y + 1 x = x - 1 } } return y, x } func parseLine(s string) []string { directions := []string{} for i := 0; i < len(s); { switch s[i] { case 'e': directions = append(directions, "e") i = i + 1 case 's': if s[i+1] == 'e' { directions = append(directions, "se") i = i + 2 } else if s[i+1] == 'w' { directions = append(directions, "sw") i = i + 2 } case 'w': directions = append(directions, "w") i = i + 1 case 'n': if s[i+1] == 'e' { directions = append(directions, "ne") i = i + 2 } else if s[i+1] == 'w' { directions = append(directions, "nw") i = i + 2 } } } return directions } func generation(t tiles) tiles { newTiles := tiles{} seenWhiteTiles := tiles{} for coord, tile := range t { // walk black tile list if tile == 1 { neighbors := getNeighbors(coord) bn := 0 for _, n := range neighbors { if t[n] == 0 { seenWhiteTiles[n] = seenWhiteTiles[n] + 1 } else { bn = bn + 1 } } // black tiles only survive if they have one or two black neighbors if bn == 1 || bn == 2 { newTiles[coord] = 1 } } } // white tiles turn black if they have two black neighbors for c, n := range seenWhiteTiles { if n == 2 { newTiles[c] = 1 } } return newTiles } func getNeighbors(c coord) []coord { return []coord{ {x: c.x + 2, y: c.y}, // e {x: c.x - 2, y: c.y}, // w {x: c.x + 1, y: c.y + 1}, // ne {x: c.x + 1, y: c.y - 1}, // nw {x: c.x - 1, y: c.y + 1}, // se {x: c.x - 1, y: c.y - 1}, // sw } } func countBlackTiles(t tiles) int { sum := 0 for _, tile := range t { sum = sum + tile } return sum } func partOne() { f, _ := os.Open("testinput") reader := bufio.NewReader(f) scanner := bufio.NewScanner(reader) t := tiles{} for scanner.Scan() { line := scanner.Text() x, y := walkGrid(parseLine(line)) if t[coord{x: x, y: y}] == 0 { t[coord{x: x, y: y}] = 1 } else { t[coord{x: x, y: y}] = 0 } } fmt.Println(countBlackTiles(t)) } func partTwo() { f, _ := os.Open("input") reader := bufio.NewReader(f) scanner := bufio.NewScanner(reader) t := tiles{} for scanner.Scan() { line := scanner.Text() y, x := walkGrid(parseLine(line)) if t[coord{x: x, y: y}] == 0 { t[coord{x: x, y: y}] = 1 } else { t[coord{x: x, y: y}] = 0 } } for day := 1; day <= 100; day = day + 1 { t = generation(t) } fmt.Println(countBlackTiles(t)) }