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) } type cell struct { x int // length y int // width z int // depth w int // spissitude } type universe struct { cells map[cell]bool hyper bool // true: 4-dimensional; false: 3-dimensional } func makeNeighborsList(c cell, hyper bool) []cell { cells := []cell{} if hyper { cells = append(cells, []cell{ // outward...? // above {x: c.x + 1, y: c.y + 1, z: c.z + 1, w: c.w + 1}, {x: c.x + 1, y: c.y, z: c.z + 1, w: c.w + 1}, {x: c.x + 1, y: c.y - 1, z: c.z + 1, w: c.w + 1}, {x: c.x, y: c.y + 1, z: c.z + 1, w: c.w + 1}, {x: c.x, y: c.y, z: c.z + 1, w: c.w + 1}, {x: c.x, y: c.y - 1, z: c.z + 1, w: c.w + 1}, {x: c.x - 1, y: c.y + 1, z: c.z + 1, w: c.w + 1}, {x: c.x - 1, y: c.y, z: c.z + 1, w: c.w + 1}, {x: c.x - 1, y: c.y - 1, z: c.z + 1, w: c.w + 1}, // same layer {x: c.x + 1, y: c.y + 1, z: c.z, w: c.w + 1}, {x: c.x + 1, y: c.y, z: c.z, w: c.w + 1}, {x: c.x + 1, y: c.y - 1, z: c.z, w: c.w + 1}, {x: c.x, y: c.y + 1, z: c.z, w: c.w + 1}, {x: c.x, y: c.y, z: c.z, w: c.w + 1}, {x: c.x, y: c.y - 1, z: c.z, w: c.w + 1}, {x: c.x - 1, y: c.y + 1, z: c.z, w: c.w + 1}, {x: c.x - 1, y: c.y, z: c.z, w: c.w + 1}, {x: c.x - 1, y: c.y - 1, z: c.z, w: c.w + 1}, // below {x: c.x + 1, y: c.y + 1, z: c.z - 1, w: c.w + 1}, {x: c.x + 1, y: c.y, z: c.z - 1, w: c.w + 1}, {x: c.x + 1, y: c.y - 1, z: c.z - 1, w: c.w + 1}, {x: c.x, y: c.y + 1, z: c.z - 1, w: c.w + 1}, {x: c.x, y: c.y, z: c.z - 1, w: c.w + 1}, {x: c.x, y: c.y - 1, z: c.z - 1, w: c.w + 1}, {x: c.x - 1, y: c.y + 1, z: c.z - 1, w: c.w + 1}, {x: c.x - 1, y: c.y, z: c.z - 1, w: c.w + 1}, {x: c.x - 1, y: c.y - 1, z: c.z - 1, w: c.w + 1}, // inward...? // above {x: c.x + 1, y: c.y + 1, z: c.z + 1, w: c.w - 1}, {x: c.x + 1, y: c.y, z: c.z + 1, w: c.w - 1}, {x: c.x + 1, y: c.y - 1, z: c.z + 1, w: c.w - 1}, {x: c.x, y: c.y + 1, z: c.z + 1, w: c.w - 1}, {x: c.x, y: c.y, z: c.z + 1, w: c.w - 1}, {x: c.x, y: c.y - 1, z: c.z + 1, w: c.w - 1}, {x: c.x - 1, y: c.y + 1, z: c.z + 1, w: c.w - 1}, {x: c.x - 1, y: c.y, z: c.z + 1, w: c.w - 1}, {x: c.x - 1, y: c.y - 1, z: c.z + 1, w: c.w - 1}, // same layer {x: c.x + 1, y: c.y + 1, z: c.z, w: c.w - 1}, {x: c.x + 1, y: c.y, z: c.z, w: c.w - 1}, {x: c.x + 1, y: c.y - 1, z: c.z, w: c.w - 1}, {x: c.x, y: c.y + 1, z: c.z, w: c.w - 1}, {x: c.x, y: c.y, z: c.z, w: c.w - 1}, {x: c.x, y: c.y - 1, z: c.z, w: c.w - 1}, {x: c.x - 1, y: c.y + 1, z: c.z, w: c.w - 1}, {x: c.x - 1, y: c.y, z: c.z, w: c.w - 1}, {x: c.x - 1, y: c.y - 1, z: c.z, w: c.w - 1}, // below {x: c.x + 1, y: c.y + 1, z: c.z - 1, w: c.w - 1}, {x: c.x + 1, y: c.y, z: c.z - 1, w: c.w - 1}, {x: c.x + 1, y: c.y - 1, z: c.z - 1, w: c.w - 1}, {x: c.x, y: c.y + 1, z: c.z - 1, w: c.w - 1}, {x: c.x, y: c.y, z: c.z - 1, w: c.w - 1}, {x: c.x, y: c.y - 1, z: c.z - 1, w: c.w - 1}, {x: c.x - 1, y: c.y + 1, z: c.z - 1, w: c.w - 1}, {x: c.x - 1, y: c.y, z: c.z - 1, w: c.w - 1}, {x: c.x - 1, y: c.y - 1, z: c.z - 1, w: c.w - 1}, }...) } // "normal" space cells = append(cells, []cell{ // above {x: c.x + 1, y: c.y + 1, z: c.z + 1, w: c.w}, {x: c.x + 1, y: c.y, z: c.z + 1, w: c.w}, {x: c.x + 1, y: c.y - 1, z: c.z + 1, w: c.w}, {x: c.x, y: c.y + 1, z: c.z + 1, w: c.w}, {x: c.x, y: c.y, z: c.z + 1, w: c.w}, {x: c.x, y: c.y - 1, z: c.z + 1, w: c.w}, {x: c.x - 1, y: c.y + 1, z: c.z + 1, w: c.w}, {x: c.x - 1, y: c.y, z: c.z + 1, w: c.w}, {x: c.x - 1, y: c.y - 1, z: c.z + 1, w: c.w}, // same layer {x: c.x + 1, y: c.y + 1, z: c.z, w: c.w}, {x: c.x + 1, y: c.y, z: c.z, w: c.w}, {x: c.x + 1, y: c.y - 1, z: c.z, w: c.w}, {x: c.x, y: c.y + 1, z: c.z, w: c.w}, // <-- original cell {x: c.x, y: c.y - 1, z: c.z, w: c.w}, {x: c.x - 1, y: c.y + 1, z: c.z, w: c.w}, {x: c.x - 1, y: c.y, z: c.z, w: c.w}, {x: c.x - 1, y: c.y - 1, z: c.z, w: c.w}, // below {x: c.x + 1, y: c.y + 1, z: c.z - 1, w: c.w}, {x: c.x + 1, y: c.y, z: c.z - 1, w: c.w}, {x: c.x + 1, y: c.y - 1, z: c.z - 1, w: c.w}, {x: c.x, y: c.y + 1, z: c.z - 1, w: c.w}, {x: c.x, y: c.y, z: c.z - 1, w: c.w}, {x: c.x, y: c.y - 1, z: c.z - 1, w: c.w}, {x: c.x - 1, y: c.y + 1, z: c.z - 1, w: c.w}, {x: c.x - 1, y: c.y, z: c.z - 1, w: c.w}, {x: c.x - 1, y: c.y - 1, z: c.z - 1, w: c.w}, }...) return cells } func checkNeighbors(u universe, c cell) bool { sum := 0 for _, c := range makeNeighborsList(c, u.hyper) { if u.cells[c] { sum = sum + 1 } } if sum == 3 { return true } else if u.cells[c] && sum == 2 { return true } return false } func step(old universe) universe { new := universe{ cells: make(map[cell]bool, len(old.cells)), hyper: old.hyper, } cellsToCheck := make([]cell, 0, len(old.cells)*80) for c := range old.cells { cellsToCheck = append(cellsToCheck, makeNeighborsList(c, old.hyper)...) } for _, c := range cellsToCheck { if checkNeighbors(old, c) { new.cells[c] = true } } return new } func newUniverse(input []string, hyper bool) universe { u := universe{ cells: make(map[cell]bool, len(input)), hyper: hyper, } for i, r := range input { for j, c := range r { if c == '#' { u.cells[cell{z: 0, x: i, y: j, w: 0}] = true } } } return u } func countActivesInUniverse(u universe) { fmt.Println(len(u.cells)) } func partOne() { f, _ := os.Open("input") reader := bufio.NewReader(f) scanner := bufio.NewScanner(reader) var input []string for scanner.Scan() { input = append(input, scanner.Text()) } u := newUniverse(input, false) u = step(u) u = step(u) u = step(u) u = step(u) u = step(u) u = step(u) countActivesInUniverse(u) } func partTwo() { f, _ := os.Open("input") reader := bufio.NewReader(f) scanner := bufio.NewScanner(reader) var input []string for scanner.Scan() { input = append(input, scanner.Text()) } u := newUniverse(input, true) u = step(u) u = step(u) u = step(u) u = step(u) u = step(u) u = step(u) countActivesInUniverse(u) }