通过减少循环来缩短元组列表?

2024-05-20 00:04:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个生成元组列表的函数,比如:

[(0, 0), (1, 1), (1, 2), (1,3), (2, 4), (3, 5), (4, 5)]

用于表示我正在制作的游戏中的分幅路径(行、列)。你知道吗

我用来生成这些路径的函数并不完美,因为它经常生成“循环”,如下所示:

[(2, 0), (2, 1), (1, 2), (0, 3), (0, 4), (1, 5), (2, 5), (3, 4), (3, 3),
 (3, 2), (4, 1)]

Image

上面的路径应该是这样的:

[(2, 0), (2, 1), (3, 2), (4, 1)]

Image

这些路径可以包含任意数量的循环,这些循环可以是任意大小和形状。你知道吗

所以我的问题是,如何在python中编写一个函数来剪切循环列表,并返回一个新的、较短的、没有这些循环的列表。你知道吗

我的尝试如下:

def Cut_Out_Loops(Path):

    NewList = list(Path)
    Cutting = True

    a = 0
    for Cords in Path:
        a += 1

        try:
            for i in range(a + 2, len(Path)):
                if (Path[i][0] == Cords[0] and abs(Path[i][1] - Cords[1]) == 1:
                    NewList = NewList[0:a] + NewList[i:]
                    Path = list(NewList)
                elif Path[i][1] == Cords[1] and abs(Path[i][0] - Cords[0]) == 1:
                    NewList = NewList[0:a] + NewList[i:]
                    Path = list(NewList)
                elif abs(Path[i][0] - Cords[0]) == 1 and abs(Path[i][1] - Cords[1]) == 1:
                    NewList = NewList[0:a] + NewList[i:]
                    Path = list(NewList)
                elif abs(Path[i][1] - Cords[1]) == 1 and abs(Path[i][0] - Cords[0]) == 1:
                    NewList = NewList[0:a] + NewList[i:]
                    Path = list(NewList)
                Cutting = False
        except IndexError:
            Cutting = True

Tags: andpath函数in路径true游戏列表
2条回答

你的路有多长?如果它们都在1000个元素以下,即使是简单的暴力算法也可以:

path = [
    (2, 0),
    (2, 1),
    (1, 2),
    (0, 3),
    (0, 4),
    (1, 5),
    (2, 5),
    (3, 4),
    (3, 3),
    (3, 2),
    (4, 1)
]


def adjacent(elem, next_elem):
    return (abs(elem[0] - next_elem[0]) <= 1 and
            abs(elem[1] - next_elem[1]) <= 1)

new_path = []
i = 0
while True:
    elem = path[i]
    new_path.append(elem)
    if i + 1 == len(path):
        break
    j = len(path) - 1
    while True:
        future_elem = path[j]
        if adjacent(elem, future_elem):
            break
        j -= 1
    i = j

print new_path

尽管你对“循环”的定义不太清楚,还是试试这个

def clean(path):
    path1 = []
    for (x1,y1) in path:
        for (i,(x2,y2)) in enumerate(path1[:-1]):
            if abs(x1-x2) <= 1 and abs(y1-y2) <= 1:
                path1 = path1[:i+1]
                break
        path1.append((x1,y1))
    return path1

这绝对适用于你的例子:

 >>> path = [(2, 0), (2, 1), (1, 2), (0, 3), (0, 4), (1, 5), (2, 5), (3, 4), (3, 3), (3, 2), (4, 1)]
 >>> clean(path)
 [(2, 0), (2, 1), (3, 2), (4, 1)]

也就是说,这只是最直接的暴力解决方案。复杂性是二次的。你知道吗

相关问题 更多 >