Codingame“儿童游戏”过程超时

时间:2019-10-31 15:33:11

标签: python-3.x

我正在尝试使用python解决A child's play上的编码挑战Codingame。 使用我的程序,我可以通过前两个测试用例,但是当测试需要大量循环时,我的程序将超时。我可以改善什么?

要完全理解问题,需要提供挑战的详细信息,但由于不确定是否允许,我不想在此处复制和粘贴挑战。

我试图用我的话来解释这个问题。鉴于此输入:

12 6
987
...#........
...........#
............
............
..#O........
..........#.
  • O是字符的起点。
  • #是您无法踩到的墙
  • .是角色可以踩到的地方

在此示例中,w = 12(矩阵的宽度)和h = 6(矩阵的高度)。 n = 987是角色必须采取的步骤数。

必需的输出

在这种情况下,7 1在给定移动次数之后字符的位置

规则

  • 角色总是从向上移动开始
  • 遇到墙时,角色会顺时针旋转并保持移动
  • 放置壁是为了使角色不会卡住,也不会离开矩阵。

当我用那个测试用例运行程序时,我得到正确的结果。

改为使用以下测试用例:

14 10
123456789
..#...........
....#..#......
.#O.....#.....
..............
..............
.......##...#.
............#.
.#........###.
.#.#..........
..............

我得到:

失败 进程已超时。这可能意味着您的解决方案不够优化,无法处理某些情况。

这是我设法编写的代码:

import math
import sys


def find_initial_position(maze, w, h):
    for i in range(0, h):
        for j in range(0,w):
            if maze[i][j] == "O":
                return [i, j]

    return -1


def can_move(maze, direction, x, y):

    if direction == "U":
        if maze[ x -1 ][ y ] == "#":
            return False
    elif direction == "R":
        if maze[ x ][ y + 1 ] == "#":
            return False
    elif direction == "D":
        if maze[ x +1 ][ y ] == "#":
            return False
    elif direction == "L":
        if maze[ x ][ y-1 ] == "#":
            return False

    return True


def turn_clockwise(direction):
    directions = ["U", "R", "D", "L"]
    return directions[ (directions.index(direction) + 1) % 4 ]


def move(direction, coordinates):
    if direction == "U":
        coordinates[0] -=1
    elif direction == "R":
        coordinates[1] +=1
    elif direction == "D":
        coordinates[0] +=1
    elif direction == "L":
        coordinates[1] -=1


def main():
    w, h = [int(i) for i in input().split()]
    n = int(input())

    maze = []
    direction = "U"
    position = [0, 0]

    for i in range(h):
        line = input()
        maze.append(line)

    position = find_initial_position(maze, w, h)

    for i in range(0, n):
        while not can_move(maze, direction, position[0], position[1]):
            direction = turn_clockwise(direction)

        move(direction, position)

    print( "%(x)d %(y)d" %{"x": position[1], "y": position[0]} )


main()

1 个答案:

答案 0 :(得分:0)

我通过以下方式简化了代码,使代码更具可读性:

  • 利用numpy的矩阵乘法进行顺时针旋转90°;
  • 使用内置的str.index()查找初始位置。

以下结果... 但是,确实,这没有说明重点。

如果您在所有测试用例中都看到“迷宫”,则说明是“机器人”以矩形模式(也可能是更复杂的模式)在四个#障碍物之间循环弹跳。因此,使用您的方法,您正在计算和重新计算相同的短步动作,数百万亿次。即使最长的循环不可能有比小迷宫中的平方数(数量级)更多的移动。

您应该尝试做的是连续记录到目前为止已完成的所有移动(位置,方向)。而且,如果(或者更确切地说,是何时)您最终到达了以前所处的位置(方向),那么您已经完成了一个完整的周期。无需计算更多的移动。假设您的循环序列的长度为 L ,并且规定的移动总数为 n ,那么最终位置将为序列元素编号 L { {3}} n (或类似的东西,尽管出现了一个错误)。

import sys
import numpy as np


def is_obstacle(maze, position):
    return maze[position[0]][position[1]] == '#'


def main():
    w, h = [int(i) for i in input().split()]
    n = int(input())

    # Load maze
    maze = []
    for i in range(h):
        line = input()
        maze.append(line)
        if 'O' in line:
            # Found initial position
            position = np.array([i, line.index('O')])

    # Initial direction
    direction = np.array([-1,0])

    # Define actions
    turn_clockwise = np.array([[0,-1],[1,0]])

    # Walk maze
    for i in range(n):
        while is_obstacle(maze, position + direction):
            direction = direction @ turn_clockwise
        position = position + direction

    print( "%(x)d %(y)d" %{"x": position[1], "y": position[0]} )


main()