Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 days ago.
Improve this question
I want to make a restriction so that distances between two notes that are > 10 not to be selected . THIS CODE IS NOT MINE
This is the website from wich i found the code https://www.vtupulse.com/artificial-intelligence/implementation-of-a-star-search-algorithm-in-python/
def aStarAlgo(start_node, stop_node):
open_set = set(start_node)
closed_set = set()
g = {} #store distance from starting node
parents = {}
# parents contains an adjacency map of all nodes
#distance of starting node from itself is zero
g[start_node] = 0
#start_node is root node i.e it has no parent nodes
#so start_node is set to its own parent node
parents[start_node] = start_node
while 0 < len(open_set) :
n = None
#node with lowest f() is found
for v in open_set:
if n == None or g[v] + heuristic(v) < g[n] + heuristic(n):
n = v
if n == stop_node or Graph_nodes[n] == None:
pass
else:
for (m, weight) in get_neighbors(n):
#nodes 'm' not in first and last set are added to first
#n is set its parent
if m not in open_set and m not in closed_set:
open_set.add(m)
parents[m] = n
g[m] = g[n] + weight
#for each node m,compare its distance from start i.e g(m) to the
#from start through n node
else:
if g[m] > g[n] + weight:
#update g(m)
g[m] = g[n] + weight
#change parent of m to n
parents[m] = n
#if m in closed set,remove and add to open
if m in closed_set:
closed_set.remove(m)
open_set.add(m)
if n == None:
print('Path does not exist!')
return None
# if the current node is the stop_node
# then we begin reconstructin the path from it to the start_node
if n == stop_node :
path = []
while parents[n] != n:
path.append(n)
n = parents[n]
path.append(start_node)
path.reverse()
print('Path found: {}'.format(path))
return path
# remove n from the open_list, and add it to closed_list
# because all of his neighbors were inspected
open_set.remove(n)
closed_set.add(n)
print('Path does not exist!')
return None
#define fuction to return neighbor and its distance
#from the passed node
def get_neighbors(v):
if v in Graph_nodes:
return Graph_nodes[v]
else:
return None
#for simplicity we ll consider heuristic distances given
#and this function returns heuristic distance for all nodes
def heuristic(n):
H_dist = {
'A': 1,
'B': 1,
'C': 1,
'D': 1,
'E': 1,
'G': 1,
}
return H_dist[n]
#Describe your graph here
Graph_nodes = {
'A': [('B', 1), ('E', 5)],
'B': [('A', 1), ('C', 3), ('G', 11)],
'C': [('B', 3)],
'D': [('E', 7), ('G', 7)],
'E': [('A', 5), ('D', 7)],
'G': [('B', 9), ('D', 7)]
}
aStarAlgo('A', 'G')
This is the website from wich i found the code https://www.vtupulse.com/artificial-intelligence/implementation-of-a-star-search-algorithm-in-python/`your text``
Related
Probably this is a very stupid mistake but I can't find a solution. I have the lists below:
node_pair = [('a', 'b'), ('b', 'a')]
edge_list = [
(1, 'unuseful thing', {'orig-id': 'a'}),
(11, 'unuseful thing', {'orig-id': 'b'}),
]
I need to find the numeric couple in edge_list that is related to node_pair. For ('a', 'b') I will see (1, 11) and for ('b', 'a') I will see (11, 1). Below my code:
for pair in node_pair:
start_node = pair[0][0]
end_node = pair[1][0]
print(f'from {start_node} --> to {end_node}')
graph_start_end_node = []
for edge in edge_list:
edge_orig_id = edge[2]['orig-id']
if start_node == edge_orig_id:
edge_start_node = edge[0]
graph_start_end_node.append(edge_start_node)
if end_node == edge_orig_id:
edge_start_node = edge[0]
graph_start_end_node.append(edge_start_node)
print(graph_start_end_node)
The result is:
from a --> to b
[1, 11]
from b --> to a
[1, 11]
Using append works only when the order in the node_pair list is the same as in the edge_list, because this way the value is added at the end of the list. When the order could vary you have to place the matched value in a specific position - like:
graph_start_end_node = [None, None]
for edge in edge_list:
edge_orig_id = edge[2]['orig-id']
if start_node == edge_orig_id:
edge_start_node = edge[0]
graph_start_end_node[0] = edge_start_node
if end_node == edge_orig_id:
edge_start_node = edge[0]
graph_start_end_node[1] = edge_start_node
I found it hard to fix your code so I tried it this way.
node_pair = [('a', 'b'), ('b', 'a')]
edge_list = [
(1, 'unuseful thing', {'orig-id': 'a'}),
(11, 'unuseful thing', {'orig-id': 'b'}),
]
for pair in node_pair:
start_node, end_node = pair
print(f'from {start_node} --> to {end_node}')
graph_start_end_node = [e[0] for p in pair for e in edge_list if e[2]['orig-id'] == p ]
print(graph_start_end_node)
Make a new list with a list iteration is generally easier than trying to append to an existing one.
I create a boogle game, and I need to build a function that receives in input: the letter board (list of lists), the list of legal words and an integer n.
The function must return all n-length tracks of valid words.
For example n = 3 then the function must return all the paths on the three-length board which are actually valid words.
I wrote a code that returns in a particular example one route out of three routes that must be returned.
Input:
board1 = [['Q', 'O', 'Q', 'Q'],
['D', 'O', 'G', 'Q'],
['Q', 'O', 'Q', 'Q'],
['Q', 'Q', 'Q', 'Q']]
word_dict = {'DOG': True}
n = 3
board = Board(board1)
length_n_paths(3, board, word_dict)
My Output:
[((1, 0), (1, 1), (1, 2))]
Wanted Output:
[[(1, 0), (0, 1), (1, 2)], [(1, 0), (1, 1), (1, 2)], [(1, 0), (2, 1), (1, 2)]]
I used a combination, first I found all the possible combinations of letters of length n, then I went through a coordinate coordinate and checked if each coordinate is in a valid position according to the coordinate in front of it, and then I checked if the word coming out of the letter combination is a word from the word list.
If so - I will return its path in a list with the other legal words paths.
my code:
direct_lst=['Up','Down','Right','Left','Up_right','Up_left','Down_right','Down_left']
class Board:
def __init__(self, board):
self.board = board
def get_board_coordinate(self):
cord_lst = []
row = len(self.board)
col = len(self.board[0])
for i in range(row):
for j in range(col):
cord_lst.append((i, j))
return cord_lst
def possible_directions(self, coordinate, next_coordinate):
y, x = coordinate
directions_funcs = {
# A dictionary that matches between a letter and the direction of the desired search
'Up': (y - 1, x),
'Down': (y + 1, x),
'Right': (y, x + 1),
'Left': (y, x - 1),
'Up_right': (y - 1, x + 1),
'Up_left': (y - 1, x - 1),
'Down_right': (y + 1, x + 1),
'Down_left': (y + 1, x + 1)
}
it_ok = False
for direction in direct_lst:
if directions_funcs[direction] == next_coordinate:
it_ok = True
return it_ok
def is_valid_path(board, path, words):
word = board.board[path[0][0]][path[0][1]]
board_coordinates = board.get_board_coordinate()
for cord in range(len(path)-1):
if path[cord] in board_coordinates and path[cord+1] in board_coordinates:
if not board.possible_directions(path[cord], path[cord + 1]):
return None
else:
word += board.board[path[cord + 1][0]][path[cord + 1][1]]
else:
return None
if word in set(words):
return word
import itertools
def create_dict(board, n):
new_dict = dict()
row = len(board.board)
col = len(board.board[0])
for i in range(row):
for j in range(col):
new_dict[(i, j)] = board.board[i][j]
result_list = list(map(list, itertools.combinations(new_dict.items(), n)))
return result_list
def coordinates_lst_and_str_lst(board, n):
combine = create_dict(board, n)
all_cord_dic = dict()
for lst in combine:
is_it_ok = True
cord_lst = []
str_l = ""
for i in range(n):
cord_lst.append(lst[i][0])
str_l += lst[i][1]
try:
if not board.possible_directions(lst[i][0], lst[i + 1][0]):
is_it_ok = False
break
except IndexError:
break
if is_it_ok:
all_cord_dic[tuple(cord_lst)] = str_l
all_cord_dic[tuple(cord_lst)[::-1]] = str_l[::-1]
return all_cord_dic
def length_n_paths(n, board, words):
possible_words = coordinates_lst_and_str_lst(board, n)
my_dict = {key:val for key, val in possible_words.items() if val in words}
return list(my_dict.keys())
I think the problem is in the combination but I dont know how to fix it.
I would be happy for any help.
After debugging, it's apparent that the result possible_words does not contain the key (1, 0), (0, 1), (1, 2), so that explains why it's not part of the answer - so the question becomes why doesn't the call to coordinates_lst_and_str_lst() generate that tuple (and the other 'missing' one)
If you break after constructing combine in coordinates_lst_and_str_lst, you will find that [((1, 0), 'D'), ((0, 1), 'O'), ((1, 2), 'G')] is not in combine, this means coordinates_lst_and_str_lst can't find it as a solution.
So, the problem must be in create_dict, which apparently isn't creating all the legal moves.
And indeed, in create_dict, you use itertools.combinations(), which gives you all the unique combinations of n items from a collection, disregarding their order, but you care about the order.
So, you don't want itertools.combinations(new_dict.items(), n), you want itertools.permutations(new_dict.items(), n). Have a closer look at the difference between combinations and permutations (of size n).
I got a hard problem in python for my last question of project.
Imagine you get a file like it :
1 2
2 3
3 4
if node 1 is linked to node 2 by an edge then 2 is accessible by a path of length 1 from 1: 1-2
if 1 is linked to 2 itself to 3 and itself to 4 then 4 is accessible by a path of length 4 from 1: 1-2-3-4
I want to return the number of nodes accessible from a given node by a path of length 3 by default
thanks for advice and help !!!!
EDIT :
def bfs(graph, start_node, distance):
if distance == 0:
return [start_node]
visited = []
queue = []
nodes_at_dist = []
level = 0
visited.append(start_node)
queue.append((start_node, level))
First, we rebuild the data structure to simplify the lookup, i.e., which nodes are reachable. I assume that our graph is undirected.
graph = [(1, 2), (2, 3), (3, 4), (1, 4), (2, 6), (6, 7)]
# we restructure our input to simplify the lookup
graph_dict = {}
for n1, n2 in graph:
if n1 not in graph_dict:
graph_dict[n1] = set()
if n2 not in graph_dict:
graph_dict[n2] = set()
graph_dict[n1].add(n2)
graph_dict[n2].add(n1)
As a result, we have a dict where the keys are all existing nodes and the corresponding value is a set of all nodes which are directly connected:
{1: {2, 4}, 2: {1, 3, 6}, 3: {2, 4}, 4: {1, 3}, 6: {2, 7}, 7: {6}}
The next part is essentially our method which finds the reachable nodes in respect of a fixed distance:
def bfs(graph_dict, start_node, distance):
# We reached the end and return the current node
if distance == 0:
return {start_node}
# We look-up all nodes which are reachable with one step
reachable = graph_dict[start_node]
# Now we iterate through this set and call our method again (recursively)
result=set()
for node in reachable:
tmp=bfs(graph_dict, node, distance-1)
result=result.union(tmp)
return result
Example Output 1: distance=2, start_node=1
{1, 3, 6}
Please note that "1" is in our result set because we can walk 1-2-1 (which are two steps).
Example Output 2: distance=3, start_node=1
{2, 4, 7}
Please note that "2" is in our result set because we can walk 1-2-1-2 (which are three steps).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I want to know how can i implement a weighted undirected graph in python for map. Map have cities and some road, which link between citiies and have respective weight.
If you don't want to just use one of the available graph libraries…
A standard way of representing graphs is an adjacency list. You can implement this as a dictionary where the keys are node names (or some other ID to lookup nodes) and the values are a list of edges. The edges can be some data structure that gives you the connecting node name and a weight — anything from a tuple to a NamedTuple to a full edge class. For example here is a minimal weighted graph:
places = {
'A': set([('B', 10), ('C', 5)]),
'B': set([('D', 3), ('A', 10)]),
'C': set([('F', 20), ('G', 9), ('A', 5)]),
'D': set([('B', 3)]),
'F': set([('C', 20)]),
'G': set([('C', 9)])
}
You can tell it's undirected because each edge appears twice — in the source and the destination node's list.
This format will support the primary graph algorithms like DFS, BFS, Dijkstra...
Here's a quick and dirty depth first search:
places = {
'A': set([('B', 10), ('C', 5)]),
'B': set([('D', 3), ('A', 10)]),
'C': set([('F', 20), ('G', 9), ('A', 5)]),
'D': set([('B', 3)]),
'F': set([('C', 20)]),
'G': set([('C', 9)])
}
def findARoute(start, end, places, visited = None):
if visited is None:
visited = set()
visited.add(start)
try:
edges = places[start]
except KeyError:
return # node not in graph
for edge in edges:
node, wieght = edge
if node not in visited:
print(f'Trying {start} -> {node}')
if node == end:
print(f'Found: {end}')
return
findARoute(node, end, places, visited)
findARoute('A', 'G', places)
Prints:
Trying A -> B
Trying B -> D
Trying A -> C
Trying C -> F
Trying C -> G
Found: G
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Problem
I have to get elements from a text file to a list, diagonally, and from top to buttom. It should work on any dimension of the letters.txt. The file would look like this:
Text file: letters.txt (thought it would be hard, I removed 'Y', and 'Z' from my original post
A B C D E F
G H I J K L
M N O P Q R
S T U V W X
the lists should look like this:
topButtom_List = ['AGMS', 'BHNT', 'CIOU', 'DJPV', 'EKQW', 'FLRX']
bLeftToURight = ['A', 'GB', 'MHC', 'SNID', 'TOJE', 'UPKF', 'VQL', 'WR', 'X']
My current code for top to buttom:
# top to buttom
topButtom_List = [] #should be ['AGMS', 'BHNT', 'CIOU', 'DJPV', 'EKQW', 'FLRX']
openFile = open("letters.txt")
for i in openFile:
i = i.replace(" ","")
length = len(i)
openFile.close()
openFile = open("letters.txt")
counter = 0
for eachIterration in range(length):
for line in openFile:
line = line.replace(" ","")
# counter should be added by 1 each time inner loop itterates x4, and outter loop x1.
topButtom_List.append(line[counter])
counter = counter + 1
openFile.close()
What I was trying to do with the code above:
I was trying to get the top to buttom characters from the text file and get it in a list called topButtom_List. I used counter to define the index that for every iteration the outer loop does, the index would be added by 1. The way I see it is, the outerloop will start, the inner loop will iterate x4 adding AGMS in the topButtom_List on the first iteration, the outer loop will iterate again and add 1 to counter. BHNTZ will be added on the second iteration and so on, the outer loop will iterate again and add 1 to counter.
From the text file: letters.txt
I want to populate topButtom_List
Output I am getting:
['A', 'G', 'M', 'S']
Expected output:
['AGMS', 'BHNT', 'CIOU', 'DJPV', 'EKQW', 'FLRX']
#!/usr/bin/python3
field = """A B C D E F
G H I J K L
M N O P Q R
S T U V W X"""
arr = [col.split(' ') for col in [row.strip() for row in field.split('\n')]]
len_x, len_y = len(arr[0]), len(arr)
len_all = len_x + len_y - 1
lines, groups = [], []
for i in range(len_all):
start = (i, 0) if i < len_y else (len_y-1, i-len_y+1)
end = (0, i) if i < len_x else (i-len_x+1, len_x-1)
lines.append([start, end])
print('List of start and end points: ', lines)
for start, end in lines:
group = ''
for i in range(len_x):
y, x = start[0] - i, start[1] + i
if y >= 0 and y < len(arr) and x < len(arr[y]):
group += arr[y][x]
else:
groups.append(group)
break
print(groups)
Returns
List of start and end points: [[(0, 0), (0, 0)], [(1, 0), (0, 1)],
[(2, 0), (0, 2)], [(3, 0), (0, 3)], [(3, 1), (0, 4)], [(3, 2), (0, 5)],
[(3, 3), (1, 5)], [(3, 4), (2, 5)], [(3, 5), (3, 5)]]
and
['A', 'GB', 'MHC', 'SNID', 'TOJE', 'UPKF', 'VQL', 'WR', 'X']