無向グラフしか作れません。監督されたものを作る方法がわかりません。
何か案が?
かなり長い曲がりくねった投稿をお詫びします。電車の中で暇つぶしがありました。
あなたが求めているのは、開始位置から離れたすべてのパスを表す有向グラフだと思います (任意の開始/終了位置を解決するために使用できる迷路のグラフ表現とは対照的です)。
(悪意はありませんが)これは宿題のように聞こえますが、少なくとも、宿題に非常に適したタスクです。これを念頭に置いて、次のソリューションでは、パフォーマンスやエレガンスよりもシンプルさに重点を置いています。
これを行う簡単な方法の 1 つは、最初にマップをよりナビゲートしやすい形式で保存し、次に開始ノードから始めて次の手順を実行することです。
(以下の実装例を参照)
この時点で、ツリーの最上部に開始ノードがあり、葉の 1 つとして終了ノードを持つ有向非巡回グラフ (DAG)が完成します。この時点でこれを解決するのは簡単です。グラフとして表す迷路の解法については、この回答を参照してください。
グラフを作成する際に考えられる最適化は、終点が見つかったら停止することです。不完全なグラフになってしまいますが、最終的な解だけに関心があるのであれば、これは問題ではありません。
スタック (先入れ先出し) を使用すると深さ優先でグラフを構築することを意味し、キュー (先入れ先出し) を使用すると幅優先アプローチになることに注意してください。
通常、最短パスを探すことが目的の場合は、キュー (幅優先) を使用することをお勧めします。次のマップを検討してください。
START
######## ######
######## ######
### b a ######
### ## ######
### ## e ######
### c d ######
######## ######
######## END
#################
パスが深さ優先でトラバースされ、ブランチa
でたまたまa->b
前のパスをたどるa->e
と、グラフは次のようになります。
START
|
a
/ \
b e <-- end, since d already visited
|
c
|
d
\
END
ただし、幅優先のアプローチを使用すると、a->e
パスはノードd
に早く到達するため、グラフが短くなり、ソリューションが改善されます。
START
|
a
/ \
b e
| |
c d
|
END
入力例:
..........
#########.
..........
.#########
......#...
#####...#.
##...####.
##.#......
...#######
e = (0,0)
s = (8,0)
免責事項: 次のコードは、速度ではなく、わかりやすくするために書かれています。完全にテストされていないため、正確性を保証するものではありませんが、何が可能かについてのアイデアが得られるはずです。
入力ファイルが一貫してフォーマットされていることを前提としています。簡潔にするために、ほとんどのエラー チェックは省略されています。
# regex to extract start/end positions
import re
re_sepos = re.compile("""
^([se])\s* # capture first char (s or e) followed by arbitrary spaces
=\s* # equal sign followed by arbitrary spaces
\( # left parenthesis
(\d+),(\d+) # capture 2 sets of integers separated by comma
\) # right parenthesis
""", re.VERBOSE)
def read_maze(filename):
"""
Reads input from file and returns tuple (maze, start, end)
maze : dict holding value of each maze cell { (x1,y1):'#', ... }
start: start node coordinage (x1,y1)
end : end node coordinate (x2,y2)
"""
# read whole file into a list
f = open(filename, "r")
data = f.readlines()
f.close()
# parse start and end positions from last 2 lines
pos = {}
for line in data[-2:]:
match = re_sepos.match(line)
if not match:
raise ValueError("invalid input file")
c,x,y = match.groups() # extract values
pos[c] = (int(x),int(y))
try:
start = pos["s"]
end = pos["e"]
except KeyError:
raise ValueError("invalid input file")
# read ascii maze, '#' for wall '.' for empty slor
# store as maze = { (x1,y1):'#', (x2,y2):'.', ... }
# NOTE: this is of course not optimal, but leads to a simpler access later
maze = {}
for line_num, line in enumerate(data[:-3]): # ignore last 3 lines
for col_num, value in enumerate(line[:-1]): # ignore \n at end
maze[(line_num, col_num)] = value
return maze, start, end
def maze_to_dag(maze, start, end):
"""
Traverses the map starting from start coordinate.
Returns directed acyclic graph in the form {(x,y):[(x1,y1),(x2,y2)], ...}
"""
dag = {} # directed acyclic graph
queue = [start] # queue of nodes to process
# repeat till queue is empty
while queue:
x,y = queue.pop(0) # get next node in queue
edges = dag[(x,y)] = [] # init list to store edges
# for each neighbour (top, bottom, left, right)
for coord in ((x,y-1), (x,y+1), (x-1,y), (x+1,y)):
if coord in dag.keys(): continue # visited before, ignore
node_value = maze.get(coord, None) # Return None if outside maze
if node_value == ".": # valid path found
edges.append(coord) # add as edge
queue.append(coord) # push into queue
# uncomment this to stop once we've found the end point
#if coord == end: return dag
return dag
if __name__ == "__main__":
maze,start,end = read_maze("l4.txt")
dag = maze_to_dag(maze, start, end)
print dag
このページは、Pythonでグラフを実装するための優れたチュートリアルを提供します。記事から、これは辞書で表されるディレクトリグラフの例です。
graph = {'A': ['B', 'C'],
'B': ['C', 'D'],
'C': ['D'],
'D': ['C'],
'E': ['F'],
'F': ['C']}
そうは言っても、 NetworkXやigraphなどの既存のグラフライブラリを調べることもできます。
既にリストがあるので、辞書の代わりに隣接行列を作成してみてください。
list_of_houses = []
directed_graph = [][]
for i in xrange(len(list_of_houses)):
for i in xrange(len(list_of_houses)):
directed_graph[i][i] = 0
次に、ある家から別の家への新しいエッジ(または接続がある場合)
directed_graph[from_house][to_house] = 1
これで完了です。house_a
からまでのエッジがあれhouse_b
ばdirected_graph[house_a][house_b] == 1
.