Reputation: 85
I'm trying to make a function to find the highest score in a directed graph. I do have a start node and can't go throught the same node twice. I've tried to use recursive to get the sum of values until I hit one end node. Then I would call back my function to the start node and try other option ultil I hit another. And so on.
My problem is that when i return to a node with more than one path, the score value for this node is the sum of all paths it can take. And I only want the sum of one specific path.
Here is my code so far:
caminho = list()
def maxscore(start, parentals, score):
global caminho
parentals += start + '|'
if len(graph[start]) > 0:
for i in graph[start]:
if i not in parentals.split('|'):
value = graph[start][i]
if value:
score += value
func = maxscore(i, parentals, score)
else:
continue
if func[0] > score:
score = func[0]
caminho = parentals.split('|')
return score, caminho
else:
return score, start
graph = {
'a': {'b': 2, 'c': 4},
'b': {'d': 5},
'c': {'a': 1, 'e': 3},
'd': {'f': 4},
'e': {'b': 2, 'f': 3, 'g': 2},
'f': {},
'g': {}
}
print(maxscore('a', '', 0))
How could I make it work to return in the end only the best score with the path(caminho) it took.
Sorry if I couldn't make myself clear enough. Feel free to ask any questions.
Upvotes: 3
Views: 1426
Reputation: 80329
Here is an approach:
def maxscore(start, path, score):
best_score = -1
best_i = None
best_path = None
current_path = path + [start]
for i in graph[start]:
if not i in path:
score_i, path_i = maxscore(i, current_path, score + graph[start][i])
if score_i > best_score:
best_score = score_i
best_i = i
best_path = path_i
if best_i is None:
return score, current_path
else:
return best_score, best_path
graph = {
'a': {'b': 2, 'c': 4},
'b': {'d': 5},
'c': {'a': 1, 'e': 3},
'd': {'f': 4},
'e': {'b': 2, 'f': 3, 'g': 2},
'f': {},
'g': {}
}
print(maxscore('a', [], 0))
Output:
(18, ['a', 'c', 'e', 'b', 'd', 'f'])
Notes:
maxscore()
after testing all possible edges.PS: After revising the code, it can be shortened a bit. best_i
is not really needed, and the test if best_i is None
can be replaced by if best_path is None
.
Also, if you need the path in the string form, you can print("|".join(best_path)).
Upvotes: 1
Reputation: 21
You probably want to send the score variable by value, but you are sending it by reference, therefore all the possible paths' scores are added to it.
This is my approach:
def maxscore(start, parentals, score):
newParentals = parentals + start + '|'
print newParentals, score
scores = []
if graph[start]:
for nextNode in graph[start]:
if nextNode not in newParentals.split('|'):
scores.append(maxscore(nextNode, newParentals, score + graph[start][nextNode]))
return sorted(scores)[-1]
else:
return score
graph = {
'a': {'b': 2, 'c': 4},
'b': {'d': 5},
'c': {'a': 1, 'e': 3},
'd': {'f': 4},
'e': {'b': 2, 'f': 3, 'g': 2},
'f': {},
'g': {}
}
print(maxscore('a', '', 0))
And this is what gets printed:
a| 0
a|c| 4
a|c|e| 7
a|c|e|b| 9
a|c|e|b|d| 14
a|c|e|b|d|f| 18
a|c|e|g| 9
a|c|e|f| 10
a|b| 2
a|b|d| 7
a|b|d|f| 11
18
You can see how it checks all possible paths, and then picks the highest score :D
Upvotes: 2