Related
I need to find a solution for the below problem in Python3. I tried itertools.combinations but not clear on how to do it.
Prepare a 7-digit number that sums to 5. Each digit can be between 0-4 only. Also, there can be repetitions. Valid example numbers are -
[ [2,1,1,0,0,1,0], [3,0,1,0,0,1,0], [0,0,0,4,0,0,1], [1,0,0,3,0,1,0], [1,1,1,1,0,1,0], ...... ]
As you can see, numbers may appear more than once in this list.
How can I create a list of all combinations meeting the criteria above?
You can get all that sum to 5 with:
list(p for p in itertools.product(range(5),repeat = 7) if sum(p) == 5)
This yields 455 solutions.
This function will find every combination, with repeated combinations, that sum to N:
from itertools import product
from typing import List, Tuple
def perm_n_digit_total(n_digits, total, choices) -> List[Tuple]:
return list(filter(
lambda x: sum(x) == total,
product(choices, repeat=n_digits)
))
Example:
perm_n_digit_total(3, 1, range(4))
Out[43]: [(0, 0, 1), (0, 1, 0), (1, 0, 0)]
perm_n_digit_total(7, 5, range(4))[::50]
Out[49]:
[(0, 0, 0, 0, 0, 0, 5),
(0, 0, 0, 3, 1, 1, 0),
(0, 0, 2, 0, 3, 0, 0),
(0, 1, 0, 1, 3, 0, 0),
(0, 2, 0, 0, 1, 0, 2),
(0, 4, 1, 0, 0, 0, 0),
(1, 0, 1, 1, 1, 0, 1),
(1, 1, 1, 1, 1, 0, 0),
(2, 0, 1, 0, 0, 2, 0),
(3, 1, 0, 0, 0, 1, 0)]
Here's an itertools'less recursive solution.
def find_solutions(target, numbers, depth, potential_solution=[]):
if depth == 0:
if sum(potential_solution) == target:
print(potential_solution)
return
current_sum = sum(potential_solution)
for n in numbers:
new_sum = current_sum + n
if new_sum > target:
continue
find_solutions(target, numbers, depth - 1, potential_solution + [n])
find_solutions(target=5, numbers=[0,1,2,3,4], depth=7)
Output
[0, 0, 0, 0, 0, 1, 4]
[0, 0, 0, 0, 0, 2, 3]
[0, 0, 0, 0, 0, 3, 2]
[0, 0, 0, 0, 0, 4, 1]
[0, 0, 0, 0, 1, 0, 4]
[0, 0, 0, 0, 1, 1, 3]
...
[3, 1, 1, 0, 0, 0, 0]
[3, 2, 0, 0, 0, 0, 0]
[4, 0, 0, 0, 0, 0, 1]
[4, 0, 0, 0, 0, 1, 0]
[4, 0, 0, 0, 1, 0, 0]
[4, 0, 0, 1, 0, 0, 0]
[4, 0, 1, 0, 0, 0, 0]
[4, 1, 0, 0, 0, 0, 0]
If I got it, you need something like this:
import itertools
value = [0, 1, 2, 3, 4]
p = itertools.product(value, repeat=7)
for j in list(p):
print(j)
As each digit can only take 5 unique values - you would require itertools.combinations_with_replacement -
from itertools import combinations_with_replacement
zero_four = list(range(5))
for c in combinations_with_replacement(zero_four, 7):
if sum(c) == 5:
print(c)
This will give you all possible combinations that sum to 5 but not all the permutations -
Output
(0, 0, 0, 0, 0, 1, 4)
(0, 0, 0, 0, 0, 2, 3)
(0, 0, 0, 0, 1, 1, 3)
(0, 0, 0, 0, 1, 2, 2)
(0, 0, 0, 1, 1, 1, 2)
(0, 0, 1, 1, 1, 1, 1)
To get all permutations - you can use the itertools.permutations but since your output can have repeated elements, you will need to use a set to retain only unique permutations -
for c in combinations_with_replacement(zero_four, 7):
if sum(c) == 5:
print(set(permutations(c)))
Hi guys i have this problem:
I have a list with number
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
Every time i found 0 i need to count it and know his position, but when the 0 is consecutive it count as one, for example:
Position start 5, Position end 8, Count 1
Position start 12, Position end 12, Count 2
Position start 14, Position end 14, Count 3
Position start 26, Position end 31, Count 4
This can be solved like this
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
last_was_0=False
zero_clusters=[]
for i in range(len(a)):
b=a[i]
if b==0:
if last_was_0:
zero_clusters[-1][-1]+=1
else:
zero_clusters.append([i, i])
last_was_0 = b==0
for i in range(len(zero_clusters)):
print(f'Position start {zero_clusters[i][0]}, Position end {zero_clusters[i][1]}, Count {i+1}')
but if i want to try it on two list? So doing the same thing that i do with one list but having two, and checking if the current index(the same for the two list) if are both 0
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
b= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
How can I achive the result?
I have already tried like this but it gives me as result only the first iteraction
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
b= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
last_was_0=False
zero_clusters=[]
for i in range(len(a)):
b=a[i]
c=b[i]
if b==0 and c==0:
if last_was_0:
zero_clusters[-1][-1]+=1
else:
zero_clusters.append([i, i])
last_was_0 = b==0
for i in range(len(zero_clusters)):
print(f'Position start {zero_clusters[i][0]}, Position end {zero_clusters[i][1]}, Count {i+1}')
Can someone help me achieve the same result of one list but with two??
You can iterate over the lists together uzing zip, and then use itertools groupby to group consecutive values.
Looping over that and storing the indexes where the key of the group is (0,0) will get you the result you want.
from itertools import groupby
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
b= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
zero_cluster = []
i = 0
for g, d in groupby(zip(a,b)):
data = list(d)
if g!=(0,0):
i+=len(data)
else:
zero_cluster.append((i, i+len(data)-1))
i+=len(data)
for i, cluster in enumerate(zero_cluster):
print(f'Position start {cluster[0]}, Position end {cluster[1]}, Count {i+1}')
Output
Position start 5, Position end 8, Count 1
Position start 12, Position end 12, Count 2
Position start 14, Position end 14, Count 3
Position start 16, Position end 16, Count 4
Position start 28, Position end 33, Count 5
Position start 36, Position end 36, Count 6
Position start 38, Position end 38, Count 7
Position start 40, Position end 40, Count 8
Also it might be helpful to understand what itertools groupby is doing by looking at this:
for g, d in groupby(zip(a,b)):
print(g,list(d))
Prints
(1, 1) [(1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]
(0, 0) [(0, 0), (0, 0), (0, 0), (0, 0)]
(1, 1) [(1, 1), (1, 1), (1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]
(0, 0) [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
(1, 1) [(1, 1), (1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
(0, 0) [(0, 0)]
(1, 1) [(1, 1)]
a numpy version
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
import numpy as np
def get_clusters(lst):
arr=np.array(lst)
diff=arr[:-1]-arr[1:]
starts = np.where(diff==1)
ends = np.where(diff==-1)
indices = np.vstack((starts[0]+1, ends[0])).T
return indices, diff[diff==1].size
print(get_clusters(a))
output
(array([[ 5, 8],
[12, 12],
[14, 14],
[16, 16],
[28, 33],
[36, 36],
[38, 38],
[40, 40]]), 8)
zip() is your friend when you need to compare elements of a list with it's predecessor or successor.
So you can use zip to get the starting index of each cluster of 1s and 0s. Then use zip again to combine these indexes into ranges of positions, selecting only the ranges that contain zeros.
a= [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
breaks = [i for i,(n,m) in enumerate(zip(a,a[1:]),1) if n!=m ]
positions = [ (s,e-1) for s,e in zip([0]+breaks,breaks+[len(a)]) if not a[s] ]
count = sum(e-s+1 for s,e in positions)
print(positions)
[(5, 8), (12, 12), (14, 14), (16, 16), (28, 33), (36, 36), (38, 38), (40, 40)]
print(count)
16
For two lists, you can combine them (using zip again) and apply the same solution:
x= [1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
y= [1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1]
a = [ paired != (0,0) for paired in zip(x,y) ]
breaks = [i for i,(n,m) in enumerate(zip(a,a[1:]),1) if n!=m ]
positions = [ (s,e-1) for s,e in zip([0]+breaks,breaks+[len(a)]) if not a[s] ]
count = sum(e-s+1 for s,e in positions)
print(positions)
[(5, 8), (12, 12), (14, 14), (16, 16), (28, 33), (36, 36), (38, 38), (40, 40)]
print(count)
16
If you're okay with using a library, this can be somewhat shortened using groupby from itertools:
from itertools import groupby
positions = [ (lg[0],lg[-1])
for bit,g in groupby(range(len(a)),lambda i:a[i]) if not bit
for lg in [list(g)]]
count = sum(e-s+1 for s,e in positions)
I am struggling to implement an algorithm that resolves a 2D maze array by only changing a direction once a wall or another obstacle is hit.
What it needs to do is, given the following array (where x is the start, 1 is an obstacle, g is the goal) find the shortest path by only hitting obstacles first (no changing direction of movement unless obstacle/wall is reached).
[[1, 1, 1, 1, 1]
[1, x, 0, 0, 1]
[1, 0, 0, 0, g]
[1, 1, 1, 1, 1]]
The solution should be:
[(1,1), (2,1), (2,4)]
In the example above, it moves only next to the maze walls, but that's only because the example is very small. All in all, it should only move in the 4 directions and not change its course once it starts a direction until an obstacle is met. Here is a more visual example:
I managed to find the following code that gets the length of the shortest path but does not display the path itself. Any help to get that would be very appreciated.
def shortestDistance(self, maze: List[List[int]], start: List[int], destination: List[int]):
start, destination = tuple(start), tuple(destination)
row, col = len(maze), len(maze[0])
def neighbors(maze, node):
temp = []
used = set()
used.add(node)
for dx, dy in [(-1, 0), (0, 1), (0, -1), (1, 0)]:
(x, y), dist = node, 0
while 0 <= x + dx < row and 0 <= y + dy < col and maze[x + dx][y + dy] == 0:
x += dx
y += dy
dist += 1
if (x, y) not in used:
temp.append((dist, (x, y)))
return temp
heap = [(0, start)]
visited = set()
while heap:
dist, node = heapq.heappop(heap)
if node in visited: continue
if node == destination:
return dist
visited.add(node)
for neighbor_dist, neighbor in neighbors(maze, node):
heapq.heappush(heap, (dist + neighbor_dist, neighbor))
return -1
Issue:
Usual breadth first search is too slow to solve the size of maze poster requires i.e. 24 x 24.
Algorithm & Code
Algorithm is based upon modification of wall following algorithm
Code is based upon a modified version of nerijus-st
/
Maze-Solving
Key Algorithm Modification from normal wall following
Continues to step in the same direction until we hit a wall
Create new branching paths to left and right of current direction when hit a wall in current direction
Use heap to focus on extending paths with minimum distances and number of direction changes
Code
# Modification of https://github.com/nerijus-st/Maze-Solving/blob/master/left%20hand%20rule.py
import numpy as np
import heapq
class Maze():
# Movement directions
directions = ["N", "E", "S", "W"]
def __init__(self, maze):
assert isinstance(maze, np.ndarray) # maze should be 2D numpy array
self.maze = maze
self.m, self.n = maze.shape
def solve_maze(self, start, goal):
"""
N
W E
S
UP (N) - get_neighbours()['N']
RIGHT (E) - get_neighbours()['E']
DOWN (S) - get_neighbours()['S']
LEFT (W) - get_neighbours()['W']
maze 2D Numpy array
start tuple for stating position
goal tuple for destination
Strategy: Keeps going in same direction until a wall is reached. Then try
form branches for both left and right directions (i.e. search both)
"""
# Try all starting directions
heap = [(0, 0, facing, [start]) for facing in Maze.directions]
heapq.heapify(heap)
while heap:
dist, changes, facing, path = heapq.heappop(heap)
changes = -changes # Negative to make earlier since using min heap
if path[-1] == goal:
return self.compress_path(path)
self.x, self.y = path[-1] # Set current position in maze
front_wall = self.get_front_wall(facing) # Coordinates next position in front
if front_wall and not self.maze[front_wall] and not front_wall in path: # if Clear in front
# Front direction clear
heapq.heappush(heap, (dist+1, -changes, facing, path + [front_wall]))
elif len(path) > 1:
# Try to left
left_wall = self.get_left_wall(facing) # Coordinates to the left
if left_wall and not self.maze[left_wall] and not left_wall in path: # if clear to the left
left_facing = self.rotate_facing(facing, "CCW") # Rotate left (i.e. counter clockwise)
heapq.heappush(heap, (dist+1, -(changes+1), left_facing, path + [left_wall]))
# Try to the right
right_wall = self.get_right_wall(facing) # Coordinates to the right
if right_wall and not self.maze[right_wall] and not right_wall in path: # if Clear to the right
right_facing = self.rotate_facing(facing, "CW") # Rotate right (i.e. clockwise)
heapq.heappush(heap, (dist+1, -(changes+1), right_facing, path + [right_wall]))
def compress_path(self, path):
if not path:
return
if len(path) < 3:
return path
result = [path[0]]
for i, p in enumerate(zip(path, path[1:])):
direction = self.get_direction(*p)
if i == 0:
prev_direction = direction
result.append(p[1][:])
continue
if len(result) > 2:
if prev_direction == direction:
result[-1] = p[1][:]
else:
result.append(p[1][:])
else:
result.append(p[1][:])
prev_direction = direction
return result
def get_neighbours(self):
' Neighbors of current position '
x, y = self.x, self.y
result = {}
result['N'] = (x-1, y) if x + 1 < self.m else None
result['S'] = (x+1, y) if x-1 >= 0 else None
result['E'] = (x, y+1) if y + 1 < self.n else None
result['W'] = (x, y-1) if y -1 >= 0 else None
return result
def get_direction(self, point1, point2):
x1, y1 = point1
x2, y2 = point2
if y1 == y2 and x1 - 1 == x2:
return 'N'
if y1 == y2 and x1 + 1 == x2:
return 'S'
if x1 == x2 and y1 + 1 == y2:
return 'E'
if x1 == x2 and y1 - 1 == y2:
return 'W'
def get_left_wall(self, facing):
if facing == "N":
return self.get_neighbours()['W'] # cell to the West
elif facing == "E":
return self.get_neighbours()['N']
elif facing == "S":
return self.get_neighbours()['E']
elif facing == "W":
return self.get_neighbours()['S']
def get_right_wall(self, facing):
if facing == "N":
return self.get_neighbours()['E'] # cell to the East
elif facing == "E":
return self.get_neighbours()['S']
elif facing == "S":
return self.get_neighbours()['W']
elif facing == "W":
return self.get_neighbours()['N']
def get_front_wall(self, facing):
return self.get_neighbours()[facing]
def rotate_facing(self, facing, rotation):
facindex = Maze.directions.index(facing)
if rotation == "CW":
if facindex == len(Maze.directions) - 1:
return Maze.directions[0]
else:
return Maze.directions[facindex + 1]
elif rotation == "CCW":
if facindex == 0:
return Maze.directions[-1]
else:
return Maze.directions[facindex - 1]
Test
Test 1
maze = [[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 0],
[1, 1, 1, 1, 1]]
M = Maze(np.array(maze))
p = M.solve_maze((1,1), (2,3))
print('Answer:', p)
# Output: Answer: [(1, 1), (2, 1), (2, 3)]
Test 2
maze = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1],
[1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
M = Maze(np.array(maze))
p = M.solve_maze((1,1), (23, 23))
print('Answer:', p)
# Output: Answer: [(1, 1), (1, 2), (1, 9), (3, 9), (3, 12), (5, 12), (5, 10), (7, 10), (7, 9), (17, 9), (17, 10), (23, 10), (23, 23)]
​
You could interpret it as a graph problem.
Generate a graph with all possible movements which then are the edeges and the possbile positions being the nodes. The edges should be marked with their length (or weight) (in your case maybe 6 blocks for example).
I guess the ball starts somewhere thus the question is (while thinking of graphs): Whats is the shortest path to a node u form a node v.
Therfore you can use the Bellman–Ford algorithm.
I will not explain it because wikipedia does a better job with that.
There are some more algorithms which solve you problem like the Dijkstra's algorithm if you don't like that one.
You can use a recursive generator function that at every step either continues to proceed on the same direction or changes course by finding other possible directions when it hits a wall:
graph = [[1, 1, 1, 1, 1], [1, 'x', 0, 0, 1], [1, 0, 0, 0, 'g'], [1, 1, 1, 1, 1]]
d_f = [lambda x, y:(x+1, y), lambda x, y:(x+1, y+1), lambda x, y:(x, y+1), lambda x, y:(x-1, y), lambda x, y:(x-1, y-1), lambda x, y:(x, y-1)]
def navigate(coord, f = None, path = [], s = []):
if graph[coord[0]][coord[-1]] == 'g':
yield path+[coord]
elif f is None:
for i, _f in enumerate(d_f):
if graph[(j:=_f(*coord))[0]][j[-1]] != 1 and j not in s:
yield from navigate(j, f = _f, path=path+[coord], s = s+[coord])
else:
if graph[(j:=f(*coord))[0]][j[-1]] == 1:
yield from navigate(coord, f = None, path=path, s = s)
else:
yield from navigate(j, f = f, path=path, s = s+[coord])
start = [(j, k) for j, a in enumerate(graph) for k, b in enumerate(a) if b == 'x']
r = min(navigate(start[0]), key=len)
Output:
[(1, 1), (2, 1), (2, 4)]
So this is what I have so far:
def createCombo(self):
usedAtoms = {'C':(0,101),'H':(0,201),'O':(0,4),'N':(0,4),'S':(0,4)}
MolecularFormula.combinations(self, usedAtoms)
def combinations(self,dicts):
product = [x for x in itertools.product(*[range(*x) for x in dicts.values()])]
print product
##print [dict(zip(dicts.keys(), p)) for p in product],
it ends up printing something out like this:
[(0, 0, 0, 0, 0), (0, 0, 0, 0, 1), (0, 0, 0, 0, 2), (0, 0, 0, 0, 3), (0, 0, 0, 1, 0), (0, 0, 0, 1, 1), (0, 0, 0, 1, 2), (0, 0, 0, 1, 3), (0, 0, 0, 2, 0), (0, 0, 0, 2, 1)
which is what I want it to print out, but how would I go about grabbing a certain index of an individual one in one of these products?
so like if I wanted to grab the 3 from this: (0, 0, 0, 0, 3)
?
In [1]: product = [(0, 0, 0, 0, 0), (0, 0, 0, 0, 1), (0, 0, 0, 0, 2), (0, 0, 0,
...: 0, 3), (0, 0, 0, 1, 0), (0, 0, 0, 1, 1), (0, 0, 0, 1, 2), (0, 0, 0, 1,
...: 3), (0, 0, 0, 2, 0), (0, 0, 0, 2, 1)]
In [2]: product[3][4] # get the fifth value of the fourth element of 'product'
Out[2]: 3
As i am beginner i need to find out the tuple which has only one value in it. for ex
a = [4, 0, 0, 4, 0, 0]
b = [0, 0, 0, 0, 0, 0]
d = [5, 0, 5, 0, 0, 0]
f = [0, 1, 0, 0, 0, 0]
This is lists value, by zipping it i get [(4, 0, 5, 0), (0, 0, 0, 1), (0, 0, 5, 0), (4, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)] this value.
In this i want to select which as only one value in tuples for ex my output should look like this [(0, 0, 0, 1), (4, 0, 0, 0)].
Please help me on it
Using a list comprehension:
[x for x in zipped if len(x) == x.count(0) + 1]