From 4ed10852e1d03f3c932ebaec6df2094da42ff9a6 Mon Sep 17 00:00:00 2001 From: omagdy Date: Sun, 15 Dec 2024 20:46:51 +0200 Subject: Day 15 part 2 done. --- 2024/go/input/day15_3.test | 9 +++ 2024/go/src/day15/main.go | 146 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 2024/go/input/day15_3.test (limited to '2024') diff --git a/2024/go/input/day15_3.test b/2024/go/input/day15_3.test new file mode 100644 index 0000000..6ee6098 --- /dev/null +++ b/2024/go/input/day15_3.test @@ -0,0 +1,9 @@ +####### +#...#.# +#.....# +#..OO@# +#..O..# +#.....# +####### + += 1; i-- { + // swaps blocks backwares input.warehouse[nx+dx*(i-1)][ny+dy*(i-1)], input.warehouse[nx+dx*(i)][ny+dy*(i)] = input.warehouse[nx+dx*(i)][ny+dy*(i)], input.warehouse[nx+dx*(i-1)][ny+dy*(i-1)] } input.warehouse[nx][ny], input.warehouse[robotPos.x][robotPos.y] = input.warehouse[robotPos.x][robotPos.y], input.warehouse[nx][ny] @@ -115,11 +141,110 @@ func simulate(input Input) Grid { return input.warehouse } +func getBlocksToMove(pos Point, dir byte, blocksToMove *map[Point]bool, warehosue Grid) { + dirMap := map[byte]Point{ + '<': {0, -1}, + '>': {0, 1}, + '^': {-1, 0}, + 'v': {1, 0}, + } + x, y := pos.x, pos.y + (*blocksToMove)[pos] = true + dx, dy := dirMap[dir].x, dirMap[dir].y + if warehosue[x][y] == '[' { + if !(*blocksToMove)[Point{x, y + 1}] { + getBlocksToMove(Point{x, y + 1}, dir, blocksToMove, warehosue) + } + if isBlock(x+dx, y+dy, warehosue) { + getBlocksToMove(Point{x + dx, y + dy}, dir, blocksToMove, warehosue) + } + } else if warehosue[x][y] == ']' { + if !(*blocksToMove)[Point{x, y - 1}] { + getBlocksToMove(Point{x, y - 1}, dir, blocksToMove, warehosue) + } + if isBlock(x+dx, y+dy, warehosue) { + getBlocksToMove(Point{x + dx, y + dy}, dir, blocksToMove, warehosue) + } + } + +} + +func copySlice(src [][]byte) [][]byte { + dest := make([][]byte, len(src)) + for i, inner := range src { + if inner != nil { + dest[i] = make([]byte, len(inner)) + copy(dest[i], inner) + } + } + return dest +} + +func canMove(blocksToMove map[Point]bool, delta Point, warehouse Grid) bool { + for b := range blocksToMove { + x, y := b.x, b.y + nx, ny := x+delta.x, y+delta.y + if isWall(nx, ny, warehouse) { + return false + } + } + return true +} + +func simulateWide(input Input) Grid { + dirMap := map[byte]Point{ + '<': {0, -1}, + '>': {0, 1}, + '^': {-1, 0}, + 'v': {1, 0}, + } + w, h := len(input.warehouse), len(input.warehouse[0]) + robotPos := getRobotsPos(input.warehouse) + for _, dir := range input.directions { + dx, dy := dirMap[dir].x, dirMap[dir].y + nx, ny := robotPos.x+dx, robotPos.y+dy + // fmt.Printf("dir: %v\n", string(dir)) + // printGrid(input.warehouse) + // fmt.Println() + if inBounds(nx, ny, w, h) && !isWall(nx, ny, input.warehouse) { + if input.warehouse[nx][ny] == '.' { + input.warehouse[nx][ny], input.warehouse[robotPos.x][robotPos.y] = input.warehouse[robotPos.x][robotPos.y], input.warehouse[nx][ny] + robotPos.x = nx + robotPos.y = ny + } else if isBlock(nx, ny, input.warehouse) { + blocksToMove := make(map[Point]bool) + if isBlock(nx, ny, input.warehouse) { + getBlocksToMove(Point{nx, ny}, dir, &blocksToMove, input.warehouse) + if canMove(blocksToMove, dirMap[dir], input.warehouse) { + copiedWarehouse := copySlice(input.warehouse) + for b := range blocksToMove { + copiedWarehouse[b.x][b.y] = '.' + } + for b := range blocksToMove { + copiedWarehouse[b.x+dx][b.y+dy] = input.warehouse[b.x][b.y] + } + input.warehouse = copiedWarehouse + for p := range blocksToMove { + delete(blocksToMove, p) + } + input.warehouse[nx][ny] = input.warehouse[robotPos.x][robotPos.y] + input.warehouse[robotPos.x][robotPos.y] = '.' + robotPos.x = nx + robotPos.y = ny + + } + } + } + } + } + return input.warehouse +} + func sumGpsCoordinates(warehouse Grid) int { ans := 0 for i, row := range warehouse { for j, cell := range row { - if cell == 'O' { + if cell == 'O' || cell == '[' { ans += i*100 + j } } @@ -129,15 +254,16 @@ func sumGpsCoordinates(warehouse Grid) int { func solve_part_one(data string) int { input := parseInput(data) - // printGrid(input.warehouse) - // printDirs(input.directions) - // fmt.Println() - warehosue := simulate(input) - return sumGpsCoordinates(warehosue) + warehouse := simulate(input) + return sumGpsCoordinates(warehouse) } func solve_part_two(data string) int { - return 42 + input := parseInput(data) + warehouse := constructWideWarehouse(input.warehouse) + input.warehouse = warehouse + simualtedWareHouse := simulateWide(input) + return sumGpsCoordinates(simualtedWareHouse) } func main() { @@ -145,6 +271,6 @@ func main() { prod := FileRead("../input/day15.prod") fmt.Println("Part_1 test: ", solve_part_one(test)) fmt.Println("Part_1 prod: ", solve_part_one(prod)) - // fmt.Println("Part_2 test: ", solve_part_two(test)) - // fmt.Println("Part_2 prod: ", solve_part_two(test)) + fmt.Println("Part_2 test: ", solve_part_two(test)) + fmt.Println("Part_2 prod: ", solve_part_two(prod)) } -- cgit v1.2.3