package main import ( "AoC2020/helper" "fmt" "os" ) func main() { args := os.Args[1:] input, err := helper.GetInput(args[0]) if err != nil { fmt.Println(err) } dimension := readInputLayer(input,0) fmt.Println(len(getDirectionsPart2())) for i := 0; i < 6; i++ { dimension = run(dimension, getDirectionsPart2) } } func run(dimension map[[4]int]rune, getDirections func() [][4]int) map[[4]int]rune { var changedValues = make(map[[4]int]rune) directions := getDirections() visitedNeighbours := make(map[[4]int]int) for position, status := range dimension { neighbourPosition := getNeighbourPoints(position,directions) neighbours := getActiveNeighbours(dimension, neighbourPosition) if status == '#' && !(neighbours == 2 || neighbours == 3) { changedValues[position] = '.' } for _, position := range neighbourPosition { visitedNeighbours[position] ++ } } for position, val := range visitedNeighbours { if val == 3 { changedValues[position] = '#' } } for position, status := range changedValues { //fmt.Printf("Changed Position: %v Status: %v \n",position,string(status)) if status == '.' { delete(dimension, position) } if status == '#' { dimension[position] = status } } fmt.Printf("Active Points: %v \n", len(dimension)) return dimension } func readInputLayer(input []string, layerLevel int) map[[4]int]rune { var layer = make(map[[4]int]rune) for y, row := range input { for x, val := range row { if val == '#' { layer[[4]int{y,x,layerLevel,0}] = val } } } return layer } func printLayer(layer int, width int, height int, dimension map[[3]int]rune) { for i:= 0; i < height; i++ { var row []rune for j:= 0; j < width; j++ { val := dimension[[3]int{i,j,layer}] if val == '#' { row = append(row,val) }else { row = append(row, '.') } } fmt.Println(string(row)) } fmt.Println() } func getNeighbourPoints(position [4]int, directions [][4]int) [][4]int{ var neighbourPositions [][4]int for _, direction := range directions { neighbourPositions = append(neighbourPositions, add(position, direction)) } return neighbourPositions } func getActiveNeighbours(dimension map[[4]int]rune, neighbourPositions [][4]int) int { activeNeighbours := 0 for _, neighbourPosition := range neighbourPositions { if dimension[neighbourPosition] == '#' { activeNeighbours++ } } //fmt.Printf("Active Neighbours: %v \n" ,activeNeighbours) return activeNeighbours } func add(a [4]int, b [4]int) [4]int { return [4]int{a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]} } func getDirections() [][4]int { possibleValues := [3]int{-1, 0, 1} var directions [][4]int for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { for k := 0; k < 3; k++ { if possibleValues[i] != 0 || possibleValues[j] != 0 || possibleValues[k] != 0 { directions = append(directions, [4]int{possibleValues[i], possibleValues[j], possibleValues[k],0}) } } } } return directions } func getDirectionsPart2() [][4]int { possibleValues := [3]int{-1, 0, 1} var directions [][4]int for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { for k := 0; k < 3; k++ { for l := 0; l < 3; l++ { if possibleValues[i] != 0 || possibleValues[j] != 0 || possibleValues[k] != 0 || possibleValues[l] != 0 { directions = append(directions, [4]int{possibleValues[i], possibleValues[j], possibleValues[k],possibleValues[l]}) } } } } } return directions } func getStatus(position [3]int, dimension [][][]rune) rune { if len(dimension) < position[0] { return '.' } layer := dimension[position[0]] if len(layer) < position[1] { return '.' } row := layer[position[1]] if len(row) < position[2] { return '.' } return rune(row[position[2]]) } func initiateDimension(z int, x int, y int) [][][]rune { var emptyRow []rune for i := 0; i < x; i++ { emptyRow = append(emptyRow, '.') } var emptyLayer [][]rune for i := 0; i < y; i++ { emptyLayer = append(emptyLayer, emptyRow) } var emptyDimension [][][]rune for i := 0; i < z; i++ { emptyDimension = append(emptyDimension, emptyLayer) } return emptyDimension }