168 lines
4.1 KiB
Go
168 lines
4.1 KiB
Go
|
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
|
||
|
}
|