How do I write O(n2) program of matrix n x n? - python

I am practicing and trying to write O(n^2) program that tests whether there are two 1s lying on the same row or the same column in A. Where A = n x n matrix of 0s and 1s.
Given A as:
I should get answer return of 2 matches.
One is on the 1st row, and another on the 3rd column.
My 2nd Attempt:
def testLines():
count = 0
for x in range( 0, len(A)-1 ):
if( (A[x] == 1) & (A[x+1] == 1) ):
count+=1
for y in range( 0, len(A)-1):
if( (A[y] == 1 & A[y+1]) == 1 ):
count+=1
print( count, '1s has been matched in the array A')
testLines()

You want to nest the two loops and change the indexes so that both x and y are parsed. Currently your code moves through (all x, y = 0) and (x = 0, all y).
A = [[0, 0, 1, 1],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 1, 0]]
def testLines():
count = 0
N = len(A)
for x in range(N):
for y in range(N):
if A[x][y] == 1:
if x+1 < N and A[x+1][y] == 1:
count += 1
if y+1 < N and A[x][y+1] == 1:
count += 1
print(count, '1s has been matched in the array A')
testLines()
Alternatively, you can go the Schwarzenegger way and not check if (x+1, y) or (x, y+1) even exist. That will raise IndexErrors that you can choose to ignore.
def testLines():
count = 0
N = len(A)
for x in range(N):
for y in range(N):
try:
if A[x][y] == 1 and A[x+1][y] == 1 or A[x][y+1] == 1:
count += 1
except IndexError:
continue
print(count, '1s has been matched in the array A')

You can run one nested loop (n²) to get summation of rows. If summation is 2 then that row has two 1s.
Now interchange rows and columns(consider rows as columns & vice versa).
Again run nested loop (n²) to check summation of columns.
n²+n²= O(n²)

Related

find 1's in the row

I have a task to do:
a = [0,1,0,1,0,0,1,1,1,1,0]
I have the list - a - randomly generated each time the program runs.
Task 1: find the longest 1-row (here it is [1,1,1,1]) and output its starting index number.
Task 2: find 1,1 in a; how many times it occurs? 1,1,1 doesn't count, only exact matches are taken into account.
a = [1,0,0,1,1,0,1,1,1,1]
counter = 1
for i in range(len(a)):
if a[i] == 1:
a[i] = counter
counter += 1
print(a)
b = []
one_rows = []
for i in a:
if i > 0:
one_rows.append(i)
if i == 0:
b.append([one_rows])
one_rows.clear()
print(b)
If I've understood your question right, you can use can use itertools.groupby to group the list and count the number of 1s:
a = [0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0]
max_len, double_ones, max_idx = float("-inf"), 0, 0
for v, g in groupby(enumerate(a), lambda k: k[1]):
if v == 1:
idxs = [i for i, _ in g]
double_ones += len(idxs) == 2
if len(idxs) > max_len:
max_len = len(idxs)
max_idx = idxs[0]
print("Longest 1-row:", max_len, "Index:", max_idx)
print("How many 1,1:", double_ones)
Prints:
Longest 1-row: 4 Index: 6
How many 1,1: 0

Leetcode Number of Closed Islands Question (Python)

