diff --git a/24/main.go b/24/main.go new file mode 100644 index 0000000..a7b2463 --- /dev/null +++ b/24/main.go @@ -0,0 +1,186 @@ +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)) + +}