微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将带坐标的地图转换为图形/相邻列表/相邻矩阵

如何解决如何将带坐标的地图转换为图形/相邻列表/相邻矩阵

我想将地图转换为图形/相邻列表/相邻矩阵。

例如,假设我有一张地图,@ 标记代表无法进入的墙壁,数字代表节点:

@@@@@@@
@12  5@
@@@3@@@
@4    @
@@@@@@@

节点坐标:

1: (1,3)
2: (2,3)
3: (3,2)
4: (1,1)
5: (5,3)

这个问题的输出应该是这样的图:

1-2-5
  \ /
   3
   |
   4

1 只能连接到 2,因为 2 是 1 可以在不经过其他节点的情况下到达的唯一节点。 2可以连接1、3、5,原因同上。

给出了墙和节点坐标。我想要一种算法将任何给定的地图转换为像上面那样的图形。任何人都可以提出解决方案吗?

解决方法

您可以使用递归查找地图中数字之间的连接,即使它们彼此不直接相邻:

from functools import reduce as rd
s = """
@@@@@@@
@12  5@
@@@3@@@
@4    @
@@@@@@@
"""
#convert the map to a coordinate dictionary
coords = {(k,j):b for j,a in enumerate(filter(None,s.split('\n'))) for k,b in enumerate(a)}
def to_graph(start,seen = []):
   t_coords = [lambda x,y:(x+1,y),lambda x,y+1),y:(x,y:(x-1,y-1),y-1)]
   #find possible valid squares to consume
   if (ops:=[k for f in t_coords if (k:=(f(*start))) in coords and coords[k] != '@']):
      #recursively check possible squares
      results = [to_graph(i,seen+[start]) for i in ops if i not in seen]
      vals = rd(lambda x,y:{**x,**y},results,{}) #merge results
      return {coords[start]:vals} if coords[start].isdigit() else vals

print(to_graph((1,1))) #start with coordinates of any value

输出:

{'1': {'2': {'5': {},'3': {'4': {},'5': {}}}}}

输出返回一个字典,显示地图中定位的值之间的关系:1 -> 2,2 -> (5,3),3 -> (4,5)

,

这是另一种解决方案,即使某些节点与其他节点根本没有连接,它也能工作,并且内存成本更低:

def getNodes(l):
    a={}
    for i in range(len(l)):
        for j in range(len(l[i])):
            if (type(l[i][j]) is type(1)):
                a.update({l[i][j]:(i,j)})
    return a

def searchAdjascentNodes(m,coordonates):
    nodes=set()
    old=set()
    toDo=set([coordonates])
    while (len(toDo)!=0):
        discoveredVertices=[]
        for i in toDo:
            adjascent=[j for j in [(i[0],i[1]+1),(i[0],i[1]-1),(i[0]+1,i[1]),(i[0]-1,i[1])] if (j[0]>=0 and j[0]<len(m) and j[1]>=0 and j[1]<len(m[0]) and j not in old and j not in toDo and j not in discoveredVertices)]
            for a in adjascent:
                if(type(m[a[0]][a[1]]) is int):
                    nodes.add(m[a[0]][a[1]])
                elif(m[a[0]][a[1]]==' '):
                    discoveredVertices.append(a)
        old=toDo.copy()
        toDo=set(discoveredVertices)
    return nodes

def createGraph(m):
    n=getNodes(m)
    r={}
    for i in n:
        r.update({i:searchAdjascentNodes(m,n[i])})
    return r

你可以这样运行:

theMap=[['@','@','@'],['@',1,2,' ',5,3,4,'@']]
print(createGraph(theMap))

你会得到: {1: {2},2: {1,5},5: {2,3},3: {2,4: {3}}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。