I'm trying to find the solution for Leetcode question #1254, finding the number of closed islands.
Given a 2D grid consists of 0s (land) and 1s (water). An island is a maximal 4-directionally connected group of 0s and a closed island is an island totally (all left, top, right, bottom) surrounded by 1s.
The way I want to solve this problem is by using a boolean value that decides whether an island has any corner values.
I understand that passing a boolean value as an argument to a function that manipulates its value does not work since it is a local variable.
However, for some reason, the code that I found from geeksforgeeks uses the same method, but it works while mine keeps giving a wrong result.
The following is my code and the one at the bottom is from geeksforgeeks.
class Solution:
def closedIsland(self, grid: List[List[int]]) -> int:
numOfRow, numOfCol = len(grid), len(grid[0])
if numOfRow == 0 or grid == None: return 0
counter = 0
def dfs(row, col, hasCorner):
if not(0 <= row < numOfRow and 0 <= col < numOfCol):
return
if grid[row][col] == 2 or grid[row][col] == 1:
return
else:
if (row == 0 or row == numOfRow -1 or col == 0 or col == numOfCol - 1):
hasCorner = True
grid[row][col] = 2
if numOfRow > row >= 0 and numOfCol > col >= 0 and grid[row][col]:
dfs(row - 1, col, hasCorner)
dfs(row + 1, col, hasCorner)
dfs(row, col - 1, hasCorner)
dfs(row, col + 1, hasCorner)
for row in range(len(grid)):
for col in range(len(grid[0])):
if grid[row][col] == 0:
hasCorner = False
dfs(row, col, hasCorner)
if (hasCorner == False):
counter += 1
print(grid)
return counter
# Python3 program for the above approach
# DFS Traversal to find the count of
# island surrounded by water
def dfs(matrix, visited, x, y, n, m, hasCornerCell):
# If the land is already visited
# or there is no land or the
# coordinates gone out of matrix
# break function as there
# will be no islands
if (x < 0 or y < 0 or
x >= n or y >= m or
visited[x][y] == True or
matrix[x][y] == 0):
return
if (x == 0 or y == 0 or
x == n - 1 or y == m - 1):
if (matrix[x][y] == 1):
hasCornerCell = True
# Mark land as visited
visited[x][y] = True
# Traverse to all adjacent elements
dfs(matrix, visited, x + 1, y, n, m, hasCornerCell)
dfs(matrix, visited, x, y + 1, n, m, hasCornerCell)
dfs(matrix, visited, x - 1, y, n, m, hasCornerCell)
dfs(matrix, visited, x, y - 1, n, m, hasCornerCell)
# Function that counts the closed island
def countClosedIsland(matrix, n, m):
# Create boolean 2D visited matrix
# to keep track of visited cell
# Initially all elements are
# unvisited.
visited = [[False for i in range(m)]
for j in range(n)]
result = 0
# Mark visited all lands
# that are reachable from edge
for i in range(n):
for j in range(m):
if ((i != 0 and j != 0 and
i != n - 1 and j != m - 1) and
matrix[i][j] == 1 and
visited[i][j] == False):
# Determine if the island is closed
hasCornerCell = False
# hasCornerCell will be updated to
# true while DFS traversal if there
# is a cell with value '1' on the corner
dfs(matrix, visited, i, j,
n, m, hasCornerCell)
# If the island is closed
if (not hasCornerCell):
result = result + 1
# Return the final count
return result
# Driver Code
# Given size of Matrix
N, M = 5, 8
# Given Matrix
matrix = [ [ 0, 0, 0, 0, 0, 0, 0, 1 ],
[ 0, 1, 1, 1, 1, 0, 0, 1 ],
[ 0, 1, 0, 1, 0, 0, 0, 1 ],
[ 0, 1, 1, 1, 1, 0, 1, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 1 ] ]
# Function Call
print(countClosedIsland(matrix, N, M))
# This code is contributed by divyeshrabadiya07
Please help me find what I'm missing here

Check if a Python list has X number of consecutive values equal to Y

I have a collection of lists each containing 16 items, and I want to find lists with 12 consecutive values either > or < than a specified threshold. For now, I have iterated through the lists and put 1 for values greater and -1 for values less than the threshold, and I used to following to eliminate those that don't have 12 of either.
if list.count(-1) >= 12 or list.count(1) >= 12:
How do I efficiently check for 12 consecutive values? (12 values can loop around) for example this would count
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1]
Currently I have 2 nested for loops, but I know this checks the same value multiple times.
for i in range(16):
light = 0
dark = 0
for j in range(12):
index = i + j
if index > 15:
index -= 15
if list[index] == 1:
light += 1
elif list[index] == -1:
dark += 1
else:
break
if dark > 0 and light > 0:
break
if dark == 12 or light == 12:
return True
I would harness itertools.groupby following way
import itertools
data = [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1]
runs = [len(list(g)) for _,g in itertools.groupby(data)]
if data[0] == data[-1]:
runs[0] += runs.pop()
print(max(runs) >= 12) # True
Explanation: I use itertools.groupby to get length of runs (in this case [7,4,5]) - itertools.groupby does group only adjacent equal elements, then if first and last values of data are equal I extract last element from runs and add it to first element (as you allow wraparound), then I check if longest run is equal or greater 12.
If I've understood correctly what you want, then here are some ways to do it:
First off you can sort the list, putting every element in an order, and then doing a linear search and incrementing a counter every time it's the same value with the previous list element
a.sort()
count = 0
for i in range(16):
if count == 12:
break
if a[i - 1] == a[i]:
count += 1
Another way to do it is with the modulo operator, which doesn't require you sorting the list. And you can add some variables to check if you've done a full loop.
flag_count = 0
count = 0
i = 0
while True:
if count == 12 or flag_count == 2:
break
if a[i % 15] == a[(i + 1) % 15]:
count += 1
if i % 15 == 0:
flag_count += 1
i += 1
You can loop through the list while keeping track how many times you've seen a specific value. Everytime you see a different value this counter resets (because you are looking for consecutive values).
def consective_values(input_list, target_value):
i = 0
count = 0
for _ in range(2 * len(input_list)):
if input_list[i] == target_value:
count += 1
else:
count = 0
if count == 12:
return True
i = (i + 1) % len(input_list)
return False
Because the consecutive values can loop around you have to be a bit more careful with the list indexing and the loop variable. The max number of loops is equal to twice the length of the list. When you still haven't found 12 consecutive values at this point you know there aren't any. TO have an index loop around a list you can always apply the modulo (%) operator

