2020 Day 17 Complete

This commit is contained in:
Brian Buller 2020-12-17 09:17:22 -06:00
parent 6c0a8593c9
commit 4ca404b3c6
6 changed files with 252 additions and 4 deletions

View File

@ -14,7 +14,7 @@ var FieldMap map[int]string
var UnknownFields map[int]bool
func main() {
fmt.Println("# Day 15")
fmt.Println("# Day 16")
inp := h.StdinToStringSlice()
FieldMap = make(map[int]string)
UnknownFields = make(map[int]bool)

8
2020/day17/input Normal file
View File

@ -0,0 +1,8 @@
....###.
#...####
##.#.###
..#.#...
##.#.#.#
#.######
..#..#.#
######.#

115
2020/day17/main.go Normal file
View File

@ -0,0 +1,115 @@
package main
import (
"fmt"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
fmt.Println("# Day 17")
fmt.Println()
inp := h.StdinToStringSlice()
//field := h.StringSliceToCoord3dByteMap(inp)
//part1old(field)
fmt.Println("## Part 1:\nAnswer:", run(inp, 3))
fmt.Println("## Part 2:\nAnswer:", run(inp, 4))
}
func run(inp []string, dim int) int {
cs := NewCubeMapFromLines(inp)
for i := 0; i < 6; i++ {
next := NewCubeMap()
wrk := cs.Copy()
for _, c := range cs.ToSlice() {
wrk.AddMany(c.Neighbors(dim))
}
for _, c := range wrk.ToSlice() {
active := cs.Contains(c)
cnt := 0
for _, n := range c.Neighbors(dim) {
if cs.Contains(n) {
cnt++
}
}
if cnt == 3 || (active && cnt == 2) {
next.Add(c)
}
}
cs = next
}
return cs.Size()
}
type Cube struct {
X, Y, Z, W int
}
func (c Cube) Neighbors(d int) []Cube {
ret := []Cube{}
for dx := -1; dx <= 1; dx++ {
for dy := -1; dy <= 1; dy++ {
for dz := -1; dz <= 1; dz++ {
for dw := -(d - 3); dw <= d-3; dw++ {
if dx == 0 && dy == 0 && dz == 0 && dw == 0 {
continue
}
ret = append(ret, Cube{c.X + dx, c.Y + dy, c.Z + dz, c.W + dw})
}
}
}
}
return ret
}
type CubeMap struct {
field map[Cube]bool
}
func NewCubeMap() *CubeMap {
return &CubeMap{map[Cube]bool{}}
}
func NewCubeMapFromLines(inp []string) *CubeMap {
cs := NewCubeMap()
for y, line := range inp {
for x, b := range line {
if b == '#' {
cs.Add(Cube{x, y, 0, 0})
}
}
}
return cs
}
func (cs *CubeMap) Add(c Cube) {
cs.field[c] = true
}
func (cs *CubeMap) AddMany(cubes []Cube) {
for _, c := range cubes {
cs.Add(c)
}
}
func (cs *CubeMap) Remove(c Cube) {
delete(cs.field, c)
}
func (cs *CubeMap) Contains(c Cube) bool {
_, ok := cs.field[c]
return ok
}
func (cs *CubeMap) Copy() *CubeMap {
field := map[Cube]bool{}
for c := range cs.field {
field[c] = true
}
return &CubeMap{field}
}
func (cs *CubeMap) Size() int {
return len(cs.field)
}
func (cs *CubeMap) ToSlice() []Cube {
ret := []Cube{}
for c := range cs.field {
ret = append(ret, Cube{c.X, c.Y, c.Z, c.W})
}
return ret
}

3
2020/day17/testinput Normal file
View File

@ -0,0 +1,3 @@
.#.
..#
###

View File

@ -72,5 +72,5 @@ func (c *Coordinate3d) GetDownCoord() *Coordinate3d {
}
}
func (c Coordinate3d) String() string {
return fmt.Sprintf("[%d, %d, %d]", c.X, c.Y, c.Z)
return fmt.Sprintf("[X:%d, Y:%d, Z:%d]", c.X, c.Y, c.Z)
}

