2020 Day 17 Complete
This commit is contained in:
parent
6c0a8593c9
commit
4ca404b3c6
@ -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
8
2020/day17/input
Normal file
@ -0,0 +1,8 @@
|
||||
....###.
|
||||
#...####
|
||||
##.#.###
|
||||
..#.#...
|
||||
##.#.#.#
|
||||
#.######
|
||||
..#..#.#
|
||||
######.#
|
115
2020/day17/main.go
Normal file
115
2020/day17/main.go
Normal 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
3
2020/day17/testinput
Normal file
@ -0,0 +1,3 @@
|
||||
.#.
|
||||
..#
|
||||
###
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user