package main import ( "flag" "fmt" "strings" "github.com/alexchao26/advent-of-code-go/util" ) func main() { var part int flag.IntVar(&part, "part", 1, "part 1 or 2") flag.Parse() fmt.Println("Running part", part) if part == 1 { ans := part1(util.ReadFile("./input.txt")) fmt.Println("Output:", ans) } else { ans := part2(util.ReadFile("./input.txt")) fmt.Println("Output:", ans) } } func part1(input string) int { grid := parseInput(input) for i := 0; i < 10; i++ { grid = step(grid) // fmt.Println(i) // for _, v := range grid { // fmt.Println(v) // } // fmt.Println("") } finalTrees, finalLumbers := countTreesAndLumber(grid) return finalTrees * finalLumbers } func part2(input string) int { grid := parseInput(input) stepsWanted := 1000000000 cacheStringifiedGridToIndex := make(map[string]int) for i := 0; i < stepsWanted; i++ { grid = step(grid) stringified := stringify(grid) if lastIndex, ok := cacheStringifiedGridToIndex[stringified]; ok { freq := i - lastIndex // skip steps for i+freq < stepsWanted { i += freq } } cacheStringifiedGridToIndex[stringified] = i } // between 197616 and 209420 finalTrees, finalLumbers := countTreesAndLumber(grid) return finalTrees * finalLumbers } func parseInput(input string) [][]string { var ans [][]string lines := strings.Split(input, "\n") // to pad either edge columnsPlusTwo := len(lines[0]) + 2 ans = append(ans, make([]string, columnsPlusTwo)) for _, l := range lines { rowSli := append([]string{""}, strings.Split(l, "")...) rowSli = append(rowSli, "") ans = append(ans, rowSli) } ans = append(ans, make([]string, columnsPlusTwo)) return ans } func step(grid [][]string) [][]string { nextGrid := make([][]string, len(grid)) for i := range grid { nextGrid[i] = make([]string, len(grid[0])) } dir := [8][2]int{ {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}, } for row := 1; row < len(grid)-1; row++ { for col := 1; col < len(grid[0])-1; col++ { var adjTrees, adjOpen, adjLumber int for _, d := range dir { neighborRow, neighborCol := row+d[0], col+d[1] switch grid[neighborRow][neighborCol] { case "#": adjLumber++ case "|": adjTrees++ case ".": adjOpen++ } } switch grid[row][col] { case ".": if adjTrees >= 3 { nextGrid[row][col] = "|" } else { nextGrid[row][col] = "." } case "|": if adjLumber >= 3 { nextGrid[row][col] = "#" } else { nextGrid[row][col] = "|" } case "#": if adjLumber >= 1 && adjTrees >= 1 { nextGrid[row][col] = "#" } else { nextGrid[row][col] = "." } } } } return nextGrid } func countTreesAndLumber(grid [][]string) (int, int) { var trees, lumbers int for _, row := range grid { for _, v := range row { switch v { case "#": lumbers++ case "|": trees++ } } } return trees, lumbers } func stringify(grid [][]string) string { var ans string for _, row := range grid { for _, v := range row { ans += v } } return ans }