View File

@ -24,12 +24,19 @@ func StringSliceToCoordByteMap(input []string) CoordByteMap {
}
func (m *CoordByteMap) Get(pos Coordinate) byte {
if pos.X <= m.Width && pos.Y <= m.Height {
return m.Field[pos]
if v, ok := m.Field[pos]; ok {
return v
}
return 0
}
func (m *CoordByteMap) Opt(pos Coordinate, def byte) byte {
if v, ok := m.Field[pos]; ok {
return v
}
return def
}
func (m *CoordByteMap) Put(pos Coordinate, val byte) {
m.Field[pos] = val
}
@ -44,3 +51,118 @@ func (m CoordByteMap) String() string {
}
return ret
}
// And the 3d Version
type Coord3dByteMap struct {
Field map[Coordinate3d]byte
MinX, MaxX int
MinY, MaxY int
MinZ, MaxZ int
}
func StringSliceToCoord3dByteMap(input []string) Coord3dByteMap {
ret := Coord3dByteMap{
Field: make(map[Coordinate3d]byte),
}
for y := range input {
for x := range input[y] {
ret.Put(Coordinate3d{X: x, Y: y, Z: 0}, input[y][x])
}
}
return ret
}
func (m *Coord3dByteMap) Copy() Coord3dByteMap {
ret := Coord3dByteMap{
Field: make(map[Coordinate3d]byte),
MinX: m.MinX, MaxX: m.MaxX,
MinY: m.MinY, MaxY: m.MaxY,
MinZ: m.MinZ, MaxZ: m.MaxZ,
}
for z := m.MinZ; z <= m.MaxZ; z++ {
for y := m.MinY; y <= m.MaxY; y++ {
for x := m.MinX; x <= m.MaxX; x++ {
c := Coordinate3d{X: x, Y: y, Z: z}
ret.Field[c] = m.Get(c)
}
}
}
return ret
}
func (m *Coord3dByteMap) Get(pos Coordinate3d) byte {
if _, ok := m.Field[pos]; !ok {
return 0
}
return m.Field[pos]
}
func (m *Coord3dByteMap) Opt(pos Coordinate3d, def byte) byte {
if v, ok := m.Field[pos]; ok {
return v
}
return def
}
func (m *Coord3dByteMap) Put(pos Coordinate3d, val byte) {
m.Field[pos] = val
if pos.X < m.MinX {
m.MinX = pos.X
}
if pos.X > m.MaxX {
m.MaxX = pos.X
}
if pos.Y < m.MinY {
m.MinY = pos.X
}
if pos.Y > m.MaxY {
m.MaxY = pos.Y
}
if pos.Z < m.MinZ {
m.MinZ = pos.Z
}
if pos.Z > m.MaxZ {
m.MaxZ = pos.Z
}
}
func (m *Coord3dByteMap) CountNeighbors(pos Coordinate3d, val byte) int {
var res int
for z := pos.Z - 1; z <= pos.Z+1; z++ {
for y := pos.Y - 1; y <= pos.Y+1; y++ {
for x := pos.X - 1; x <= pos.X+1; x++ {
if m.Get(Coordinate3d{X: x, Y: y, Z: z}) == val {
res++
}
}
}
}
return res
}
func (m Coord3dByteMap) Count(val byte) int {
var ret int
for z := m.MinZ; z <= m.MaxZ; z++ {
for y := m.MinY; y <= m.MaxY; y++ {
for x := m.MinX; x <= m.MaxX; x++ {
if m.Get(Coordinate3d{X: x, Y: y, Z: z}) == val {
ret++
}
}
}
}
return ret
}
func (m Coord3dByteMap) String() string {
var ret string
for z := m.MinZ; z <= m.MaxZ; z++ {
for y := m.MinY; y <= m.MaxY; y++ {
for x := m.MinX; x <= m.MaxX; x++ {
ret = ret + string(m.Field[Coordinate3d{X: x, Y: y, Z: z}])
}
ret = ret + "\n"
}
ret = ret + "\n\n"
}
return ret
}