Understanding print matrix in clockwise spiral in Python - python

I found this exercise to study matrices or 2d vectors in Python (I'm beginner)
'''
start row index - k
end row index - m
start column index - l
end column index - n
iterator - i
array or list - a
'''
# Python3 program to print
# given matrix in spiral form
def spiralPrint(m, n, a) :
k = 0; l = 0
''' k - starting row index
m - ending row index
l - starting column index
n - ending column index
i - iterator '''
while (k < m and l < n) :
# Print the first row from
# the remaining rows
for i in range(l, n) :
print(a[k][i], end = " ")
k += 1
# Print the last column from
# the remaining columns
for i in range(k, m) :
print(a[i][n - 1], end = " ")
n -= 1
# Print the last row from
# the remaining rows
if ( k < m) :
for i in range(n - 1, (l - 1), -1) :
print(a[m - 1][i], end = " ")
m -= 1
# Print the first column from
# the remaining columns
if (l < n) :
for i in range(m - 1, k - 1, -1) :
print(a[i][l], end = " ")
l += 1
a =[[1,2,3,4,5],
[6,7,8,9,10],
[11,12,13,14,15],
[16,17,18,19,20]]
R = 4
C = 5
spiralPrint(R,C,a)
I wanted to understand the logic behind it, I mean why they were used 4 loops to iterate and why they assigned indices as rows and columns?
Also, how does the function know exactly that at the end of the element it has to go under the second list and go around?

There are four for-loops, one for each side of the spiral.
Each iteration of the while-loop writes out one ring of the matrix. k and m control how much of each side column needs to be printed. k starts at 0 and m at the height of the matrix. Each time a top row is printed, k gets incremented by 1, so the subsequent columns to be printed start one row lower. Each time a bottom row is printed, m gets decremented by 1, so the subsequent columns to be printed stop one row higher.
Similarly, l and n control how much of each row needs to be printed, and get adjusted every time a column is printed.
Everything is easier to follow if you draw the matrix on a sheet of paper and write out k, m, l and n while you mark the parts that are being printed.
The exercise is a good illustration of how ranges work in Python.

Related

Partitioning array to k subsets using dynamic programming in python

I found this geeksforgeeks article explaining how to approach the "partitioning array into 2 subsets" problem. As the problem I am working on is a 3-partition problem, I would like to extend the logic of the code used in this article to the 3-partition problem. However, I am unsure how the 2-D array is used to determine whether the array can be partitioned into 2 subsets.
This is the description of the problem from the page:
Partition problem is to determine whether a given set can be partitioned into two subsets such that the sum of elements in both subsets is the same.
Here is the link to the page: https://www.geeksforgeeks.org/partition-problem-dp-18/
Here is the code implemented on the post:
def findPartition(arr, n):
sum = 0
i, j = 0, 0
# calculate sum of all elements
for i in range(n):
sum += arr[i]
if sum % 2 != 0:
return false
part = [[True for i in range(n + 1)]
for j in range(sum // 2 + 1)]
# initialize top row as true
for i in range(0, n + 1):
part[0][i] = True
# initialize leftmost column,
# except part[0][0], as 0
for i in range(1, sum // 2 + 1):
part[i][0] = False
# fill the partition table in
# bottom up manner
for i in range(1, sum // 2 + 1):
for j in range(1, n + 1):
part[i][j] = part[i][j - 1]
if i >= arr[j - 1]:
part[i][j] = (part[i][j] or
part[i - arr[j - 1]][j - 1])
return part[sum // 2][n]
I understand that the 2 for loops traverse the table row by row, column by column and the default value for the current cell is the value of the cell to the left of it (meaning, the number is assumed not to be added to the subset).
for i in range(1, sum // 3 + 1):
for j in range(1, n + 1):
part[i][j] = part[i][j - 1]
The if condition ensures that the current number does not exceed the target value of sum // 2
if i >= arr[j - 1]:
This leads me to my question: Using this code, at the bottom rightmost cell (whose value we return to the main function) wouldn't the code just check if sum // k can be obtained for the at least 1 subset? How can we assume that sum // k can be achieved for all subsets based on this? This is because we are unsure about which numbers from the array have been used and if any numbers across the subarrays overlap.
part[i][j] = (part[i][j] or part[i - arr[j - 1]][j - 1])
I have also found a similar solution for the 3-partition problem posted by rishabh1005 on github (link: https://github.com/rishabh1005/Algorithmic-Toolbox/blob/master/week6_dynamic_programming2/2_partitioning_souvenirs/partition3.py). However, he implements a counter to check if the value of each cell is equal to the target value of sum // k. The counter is incremented each time a cell is equal to sum // k.
if count<3: return 0
else: return 1
However, I am similar unsure about the final if conditions he used. Why can the array be partitioned into 3 subsets if the counter value is > 3?
Thanks everyone for your help.

I was asked to make a program in python to check whether a sorting algorithm is stable or not. Need some help regarding that

So I decided to approach this problem by creating another array (lets say arraycount) with the same length of the input array(lets say arraynumber) which is to be sorted. For the program to really check the stability of the sorting function, I decided to use test cases of integer array of repeated occurrences eg arraynumber = {10,8,7,8,2,2,2,1,6}. I then use a function to calculate the occurrences of the number in the array and store them in the arraycount[] which will result as arraycount={1,1,1,2,1,2,3,1,1}.
Naturally after sorting in increasing order they become arraynumber={1,2,2,2,6,7,8,8,10} and the result of the arraycount decides that its stable or not. Hence if its stable arraycount={1,1,2,3,1,1,1,2,1} otherwise it won't be same.
This is the code I have been working on. Help and feedback is appreciated. Main function and input is not taken yet. I will take another array copy of the original arraycount which will be compared afterward to check if it's retained the original position. Sorry if I made any trivial mistakes. Thank you.
def merge(arr1, l, m, r,arr2):
n1 = m - l + 1
n2 = r- m
# create temp arrays
L = [0] * (n1)
R = [0] * (n2)
# Copy data to temp arrays L[] and R[]
for i in range(0 , n1):
L[i] = arr1[l + i]
for j in range(0 , n2):
R[j] = arr1[m + 1 + j]
# Merge the temp arrays back into arr[l..r]
i = 0 # Initial index of first subarray
j = 0 # Initial index of second subarray
k = l # Initial index of merged subarray
while i < n1 and j < n2 :
if L[i] <= R[j]:
arr1[k] = L[i]
arr2[k]=L[i]
i += 1
else:
arr1[k] = R[j]
arr2[k]=R[j]
j += 1
k += 1
# Copy the remaining elements of L[], if there
# are any
while i < n1:
arr1[k] = L[i]
arr2[k]=L[i]
i += 1
k += 1
# Copy the remaining elements of R[], if there
# are any
while j < n2:
arr1[k] = R[j]
arr2[k]=R[j]
j += 1
k += 1
# l is for left index and r is right index of the
# sub-array of arr to be sorted
def mergeSort(arr1,l,r,arr2):
if l < r:
# Same as (l+r)/2, but avoids overflow for
# large l and h
m = (l+(r-1))/2
# Sort first and second halves
mergeSort(arr1, l, m,arr2)
mergeSort(arr1, m+1, r,arr2)
merge(arr1, l, m, r,arr2)
# This function takes last element as pivot, places
# the pivot element at its correct position in sorted
# array, and places all smaller (smaller than pivot)
# to left of pivot and all greater elements to right
# of pivot
def partition(arr1,low,high,arr2):
i = ( low-1 ) # index of smaller element
pivot = arr1[high] # pivot
for j in range(low , high):
# If current element is smaller than or
# equal to pivot
if arr1[j] <= pivot:
# increment index of smaller element
i = i+1
arr1[i],arr1[j] = arr1[j],arr1[i]
arr2[i],arr2[j]=arr2[j],arr2[i]
arr1[i+1],arr1[high] = arr1[high],arr1[i+1]
arr2[i+1],arr2[high]=arr2[high],arr2[i+1]
return ( i+1 )
# The main function that implements QuickSort
# arr1[] --> Array to be sorted,
# arr2[] --> Second Array of the count to be sorted along with first array
# low --> Starting index,
# high --> Ending index
# Function to do Quick sort
def quickSort(arr1,low,high,arr2):
if low < high:
# pi is partitioning index, arr[p] is now
# at right place
pi = partition(arr1,low,high,arr2)
# Separately sort elements before
# partition and after partition
quickSort(arr1, low, pi-1,arr2)
quickSort(arr1, pi+1, high,arr2)
def countArray(arr1,arr2):
i=0,j=1,k=0
while i<range(len(arr1[])):
while j<range(len(arr1[])):
if arr1[i]==arr1[j]:
arr2[i]=k+1
j=j+1
k=0
i=i+1
arraylist=[]
arraycount=[]
def isStable(arr1,arr2):
k=0
while i < range(len(arr1[])):
if arr[i]==arr2[i]:
k=k+1
i=i+1
if k==len(arr2):
print("Stable sort")
else:
print("Unstable sort")

How to iterate over (N-1) elements?

I want to iterate over N-1 elements in the for loop in python. For example, N=20, I want to start with the second element 2,3...20.
I have tried putting range(N-1), but it excludes the last element, ​not the first one.
for i in range(N):
delta = (2 * np.random.rand(3) - 1) * max_delta
trial[i] += delta
You can use:
for i in range(1, N):
The first parameter dictates which index to start from, with the second indicating the termination point.
Small note: The second element would have i = 1, not i = 2!
start should be 2, and end should n + 1
it should be range(2,n+1).
n = 20
start = 2 # first element in the loop (inclusive)
stop = n + 1 # stops before this number (exclusive)
# prints 2 to 20
for i in range(start, stop):
print(i)

Algorithm for itertools.combinations in Python

I was solving a programming puzzle involving combinations. It led me to a wonderful itertools.combinations function and I'd like to know how it works under the hood. Documentation says that the algorithm is roughly equivalent to the following:
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = list(range(r))
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
I got the idea: we start with the most obvious combination (r first consecutive elements). Then we change one (last) item to get each subsequent combination.
The thing I'm struggling with is a conditional inside for loop.
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
This experession is very terse, and I suspect it's where all the magic happens. Please, give me a hint so I could figure it out.
The loop has two purposes:
Terminating if the last index-list has been reached
Determining the right-most position in the index-list that can be legally increased. This position is then the starting point for resetting all indeces to the right.
Let us say you have an iterable over 5 elements, and want combinations of length 3. What you essentially need for this is to generate lists of indexes. The juicy part of the above algorithm generates the next such index-list from the current one:
# obvious
index-pool: [0,1,2,3,4]
first index-list: [0,1,2]
[0,1,3]
...
[1,3,4]
last index-list: [2,3,4]
i + n - r is the max value for index i in the index-list:
index 0: i + n - r = 0 + 5 - 3 = 2
index 1: i + n - r = 1 + 5 - 3 = 3
index 2: i + n - r = 2 + 5 - 3 = 4
# compare last index-list above
=>
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
break
This loops backwards through the current index-list and stops at the first position that doesn't hold its maximum index-value. If all positions hold their maximum index-value, there is no further index-list, thus return.
In the general case of [0,1,4] one can verify that the next list should be [0,2,3]. The loop stops at position 1, the subsequent code
indices[i] += 1
increments the value for indeces[i] (1 -> 2). Finally
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
resets all positions > i to the smallest legal index-values, each 1 larger than its predecessor.
This for loop does a simple thing: it checks whether the algorithm should terminate.
The algorithm start with the first r items and increases until it reaches the last r items in the iterable, which are [Sn-r+1 ... Sn-1, Sn] (if we let S be the iterable).
Now, the algorithm scans every item in the indices, and make sure they still have where to go - so it verifies the ith indice is not the index n - r + i, which by the previous paragraph is the (we ignore the 1 here because lists are 0-based).
If all of these indices are equal to the last r positions - then it goes into the else, commiting the return and terminating the algorithm.
We could create the same functionality by using
if indices == list(range(n-r, n)): return
but the main reason for this "mess" (using reverse and break) is that the first index from the end that doesn't match is saved inside i and is used for the next level of the algorithm which increments this index and takes care of re-setting the rest.
You could check this by replacing the yields with
print('Combination: {} Indices: {}'.format(tuple(pool[i] for i in indices), indices))
Source code has some additional information about what is going on.
The yeild statement before while loop returns a trivial combination of elements (which is simply first r elements of A, (A[0], ..., A[r-1])) and prepares indices for future work.
Let's say that we have A='ABCDE' and r=3. Then, after the first step the value of indices is [0, 1, 2], which points to ('A', 'B', 'C').
Let's look at the source code of the loop in question:
2160 /* Scan indices right-to-left until finding one that is not
2161 at its maximum (i + n - r). */
2162 for (i=r-1 ; i >= 0 && indices[i] == i+n-r ; i--)
2163 ;
This loop searches for the rightmost element of indices that hasn't reached its maximum value yet. After the very first yield statement the value of indices is [0, 1, 2]. Therefore, for loop terminates at indices[2].
Next, the following code increments the ith element of indices:
2170 /* Increment the current index which we know is not at its
2171 maximum. Then move back to the right setting each index
2172 to its lowest possible value (one higher than the index
2173 to its left -- this maintains the sort order invariant). */
2174 indices[i]++;
As a result, we get index combination [0, 1, 3], which points to ('A', 'B', 'D').
Then we roll back the subsequent indices if they are too big:
2175 for (j=i+1 ; j<r ; j++)
2176 indices[j] = indices[j-1] + 1;
Indices increase step by step:
step indices
(0, 1, 2)
(0, 1, 3)
(0, 1, 4)
(0, 2, 3)
(0, 2, 4)
(0, 3, 4)
(1, 2, 3)
...

better algorithm for checking 5 in a row/col in a matrix

is there a good algorithm for checking whether there are 5 same elements in a row or a column or diagonally given a square matrix, say 6x6?
there is ofcourse the naive algorithm of iterating through every spot and then for each point in the matrix, iterate through that row, col and then the diagonal. I am wondering if there is a better way of doing it.
You could keep a histogram in a dictionary (mapping element type -> int). And then you iterate over your row or column or diagonal, and increment histogram[element], and either check at the end to see if you have any 5s in the histogram, or if you can allow more than 5 copies, you can just stop once you've reached 5 for any element.
Simple, one-dimensional, example:
m = ['A', 'A', 'A', 'A', 'B', 'A']
h = {}
for x in m:
if x in h:
h[x] += 1
else:
h[x] = 1
print "Histogram:", h
for k in h:
if h[k]>=5:
print "%s appears %d times." % (k,h[k])
Output:
Histogram: {'A': 5, 'B': 1}
A appears 5 times.
Essentially, h[x] will store the number of times the element x appears in the array (in your case, this will be the current row, or column or diagonal). The elements don't have to appear consecutively, but the counts would be reset each time you start considering a new row/column/diagonal.
You can check whether there are k same elements in a matrix of integers in a single pass.
Suppose that n is the size of the matrix and m is the largest element. We have n column, n row and 1 diagonal.
Foreach column, row or diagonal we have at most n distinct element.
Now we can create a histogram containing (n + n + 1) * (2 * m + 1) element. Representing
the rows, columns and the diagonal each of them containing at most n distinct element.
size = (n + n + 1) * (2 * m + 1)
histogram = zeros(size, Int)
Now the tricky part is how to update this histogram ?
Consider this function in pseudo-code:
updateHistogram(i, j, element)
if (element < 0)
element = m - element;
rowIndex = i * m + element
columnIndex = n * m + j * m + element
diagonalIndex = 2 * n * m + element
histogram[rowIndex] = histogram[rowIndex] + 1
histogram[columnIndex] = histogram[columnIndex] + 1
if (i = j)
histogram[diagonalIndex] = histogram[diagonalIndex] + 1
Now all you have to do is to iterate throw the histogram and check whether there is an element > k
Your best approach may depend on whether you control the placement of elements.
For example, if you were building a game and just placed the most recent element on the grid, you could capture into four strings the vertical, horizontal, and diagonal strips that intersected that point, and use the same algorithm on each strip, tallying each element and evaluating the totals. The algorithm may be slightly different depending on whether you're counting five contiguous elements out of the six, or allow gaps as long as the total is five.
For rows you can keep a counter, which indicates how many of the same elements in a row you currently have. To do this, iterate through the row and
if current element matches the previous element, increase the counter by one. If counter is 5, then you have found the 5 elements you wanted.
if current element doesn't match previous element, set the counter to 1.
The same principle can be applied to columns and diagonals as well. You probably want to use array of counters for columns (one element for each column) and diagonals so you can iterate through the matrix once.
I did the small example for a smaller case, but you can easily change it:
n = 3
matrix = [[1, 2, 3, 4],
[1, 2, 3, 1],
[2, 3, 1, 3],
[2, 1, 4, 2]]
col_counter = [1, 1, 1, 1]
for row in range(0, len(matrix)):
row_counter = 1
for col in range(0, len(matrix[row])):
current_element = matrix[row][col]
# check elements in a same row
if col > 0:
previous_element = matrix[row][col - 1]
if current_element == previous_element:
row_counter = row_counter + 1
if row_counter == n:
print n, 'in a row at:', row, col - n + 1
else:
row_counter = 1
# check elements in a same column
if row > 0:
previous_element = matrix[row - 1][col]
if current_element == previous_element:
col_counter[col] = col_counter[col] + 1;
if col_counter[col] == n:
print n, 'in a column at:', row - n + 1, col
else:
col_counter[col] = 1
I left out diagonals to keep the example short and simple, but for diagonals you can use the same principle as you use on columns. The previous element would be one of the following (depending on the direction of diagonal):
matrix[row - 1][col - 1]
matrix[row - 1][col + 1]
Note that you will need to make a little bit extra effort in the second case. For example traverse the row in the inner loop from right to left.
I don't think you can avoid iteration, but you can at least do an XOR of all elements and if the result of that is 0 => they are all equal, then you don't need to do any comparisons.
You can try improve your method with some heuristics: use the knowledge of the matrix size to exclude element sequences that do not fit and suspend unnecessary calculation. In case the given vector size is 6, you want to find 5 equal elements, and the first 3 elements are different, further calculation do not have any sense.
This approach can give you a significant advantage, if 5 equal elements in a row happen rarely enough.
If you code the rows/columns/diagonals as bitmaps, "five in a row" means "mask % 31== 0 && mask / 31 == power_of_two"
00011111 := 0x1f 31 (five in a row)
00111110 := 0x3e 62 (five in a row)
00111111 := 0x3f 63 (six in a row)
If you want to treat the six-in-a-row case also as as five-in-a-row, the easiest way is probably to:
for ( ; !(mask & 1) ; mask >>= 1 ) {;}
return (mask & 0x1f == 0x1f) ? 1 : 0;
Maybe the Stanford bit-tweaking department has a better solution or suggestion that does not need looping?

Categories