How to compare with .index cell by cell in python

Y = [1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1,]
X = [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ]
Di = []
for number in Y: # as for each number in Y
if number > 0: # and the number if more than 0
if number in X: # compare to the numbers in X
if number not in Di: # when in cases of number found not in X
Di.append(number) # Add to the Di
print("Di",Di) #print the letters Di and the value of the number 1 found
if Di == [1]: # Condition #if the value is equal to 1 print excluded
print("excluded") # Clause #print excluded
else:
print("not excluded")
Output
Di --> excludeed #because of digit 5 counting 0
The above code is from a python program that try to compare the 1 or 0 where it works as follow find the first value that is 0 in Y list and compare it with the value in the same position in the list X and if found positive exclude if not found negative go to the next 0 in the list Y and so on when the list is finished and could not exclude any print not excluded. hope this make sense but it is not doing its Function. if someone can modify it for me with .index to make the expected function this would make my life much happier.
kind regards
Basem
Y = [1, 1, 0, 1, 0]
X = [0, 0, 1, 0, 0]
def excluder(yVal, xVal):
for count, ele in enumerate(yVal):
print("Current Y list value in this loop cycle:" + str(ele))
if yVal[count] > xVal[count]:
print(str(yVal[count]), " is greater in the Y list")
elif yVal[count] < xVal[count]:
print(str(xVal[count]), " is greater in the X list")
else:
print(str(xVal[count]), " X and Y are equal")
excluder(Y, X)
Output below....I included an enumerate function because it is a good way to get the count in a loop without having to increment a variable.
Current Y list value in this loop cycle:1
1 is greater in the Y list
Current Y list value in this loop cycle:1
1 is greater in the Y list
Current Y list value in this loop cycle:0
1 is greater in the X list
Current Y list value in this loop cycle:1
1 is greater in the Y list
Current Y list value in this loop cycle:0
0 X and Y are equal

Programming Maze Solution recursively

This function is intended to recursively navigate a maze and find the length of the shortest path. The path itself is not necessary, only the length. The maze is represented by a 2d list with values such as
0 1 0 0 0
0 0 0 1 0
0 0 0 1 0
The user starts at (0,0) and must end up at the end of the maze as defined (in my case it is the bottom right cell). 1's represent walls.
def maze(x,y,array,length):
m = len(array)
n = len(array[0])
if x < 0 or y < 0 or x == m or y == n or array[x][y] == 1:
return float("inf")
elif x == m - 1 and y == n - 1:
return length
else:
array[x][y] = 1
up = maze(x - 1,y,array,length + 1)
right = maze(x,y + 1,array,length + 1)
down = maze(x + 1,y,array,length + 1)
left = maze(x,y - 1,array,length + 1)
return min(up,down,left,right)
array = [[0,1,0,0,0],[0,0,0,1,0],[0,0,0,1,0]]
minLength = maze(0,0,array,1)
print(minLength)
I designed it so that it recursively finds all possible paths from each direction (up, down, left and right), and returns the lowest value from all these paths with each step of the way. It returns inf for any path that is not valid.
For this specific array, it returns 11, which is false, it should be 9. I do not believe it is merely a mathematical error, as I tried printing each step of the way and it is not recognizing certain paths (it returns inf for paths that most definitely have options).
I can't seem to find where my code is going wrong, it seems like it should properly return the value, but in practice it does not.
array is a reference to the original array, not a local copy. See any of the on-line tutorials on how Python passes function arguments, or how it handles lists. You can see the effect by printing array in your main program after the call to maze:
Final Maze [
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 0]
]
Fixing this is relatively easy: copy the nested list and use that copy locally.
from copy import deepcopy
def maze(x,y,array,length):
m = len(array)
n = len(array[0])
if x < 0 or y < 0 or x == m or y == n or array[x][y] == 1:
return float("inf")
elif x == m - 1 and y == n - 1:
return length
else:
new_maze = deepcopy(array)
new_maze[x][y] = 1
up = maze(x - 1,y,new_maze,length + 1)
right = maze(x,y + 1,new_maze,length + 1)
down = maze(x + 1,y,new_maze,length + 1)
left = maze(x,y - 1,new_maze,length + 1)
return min(up,down,left,right)
array = [[0,1,0,0,0],[0,0,0,1,0],[0,0,0,1,0]]
minLength = maze(0,0,array,1)
print("Final Maze", array)
print(minLength)
The output from this is (edited for readability again)
Final Maze [
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 1, 0]
]
9

Categories