Related
Consider all arrays of l non-negative integers in the range 0,...,m. I would like to iterate (using a generator) over only those whose sum is exactly s.
For example, take l=7, s=5, m=4, the iteration could look like:
(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)
(0, 0, 0, 0, 1, 2, 2)
(0, 0, 0, 0, 1, 3, 1)
(0, 0, 0, 0, 1, 4, 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)
I don't mind which order the iteration happens in but I would like it to be efficient.
A really dumb way to reproduce the above that is far too slow for larger values of the variables is:
import itertools
s = 5
l = 7
m = 5
for arr in itertools.product(range(m), repeat=l):
if sum(arr) == s:
print(arr)
Think of the problem this way, you want to put s balls in l buckets with no more than m balls in any one bucket.
Since I know how to add one ball at a time, my instinct is to solve this using recursion. The base case is putting 0 balls instead of s and to go from one step to the next, adding 1 ball to each of the buckets that currently have less than m balls in them.
To make sure it's actually possible to complete the recursion, we first check there is enough places to put the balls.
# this helper function tells us the last non zero index in an array
def last_non_zero(arr):
indx = -1
while arr[indx] == 0 and indx > -len(arr):
indx -= 1
return len(arr) + indx
def balls_in_buckets(num_balls, num_buckets, max_balls):
assert num_buckets * max_balls >= num_balls, f"You can't put {num_balls} balls in {num_buckets} buckets without more than {max_balls} in a bucket."
if num_balls == 0:
yield ([0]*num_buckets).copy()
else:
for array in balls_in_buckets(num_balls - 1, num_buckets, max_balls):
for bucket_number in range(last_non_zero(array), num_buckets):
if array[bucket_number] < max_balls:
array_copy = array.copy()
array_copy[bucket_number] += 1
yield array_copy
Edit: Added code to remove duplicates
Edit: Performance improvement, takes about 2 seconds to generate the whole sequence for l=14, s=10, m=8. There are 1,143,870 items in the sequence.
What you are looking for are called "partitions". Unfortunately, there's some ambiguity as to whether "partitions" refers to splitting a set into partitions (e.g. [a,b,c] into [[a,b],[c]]), just the numbers characterizing size of each split (e.g. [2,1]), or the count of how many different splitting there are. The most promising search terms I found were "partition a number into k parts python", yielding Python Integer Partitioning with given k partitions and "python partition of indistinguishable items" yielding Partition N items into K bins in Python lazily . Those answers focus on partitions with at least one element, while you allow partitions to include zero elements. In addition, you seem to care about the order within a partition. For instance, you list (0, 0, 0, 0, 0, 1, 4), (0, 0, 0, 0, 0, 4, 1), and (0, 0, 0, 0, 1, 0, 4) as distinct partitions, while traditionally those would be considered equivalent.
I think the best way is to iterate through the buckets, and for each one iterate through the possible values. I changed the parameter names; l, s, and m and not very informative names, and "sum" and "max" are built-in functions. My current version, which may need more debugging:
def get_partitions(length, total, upper_bound):
if length == 1:
if total > upper_bound:
return []
return [[total]]
if total == 0:
return [[0]*length]
return [ [n]+sub_partition for
n in range(min(total, upper_bound)+1) for
sub_partition in get_partitions(
length-1, total-n, upper_bound)]
Side note: I initially read "iterate over the arrays" as meaning "go through the elements of the array". I think that the proper terminology is "iterate over the set of such arrays". When you say "iterate over x", x is being treated as the iterable, not the elements of the iterable.
By modyfing this answer, taking into account max_value:
def sums(length, total_sum, max_value):
if length == 1:
yield (total_sum,)
else:
for value in range(max(0, total_sum - (length - 1) * max_value),
min(max_value, total_sum) + 1):
for permutation in sums(length - 1, total_sum - value, max_value):
yield (value,) + permutation
L = list(sums(7,5, 4))
print('total permutations:',len(L))
# First and last 10 of list
for i in L[:10] + ['...'] + L[-10:]:
print(i)
total permutations: 455
(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)
(0, 0, 0, 0, 1, 2, 2)
(0, 0, 0, 0, 1, 3, 1)
(0, 0, 0, 0, 1, 4, 0)
(0, 0, 0, 0, 2, 0, 3)
...
(3, 1, 0, 0, 1, 0, 0)
(3, 1, 0, 1, 0, 0, 0)
(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)
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)]
Here, i have 6 lists, all of them has same length of data. one is time which contains time from one start point to one end point and another five list contains signals.
time = [11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67]
A = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
B = [0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2]
C = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
D = [0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2]
E = [0, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
Here first i want to compare list A and B. if in list A 0 comes and in the same index 2 comes in B and if it is True then in second condition check in the same index in other three list there C should be 0, D should be 0 and E should be 1. if this condition satisfy then it is passed but in case in some point it comes different value then i need the start time and end time.
or j in range(len(time)):
lis = []
lis2 = []
for i in range(len(A)):
if(A[i] == 0 and B[i] == 2):
if C == 0 and D == 0 and E == 1:
lis.append(time[i])
else:
lis2.append(time[i])
print lis
print lis2
Using this code i've got the time where it is not satisfying but this isn't what i want.
i want the start time and end time like this
OUTPUT - [33,42] or [33,34,35,36,37,38,39,40,41,42]
Because in this time period 1st condition is True and from where it fails 2nd condition from there it should print the time till 1st condition True like i've given in output, then no need to check further.
Thank You In Advance.
I think this is what you want.
or j in range(len(time)):
lis = []
lis2 = []
bool = false
for i in range(len(A)):
if bool:
break
if(A[i] == 0 and B[i] == 2):
if C == 0 and D == 0 and E == 1:
lis.append(time[i])
else:
bool = true
lis2.append(time[i])
print lis
print lis2
Using numpy, you can do the following:
import numpy as np
A = np.array(A)
B = np.array(B)
C = np.array(C)
D = np.array(D)
E = np.array(E)
time = np.array(time)
print time[(A == 0)*(B == 2)*(C == 0)*(D == 0)*(E == 1)]
By the way, your example is wrong. The correct result is [32, 34, 35, 36, 37, 39, 40, 48, 49, 50, 51, 52], thus there are two periods with the correct pattern (from 31 to 40 and from 48 to 52).
I am very new with python and am struggling in creating a matrix that expresses the longest common substring. I am looking for a result like this: LCS matrix
This is my code so far.
def compute_lcs(X, Y):
m = len(X)
n = len(Y)
# An (m) times (n) matrix
matrix = [[0] * (n) for _ in range(m)]
for i in range(1, m):
for j in range(1, n):
if X[i] == Y[j]:
if i == 0 or j == 0:
matrix[i][j] = 1
else:
matrix[i][j] = matrix[i-1][j-1]+1
else:
matrix[i][j] = 0
return matrix
b = compute_lcs('AACTGGCAG','TACGCTGGA')
for y in b:
print (y)
Current Output:
[0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 1, 1, 1, 1, 1, 0]
[0, 1, 0, 2, 0, 2, 2, 2, 0]
[0, 1, 2, 1, 3, 0, 3, 3, 0]
[0, 1, 2, 0, 2, 4, 0, 0, 0]
[0, 1, 2, 0, 1, 3, 0, 0, 0]
[0, 1, 0, 3, 0, 2, 4, 1, 0]
[0, 0, 2, 1, 4, 1, 3, 5, 0]
[0, 1, 1, 0, 2, 5, 0, 0, 0]
Expected Output:
[0, 0, 0, 1, 0, 0, 0, 0, 0]
[1, 1, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 2, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 1, 1, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 2, 0, 0]
[0, 0, 0, 2, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 3, 1, 0, 0, 0]
[0, 0, 0, 0, 1, 4, 0, 0, 1]
[1, 1, 0, 0, 0, 0, 0, 1, 0]
However my result is a matrix that shows incorrect values. When I do the matrix by hand, the correct output looks like this: Correct output. I feel like my logic makes sense, what am I doing incorrectly?
Thanks everyone.
First off, to make things clear, the longest common subsequence problem is not the same as the longest common substring problem. What you're trying to solve is the latter; better not to confuse the two.
Secondly, your else branches are not aligned under the appropriate if conditions.
Whenever the strings match X[i] == Y[j], we set the matrix element to 1 if the index i or j is 0 since i-1 or j-1 at 0 gives -1 (unfortunately, this is also the index for last item in Python) which is not what we want, otherwise we increment for higher indices i, j > 1.
Thirdly, your looping should start at 0 not 1 since we start from the first characters in the strings which are at indices 0:
def compute_lcs(X, Y):
m = len(X)
n = len(Y)
# An (m) times (n) matrix
matrix = [[0] * n for _ in range(m)]
for i in range(0, m):
for j in range(0, n):
if X[i] == Y[j]:
if i == 0 or j == 0:
matrix[i][j] = 1
else:
matrix[i][j] = matrix[i-1][j-1]+1
else:
matrix[i][j] = 0
return matrix
To get the exact matrix shown in the expected output, you should swap the order of the arguments or transpose the matrix before printing. Note however that these are not necessary (swapping or transposing) and only serve for formatting purposes:
b = compute_lcs('TACGCTGGA', 'AACTGGCAG')
for y in b:
print (y)
[0, 0, 0, 1, 0, 0, 0, 0, 0]
[1, 1, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 2, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 1, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 2, 0, 0]
[0, 0, 0, 2, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 3, 1, 0, 0, 1]
[0, 0, 0, 0, 1, 4, 0, 0, 1]
[1, 1, 0, 0, 0, 0, 0, 1, 0]
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]