I want to simplify an if: .. else: ..
construct:
def find_eulerian_tour(graph):
available_edges, path = initial_state(graph)
while incomplete(available_edges):
edge = propose_extension_edge(available_edges, path)
if extension_is_possible(edge):
extend_path(available_edges, path, edge)
else:
node = propose_node_for_reorder(available_edges, path)
if reorder_is_sensible(node):
path = reorder_path(available_edges, path, node)
else:
return None
return path
It seems unnecessarily complicated, because the idea can be expressed much simpler.
def find_eulerian_tour(graph):
available_edges, path = initial_state(graph)
while incomplete(available_edges):
if extension_is_possible(available_edges, path):
extend_path(available_edges, path)
elif reorder_is_sensible(available_edges, path):
path = reorder_path(available_edges, path)
else:
return None
return path
But now I have to do the calculations from
edge = propose_extension_edge(available_edges, path)
and
node = propose_node_for_reorder(available_edges, path)
twice because I can't keep the results in variables (edge = .., node = ..).
I am looking for an idea to keep code as simple as it is with the elif
construction while doing the propose_node..
-calculation only once.
def find_eulerian_tour(graph):
available_edges, path = initial_state(graph)
while incomplete(available_edges):
edge = propose_extension_edge(available_edges, path)
if extension_is_possible(edge):
extend_path(available_edges, path, edge)
else:
node = propose_node_for_reorder(available_edges, path)
if reorder_is_sensible(node):
path = reorder_path(available_edges, path, node)
else:
return None
return path
def initial_state(graph):
available, path = graph[:], []
if len(available) > 0:
path.append(available[0][0])
return available, path
def incomplete(available_edges):
return len(available_edges) > 0
def propose_extension_edge(available_edges, path):
last_node = path[-1]
for edge in available_edges:
if last_node in edge:
return edge
return None
def extension_is_possible(edge):
return edge
def extend_path(available_edges, path, edge):
if edge[0] == path[-1]:
path.append(edge[1])
else:
path.append(edge[0])
available_edges.remove(edge)
def propose_node_for_reorder(available_edges, path):
if reorder_is_possible(path):
return find_split(available_edges, path)
return None
def reorder_is_possible(path):
return is_tour(path)
def find_split(available_edges, path):
options = edgenodes(available_edges)
for node in options:
if node in path:
return node
return None
def reorder_is_sensible(node):
return node
def is_tour(path):
return path[0] == path[-1]
def edgenodes(edges):
result = []
for edge in edges:
for node in edge:
if not node in result:
result.append(node)
return result
def reorder_path(available_edges, tour, split):
split_location = tour.index(split)
return tour[split_location:-1] + tour[0:split_location+1]
Example use:
graph1 = [(1, 2), (2, 3), (3, 1)]
graph2 = [(0, 1), (1, 5), (1, 7), (4, 5), (4, 8), (1, 6), (3, 7), (5, 9), (2, 4), (0, 4), (2, 5), (3, 6), (8, 9)]
graph3 = [(1, 13), (1, 6), (6, 11), (3, 13), (8, 13), (0, 6), (8, 9),(5, 9), (2, 6), (6, 10), (7, 9), (1, 12), (4, 12), (5, 14), (0, 1), (2, 3), (4, 11), (6, 9), (7, 14), (10, 13)]
print find_eulerian_tour(graph1)
print find_eulerian_tour(graph2)
print find_eulerian_tour(graph3)