Day 15. part 2.
This commit is contained in:
parent
6593658d36
commit
0dc1aeebed
|
@ -1,6 +1,8 @@
|
||||||
package day_15
|
package day_15
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,7 +11,10 @@ const (
|
||||||
Player = '@'
|
Player = '@'
|
||||||
Box = 'O'
|
Box = 'O'
|
||||||
Empty = '.'
|
Empty = '.'
|
||||||
|
WideBoxL = '['
|
||||||
|
WideBoxR = ']'
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
InstUp = '^'
|
InstUp = '^'
|
||||||
InstDown = 'v'
|
InstDown = 'v'
|
||||||
|
@ -19,6 +24,12 @@ const (
|
||||||
|
|
||||||
type Warehouse [][]rune
|
type Warehouse [][]rune
|
||||||
|
|
||||||
|
func (w Warehouse) Print() {
|
||||||
|
for _, line := range w {
|
||||||
|
fmt.Println(string(line))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w Warehouse) At(x, y int) rune {
|
func (w Warehouse) At(x, y int) rune {
|
||||||
if x < 0 || y < 0 || x >= len(w[0]) || y >= len(w) {
|
if x < 0 || y < 0 || x >= len(w[0]) || y >= len(w) {
|
||||||
return Wall
|
return Wall
|
||||||
|
@ -57,7 +68,31 @@ func SolveBasic(input string) int {
|
||||||
|
|
||||||
// task:https://adventofcode.com/2024/day/12#part2
|
// task:https://adventofcode.com/2024/day/12#part2
|
||||||
func SolveComplex(input string) int {
|
func SolveComplex(input string) int {
|
||||||
return 0
|
warehouse, instructions, rX, rY := loadWide(input)
|
||||||
|
|
||||||
|
for _, instr := range instructions {
|
||||||
|
switch instr {
|
||||||
|
case InstUp:
|
||||||
|
rX, rY = moveWideUp(warehouse, rX, rY)
|
||||||
|
case InstDown:
|
||||||
|
rX, rY = moveWideDown(warehouse, rX, rY)
|
||||||
|
case InstLeft:
|
||||||
|
rX, rY = moveWideLeft(warehouse, rX, rY)
|
||||||
|
case InstRight:
|
||||||
|
rX, rY = moveWideRight(warehouse, rX, rY)
|
||||||
|
default:
|
||||||
|
panic("unknown instruction " + string(instr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum := 0
|
||||||
|
for y, line := range warehouse {
|
||||||
|
for x, val := range line {
|
||||||
|
if val == WideBoxL {
|
||||||
|
sum += y*100 + x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
func load(input string) (Warehouse, []rune, int, int) {
|
func load(input string) (Warehouse, []rune, int, int) {
|
||||||
|
@ -77,6 +112,32 @@ func load(input string) (Warehouse, []rune, int, int) {
|
||||||
return warehouse, instructions, rX, rY
|
return warehouse, instructions, rX, rY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadWide(input string) (Warehouse, []rune, int, int) {
|
||||||
|
substrings := strings.Split(input, "\n\n")
|
||||||
|
warehouse := Warehouse{}
|
||||||
|
rX := 0
|
||||||
|
rY := 0
|
||||||
|
for y, line := range strings.Split(substrings[0], "\n") {
|
||||||
|
line = expandLine(line)
|
||||||
|
if strings.ContainsRune(line, Player) {
|
||||||
|
rY = y
|
||||||
|
rX = strings.IndexRune(line, Player)
|
||||||
|
}
|
||||||
|
warehouse = append(warehouse, []rune(line))
|
||||||
|
}
|
||||||
|
instructions := []rune(strings.ReplaceAll(substrings[1], "\n", ""))
|
||||||
|
|
||||||
|
return warehouse, instructions, rX, rY
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandLine(line string) string {
|
||||||
|
line = strings.ReplaceAll(line, "#", "##")
|
||||||
|
line = strings.ReplaceAll(line, ".", "..")
|
||||||
|
line = strings.ReplaceAll(line, "@", "@.")
|
||||||
|
line = strings.ReplaceAll(line, "O", "[]")
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
|
||||||
func moveUp(warehouse Warehouse, x int, y int) (int, int) {
|
func moveUp(warehouse Warehouse, x int, y int) (int, int) {
|
||||||
if warehouse.At(x, y-1) == Wall {
|
if warehouse.At(x, y-1) == Wall {
|
||||||
return x, y
|
return x, y
|
||||||
|
@ -160,3 +221,139 @@ func moveRight(warehouse Warehouse, x int, y int) (int, int) {
|
||||||
}
|
}
|
||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func moveWideUp(warehouse Warehouse, x int, y int) (int, int) {
|
||||||
|
if warehouse.At(x, y-1) == Wall {
|
||||||
|
return x, y
|
||||||
|
} else if warehouse.At(x, y-1) == Empty {
|
||||||
|
warehouse[y][x] = Empty
|
||||||
|
warehouse[y-1][x] = Player
|
||||||
|
return x, y - 1
|
||||||
|
} else {
|
||||||
|
type Point struct {
|
||||||
|
x, y int
|
||||||
|
}
|
||||||
|
checkable := []Point{{x, y}}
|
||||||
|
|
||||||
|
for i := 0; i < len(checkable); i++ {
|
||||||
|
p := checkable[i]
|
||||||
|
l := warehouse.At(p.x, p.y-1)
|
||||||
|
if l == Wall {
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
if l == WideBoxL {
|
||||||
|
if !slices.Contains(checkable, Point{p.x, p.y - 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x, p.y - 1})
|
||||||
|
}
|
||||||
|
if !slices.Contains(checkable, Point{p.x + 1, p.y - 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x + 1, p.y - 1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if l == WideBoxR {
|
||||||
|
if !slices.Contains(checkable, Point{p.x, p.y - 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x, p.y - 1})
|
||||||
|
}
|
||||||
|
if !slices.Contains(checkable, Point{p.x - 1, p.y - 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x - 1, p.y - 1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := len(checkable) - 1; i >= 0; i-- {
|
||||||
|
p := checkable[i]
|
||||||
|
warehouse[p.y-1][p.x] = warehouse[p.y][p.x]
|
||||||
|
warehouse[p.y][p.x] = Empty
|
||||||
|
}
|
||||||
|
return x, y - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveWideDown(warehouse Warehouse, x int, y int) (int, int) {
|
||||||
|
if warehouse.At(x, y+1) == Wall {
|
||||||
|
return x, y
|
||||||
|
} else if warehouse.At(x, y+1) == Empty {
|
||||||
|
warehouse[y][x] = Empty
|
||||||
|
warehouse[y+1][x] = Player
|
||||||
|
return x, y + 1
|
||||||
|
} else {
|
||||||
|
type Point struct {
|
||||||
|
x, y int
|
||||||
|
}
|
||||||
|
checkable := []Point{{x, y}}
|
||||||
|
|
||||||
|
for i := 0; i < len(checkable); i++ {
|
||||||
|
p := checkable[i]
|
||||||
|
l := warehouse.At(p.x, p.y+1)
|
||||||
|
if l == Wall {
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
if l == WideBoxL {
|
||||||
|
if !slices.Contains(checkable, Point{p.x, p.y + 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x, p.y + 1})
|
||||||
|
}
|
||||||
|
if !slices.Contains(checkable, Point{p.x + 1, p.y + 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x + 1, p.y + 1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if l == WideBoxR {
|
||||||
|
if !slices.Contains(checkable, Point{p.x, p.y + 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x, p.y + 1})
|
||||||
|
}
|
||||||
|
if !slices.Contains(checkable, Point{p.x - 1, p.y + 1}) {
|
||||||
|
checkable = append(checkable, Point{p.x - 1, p.y + 1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := len(checkable) - 1; i >= 0; i-- {
|
||||||
|
p := checkable[i]
|
||||||
|
warehouse[p.y+1][p.x] = warehouse[p.y][p.x]
|
||||||
|
warehouse[p.y][p.x] = Empty
|
||||||
|
}
|
||||||
|
return x, y + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveWideLeft(warehouse Warehouse, x int, y int) (int, int) {
|
||||||
|
if warehouse.At(x-1, y) == Wall {
|
||||||
|
return x, y
|
||||||
|
} else if warehouse.At(x-1, y) == Empty {
|
||||||
|
warehouse[y][x] = Empty
|
||||||
|
warehouse[y][x-1] = Player
|
||||||
|
return x - 1, y
|
||||||
|
} else {
|
||||||
|
newX := x - 1
|
||||||
|
for ; warehouse.At(newX, y) == WideBoxL || warehouse.At(newX, y) == WideBoxR; newX-- {
|
||||||
|
}
|
||||||
|
if warehouse.At(newX, y) == Empty {
|
||||||
|
for tx := newX; tx < x-1; tx++ {
|
||||||
|
warehouse[y][tx] = warehouse[y][tx+1]
|
||||||
|
}
|
||||||
|
warehouse[y][x-1] = Player
|
||||||
|
warehouse[y][x] = Empty
|
||||||
|
return x - 1, y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveWideRight(warehouse Warehouse, x int, y int) (int, int) {
|
||||||
|
if warehouse.At(x+1, y) == Wall {
|
||||||
|
return x, y
|
||||||
|
} else if warehouse.At(x+1, y) == Empty {
|
||||||
|
warehouse[y][x] = Empty
|
||||||
|
warehouse[y][x+1] = Player
|
||||||
|
return x + 1, y
|
||||||
|
} else {
|
||||||
|
newX := x + 1
|
||||||
|
for ; warehouse.At(newX, y) == WideBoxL || warehouse.At(newX, y) == WideBoxR; newX++ {
|
||||||
|
}
|
||||||
|
if warehouse.At(newX, y) == Empty {
|
||||||
|
for tx := newX; tx > x+1; tx-- {
|
||||||
|
warehouse[y][tx] = warehouse[y][tx-1]
|
||||||
|
}
|
||||||
|
warehouse[y][x+1] = Player
|
||||||
|
warehouse[y][x] = Empty
|
||||||
|
return x + 1, y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
|
@ -22,5 +22,5 @@ func TestBasicSolutionExample01(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComplexSolutionExample(t *testing.T) {
|
func TestComplexSolutionExample(t *testing.T) {
|
||||||
helpers.Check(t, day_15.SolveComplex, helpers.Format(ExampleData), 0)
|
helpers.Check(t, day_15.SolveComplex, helpers.Format(ExampleData01), 9021)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue