236 lines
6.1 KiB
Go
236 lines
6.1 KiB
Go
|
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)
|
||
|
}
|