diff --git a/2020/day16/main.go b/2020/day16/main.go index 7e89e9f..028e046 100644 --- a/2020/day16/main.go +++ b/2020/day16/main.go @@ -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) diff --git a/2020/day17/input b/2020/day17/input new file mode 100644 index 0000000..9511cae --- /dev/null +++ b/2020/day17/input @@ -0,0 +1,8 @@ +....###. +#...#### +##.#.### +..#.#... +##.#.#.# +#.###### +..#..#.# +######.# diff --git a/2020/day17/main.go b/2020/day17/main.go new file mode 100644 index 0000000..7ff3d89 --- /dev/null +++ b/2020/day17/main.go @@ -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 +} diff --git a/2020/day17/testinput b/2020/day17/testinput new file mode 100644 index 0000000..eedd3d2 --- /dev/null +++ b/2020/day17/testinput @@ -0,0 +1,3 @@ +.#. +..# +### diff --git a/helpers/coordinate3d.go b/helpers/coordinate3d.go index 665bf8b..7cd50ce 100644 --- a/helpers/coordinate3d.go +++ b/helpers/coordinate3d.go @@ -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) } diff --git a/helpers/coordinateByteMap.go b/helpers/coordinateByteMap.go index 8ce0bb0..28e53a4 100644 --- a/helpers/coordinateByteMap.go +++ b/helpers/coordinateByteMap.go @@ -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 +}