Going through a square matrix in an ever smaller spiral - algorithm

What I want to do is an algorithm that goes through a matrix in a closing spiral pattern as follows:
1 | 2 | 3
---------
8 | 9 | 4
---------
7 | 6 | 5
What would be the simplest way to tackle this problem ?
My thoughts:
Corner or obstacle detection.
Have a programmatic way to go down vertically and in reverse.
Have a way to detect that an element has already been visited.
P.S: Not sure how to handle a case where the size is not a square or the width is an even number.

You don't need a visited concept for each cell, just a single variable to indicate how far you are.
Below is some (not extensively tested) Java code to do this.
It should be pretty readable.
// initialize
int w = 5, h = 7;
int[][] arr = new int[w][h];
// do the work
int count = 1;
for (int i = 0; count <= w*h; i++)
{
// go right
for (int x = i; x < w-i && count <= w*h; x++)
arr[x][i] = count++;
// go down
for (int y = i+1; y < h-i && count <= w*h; y++)
arr[w-i-1][y] = count++;
// go left
for (int x = w-2-i; x >= i && count <= w*h; x--)
arr[x][h-i-1] = count++;
// go up
for (int y = h-2-i; y > i && count <= w*h; y--)
arr[i][y] = count++;
}
Java.
Output:
1 2 3 4 5
20 21 22 23 6
19 32 33 24 7
18 31 34 25 8
17 30 35 26 9
16 29 28 27 10
15 14 13 12 11

For each cell, have a number that denotes how many empty/visited cells are in its immediate vertical and horizontal position (let's call it numVisitedAroundCell.) Also, have a boolean flag isVisited. Go through the cells and update numVisitedAroundCell (so the corner cells would have numVisitedAroundCell == 2 and the outer layer of cells that is not a corner would have numVisitedAroundCell == 1)
Go through the cells and find a corner cell, which would be a cell with numVisitedAroundCell == 2.
From there, either go vertically or horizontally, while marking each cell you pass as isVisited and incrementing the number of numVisitedAroundCell. Keep going down the path you choose until you hit a corner cell(when you hit this corner cell, numVisitedAroundCell should be 3), then find the next unvisited cell, and go down that route. If you keep doing this, I believe you will get the spiral that you wanted. Also, this should deal with cases where the width is even and if the size is not square.

Recursively, for no good reason:
Use four functions, named right(), down(), left(), and up().
The right() function counts along the top row of the matrix, and then
passes the remaining rows (all excluding the one it just filled in) to
down().
The down() function counts down the right edge of the matrix, and then
passes the remaining columns to left().
etc.
Recursion stops when a width or a height reaches zero.

Related

Rotate Image - Java

I am doing a question where, given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise).You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. This my my code:
class Solution {
public void rotate(int[][] matrix) {
int size = matrix.length;
for(int i = 0 ; i < matrix.length; i++){
for(int y = 0 ; y < matrix[0].length ; y++){
matrix[i][y] = matrix[size - y - 1][i];
System.out.println(size - y - 1);
System.out.println(i);
System.out.println("");
}
}
}
}
This is the input and output results:
input matrix: [[1,2,3],[4,5,6],[7,8,9]]
output matrix: [[7,4,7],[8,5,4],[9,4,7]]
expected matrix: [[7,4,1],[8,5,2],[9,6,3]]
I do not really understand why I am getting duplicates in my output such as the number seven 3 times. On my System.out.println statement, I am getting the correct list of indexes :
2
0
1
0
0
0
2
1
1
1
0
1
2
2
What can be wrong?
I have found a solution. I will try my best to explain it.
Let us consider an array of size 4.
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now lets look at the numbers present only on the outside of the array:
1 2 3 4
5 8
9 12
13 14 15 16
We will proceed by storing the first element 1 in a temporary variable. Next we will replace 1 by 13, 13 by 16, 16 by 4 and at last 4 by 1 (whose value we already stored in the temporary variable).
We will do the same for all the elements of the first row.
Here is a pseudocode if you just want to rotate this outer ring, lets call it an outer ring:
for i = 0 to n-1
{
temp = A[0][i];
A[0][i] = A[n-1-i][0];
A[n-1-i][0] = A[n-1-0][n-1-i];
A[n-1-0][n-1-i] = A[i][n-1-0];
A[i][n-1-0] = temp;
}
The code runs for a total of n times. Once for each element of first row. Implement this code an run it. You will see only the outer ring is rotated. Now lets look at the inner ring:
6 7
10 11
Now the loop in pseudocode only needs to run for 2 times and also our range of indexes has decreased. For outer ring, the loop started from i = 0 and ended at i = n-1. However, for the inner ring the for loop need to run from i = 1 to i = n-2.
If you had an array of size n, to rotate the xth ring of the array, the loop needs to run from i = x to i = n-1-x.
Here is the code to rotate the entire array:
x = 0;
int temp;
while (x < n/2)
{
for (int i = x;i < n-1-x;i++)
{
temp = arr[x][i];
arr[x][i] = arr[n-1-i][x];
arr[n-1-i][x] = arr[n-1-x][n-1-i];
arr[n-1-x][n-1-i] = arr[i][n-1-x];
arr[i][n-1-x] = temp;
}
x++;
}
Here each value of x denotes the xth ring.
0 <= x <= n-1
The reason why the outer loop runs only for x < n/2 times is because each array has n/2 rings when n is even and n/2 + 1 rings if n is odd.
I hope I have helped you. Do comment if face any problems with the solution or its explanation.

Algorithm to find optimal groups in 2D array

I have a deck of 24 cards - 8 red, 8 blue and 8 yellow cards.
red |1|2|3|4|5|6|7|8|
yellow |1|2|3|4|5|6|7|8|
blue |1|2|3|4|5|6|7|8|
I can take 3 of cards (same numbers, straight, straigh flush), whereas each of the type is scored differently.
My question is, how to calculate maximal possible score (find optimal groups) for a game in progress, where some cards are already missing.
for example:
red |1|2|3|4|5|6|7|8|
yellow |1|2|3| |5| |7|8|
blue |1|2| |4|5|6| |8|
The score for a three-of-a-kind is:
1-1-1 20
2-2-2 30
3-3-3 40
4-4-4 50
5-5-5 60
6-6-6 70
7-7-7 80
8-8-8 90
The score for a straight is:
1-2-3 10
2-3-4 20
3-4-5 30
4-5-6 40
5-6-7 50
6-7-8 60
The score for a straight flush is:
1-2-3 50
2-3-4 60
3-4-5 70
4-5-6 80
5-6-7 90
6-7-8 100
A solution which recursively tries every combination would go like this:
Start looking at combinations that have a red 8 as the highest card: three-of-a-kind r8-y8-b8, straight flush r6-r7-r8, and every possible straight *6-*7-r8. For each of these, remove the cards from the set, and recurse to check combinations with the yellow 8, then blue 8, then red 7, yellow 7, blue 7, red 6 ... until you've checked everything except the 2's and 1's; then add three-of-a-kind 2-2-2 and 1-1-1 if available. At each step, check which recursion returns the maximum score, and return this maximum.
Let's look at what happens in each of these steps. Say we're looking at combinations with red 8; we have available cards like:
red ...|6|7|8|
yellow ...|6| |8|
blue ...| |7|8|
First, use three-of-a-kind r8-y8-b8, if possible. Create a copy of the available cards, remove the 8's, and recurse straight to the 7's:
score = 90 + max_score(cards_copy, next = red 7)
(Trying the three-of-a-kind should only be done when the current card is red, to avoid duplicate solutions.)
Then, use straight flush r6-r7-r8, if possible. Create a copy of the available cards, remove r6, r7 and r8, and recurse to yellow 8:
score = 100 + max_score(cards_copy, next = yellow 8)
Then, use every possible non-flush straight containing red 8; in the example, those are r6-b7-r8, y6-r7-r8 and y6-b7-r8 (there could be up to nine). For each of these, create a copy of the available cards, remove the three cards and recurse to yellow 8:
score = 60 + max_score(cards_copy, next = yellow 8)
Then, finally, recurse without using red 8: create a copy of the available cards, remove red 8 and recurse to yellow 8:
score = max_score(cards_copy, next = yellow 8)
You then calculate which of these options has the greatest score (with the score returned by its recursion added), and return that maximum score.
A quick test in JavaScript shows that for a full set of 24 cards, the algorithm goes through 30 million recursions to find the maximum score 560, and becomes quite slow. However, as soon as 3 higher-value cards have been removed, the number of recursions falls below one million and it takes around 1 second, and with 6 higher-value cards removed, it falls below 20,000 and returns almost instantly.
For almost-complete sets, you could pre-compute the maximum scores, and only calculate the score once a certain number of cards have been removed. A lot of sets will be duplicates anyway; removing r6-r7-r8 will result in the same maximum score as removing y6-y7-y8; removing r6-y7-b8 is a duplicate of removing b6-y7-r8... So first you change the input to a canonical version, and then you look up the pre-computed score. E.g. using pre-computed scores for all sets with 3 or 6 cards removed would require storing 45,340 scores.
As a code example, here's the JavaScript code I tested the algorithm with:
function clone(array) { // copy 2-dimensional array
var copy = [];
array.forEach(function(item) {copy.push(item.slice())});
return copy;
}
function max_score(cards, suit, rank) {
suit = suit || 0; rank = rank || 7; // start at red 8
var max = 0;
if (rank < 2) { // try 3-of-a-kind for rank 1 and 2
if (cards[0][0] && cards[1][0] && cards[2][0]) max += 20;
if (cards[0][1] && cards[1][1] && cards[2][1]) max += 30;
return max;
}
var next_rank = suit == 2 ? rank - 1: rank;
var next_suit = (suit + 1) % 3;
max = max_score(clone(cards), next_suit, next_rank); // try skipping this card
if (! cards[suit][rank]) return max;
if (suit == 0 && cards[1][rank] && cards[2][rank]) { // try 3-of-a-kind
var score = rank * 10 + 20 + max_score(clone(cards), 0, rank - 1);
if (score > max) max = score;
}
for (var i = 0; i < 3; i++) { // try all possible straights
if (! cards[i][rank - 2]) continue;
for (var j = 0; j < 3; j++) {
if (! cards[j][rank - 1]) continue;
var copy = clone(cards);
copy[j][rank - 1] = 0; copy[i][rank - 2] = 0;
var score = rank * 10 - 10 + max_score(copy, next_suit, next_rank);
if (i == suit && j == suit) score += 40; // straight is straight flush
if (score > max) max = score;
}
}
return max;
}
document.write(max_score([[1,1,1,1,1,0,1,1], [1,1,1,1,1,1,1,0], [1,1,1,0,1,1,1,1]]));
An obvious way to speed up the algorithm is to use a 24-bit pattern instead of a 3x8 bit array to represent the cards; that way the array cloning is no longer necessary, and most of the code is turned into bit manipulation. In JavaScript, it's about 8 times faster:
function max_score(cards, suit, rank) {
suit = suit || 0; rank = rank || 7; // start at red 8
var max = 0;
if (rank < 2) { // try 3-of-a-kind for rank 1 and 2
if ((cards & 65793) == 65793) max += 20; // 65793 = rank 1 of all suits
if ((cards & 131586) == 131586) max += 30; // 131586 = rank 2 of all suits
return max;
}
var next_rank = suit == 2 ? rank - 1: rank;
var next_suit = (suit + 1) % 3;
var this_card = 1 << rank << suit * 8;
max = max_score(cards, next_suit, next_rank); // try skipping this card
if (! (cards & this_card)) return max;
if (suit == 0 && cards & this_card << 8 && cards & this_card << 16) { // try 3oaK
var score = rank * 10 + 20 + max_score(cards, 0, rank - 1);
if (score > max) max = score;
}
for (var i = 0; i < 3; i++) { // try all possible straights
var mid_card = 1 << rank - 1 << i * 8;
if (! (cards & mid_card)) continue;
for (var j = 0; j < 3; j++) {
var low_card = 1 << rank - 2 << j * 8;
if (! (cards & low_card)) continue;
var cards_copy = cards - mid_card - low_card;
var score = rank * 10 - 10 + max_score(cards_copy, next_suit, next_rank);
if (i == suit && j == suit) score += 40; // straight is straight flush
if (score > max) max = score;
}
}
return max;
}
document.write(max_score(parseInt("111101110111111111011111", 2)));
// B Y R
// 876543218765432187654321
The speed for almost-complete sets can be further improved by using the observation that if a straight flush for all three suits can be be made for the current rank, then this is always the best option. This reduces the number of recursions drastically, because nine cards can be skipped at once. This check should be added immediately after trying 3-of-a-kind for rank 1 and 2:
if (suit == 0) { // try straight flush for all suits
var flush3 = 460551 << rank - 2; // 460551 = rank 1, 2 and 3 of all suits
if ((cards & flush3) == flush3) {
max = rank * 30 + 90;
if (rank > 2) max += max_score(cards - flush3, 0, rank - 3);
return max;
}
}

how to get the moore neighbourhood using index of a vector

I have a matrix in Rcpp (C++ for R) which is stored in column order in memory. Ie, it looks like:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
Now, I have a single for loop that runs from i = 1 to 25 (bear in mind, it is all zero based, but here I am just saying one for convenience).
For every element of the matrix, I want its Moore neighbourhood. This is easy for the elements that are not on the edge. So if our selected index is idx and the size of the square matrix is nrow then we have
leftmid = idx - nrow
lefttop = (idx - nrow) - 1
leftbot = (idx - nrow) + 1
rightmid = idx + nrow
righttop = (idx + nrow) - 1
rightbot = (idx + nrow) + 1
midtop = idx - 1
midbot = idx + 1
But i cant figure out how to deal with the edge cases. For example, if idx = 3, then i want the neighbours:
leftmid = 23
lefttop = 22
leftbot = 24
rightmid = 8
righttop = 7
rightbot = 9
midtop = 2
midbot = 4
It's a little bit more complicated at the corner cases as well. My goal here is to reduce time. I am currently running my program with a double for loop which works, but is slower than reasonable. I want to change it into a single for loop to improve performance.
Edit: I realized the left and right boundaries can be obtained by modulus. So 3 - 5 %% 25 = 23. But I still have the top and bottom edge cases.
It appears you're interested in "cyclic" boundary conditions, where the matrix has a toroidal topology, i.e. the top wraps around to the bottom and the right wraps around to the left.
It might be easier to iterate with four loops, one each over the row and column, and then one each over the row and column of the neighborhood. Something like this should work:
int mooreNeighbors[3][3];
int nRows = 5;
int nCols = 5;
// Loop over the rows and columns of the matrix
for (int i = 0; i < nRows; ++i) {
for (int j = 0; j < nCols; ++j) {
// Loop over the cyclic Moore neighborhood
for (int mnI = 0; mnI < 3; ++mnI) {
for (int mnJ = 0; mnJ < 3; ++mnJ) {
// Sub-matrix indices
int subI = (i - mnI - 1) % nRows;
int subJ = (j - mnJ - 1) % nCols;
// Index into column-dominant matrix
int idx = subI + subJ*nRows;
mooreNeighbors[mnI][mnJ] = matrix[idx];
}
}
}
}
I haven't tried compiling this, but it should be close to correct and clear enough to correct any mistakes. Think of it as pseudo-code.
Also, I'm preferring clarity over optimality. For example, you don't have to do everything in the inner-most loop.

Maximum Devastation to be caused if a building with height h causes all h-1 buildings to its right to collapse

In a recent interview question I got the following problem.
In a particular city we have a row of buildings with varying heights.
The collapse of a building with height h causes the next h-1 buildings on its right to collapse too.
The height of the buildings can be between 1 and 5000. Given the heights of all the buildings (arranged from left to right ie; for leftmost building index=1 and for rightmost building index=N) we needed to find out the index of the building which would cause the maximum devastation.
For example:
Input:
Number of buildings : 6
Height of Buildings:
2 1 3 3 1 6
Answer should be building at the index 3
The solution I tried was using the brute force technique with a complexity of O(N^2).
What I did was for each building in the list I found out the number of buildings that it would destroy.
Could a better solution for this question be constructed?
Simply go from the left, collapse the first building, and calculate how much total(*) damage it did.
Do this again and again from the very next building (which hasn't collapsed).
From these, pick the maximum.
Complexity: O(n).
This greedy algorithm works because the whole process is a chain reaction, if building A forces the collapse of B, then you cannot achieve better score starting from B.
(*) You can do this by maintaining one counter which stores how many buildings to the right should be collapsed. counter = max(counter - 1, height of next building).
some areas of the city function as "firewalls" - collapse stops at that point. a little thought shows that these are sections to the left of a value of 1 where height increases (to the left) no more than once per step (if you can have 0 heights that complicates things very slightly).
and the highest scoring region must start just after a firewall (since if it didn't there would be a higher region just to the left).
so scan from the right, finding these firewalls, and then find which section to the right of a firewall has the largest damage. this is O(n) because it's just linear scans (once from right to left and then once for each section, with no overlap).
actually, Karoly's answer is equivalent and simpler to implement.
Start with rightmost index.
The last building shall cause a devastation value of 1.
Iterate leftwards.
Something like (devastation from building i)
D[i] = 1 + min( N-i, max( index[i]-1, 0+D[i+1],1+D[i+2],... to index[i]-1 terms ) )
Same approach as #Karoly's answer. In ruby:
def find_max_damage_index(buildings)
max_damage = 0
max_start_index = nil
current_start_index = nil
current_h = 0
current_damage = 0
buildings.each_with_index{|h,i|
if current_h == 0 #end of batch
if current_damage > max_damage
max_damage = current_damage
max_start_index = current_start_index
end
#start new batch
current_h = h
current_damage = 1
current_start_index = i
else
current_h = h if h > current_h
current_damage += 1
end
current_h -= 1
}
#last batch
if current_damage > max_damage
max_damage = current_damage
max_start_index = current_start_index
end
return max_start_index
end
In Java, without considering subsequent collapses:
public static int collapse(int[] buildings) {
int i, maxDamage, index, currentDamage;
// do not consider the last building, it will cause only its own fall
maxDamage = 1;
index = buildings.length - 1;
for(i = buildings.length - 1; i >= 0; i--) {
// update maximum damage as the mimimum value between the building[i] (the height of the building at index i) and the remaining number of elements from i to the end of the array
currentDamage = Math.min(buildings[i], buildings.length - i);
System.out.println(currentDamage);
if(currentDamage > maxDamage) {
maxDamage = currentDamage;
index = i;
}
}
return index;
}
My final solution is different from the accepted one, which by the way I didn't fully understand.
The idea is to count starting from the rightmost position the number of buildings that the current index will collapse.
index: 7 6 5 4 3 2 1 0
height: 1 3 1 2 4 1 3 2
damage: 1 2 1 2 4 1 3 2
Then I just make a cumulative sum, starting from the rightmost position again. I add to the number of buildings the current position collapses the number of buildings that were collapsed staring from the next building to the right that didn't collapse until the end.
index: 7 6 5 4 3 2 1 0
height: 1 3 1 2 4 1 3 2
damage: 1 2 1 2 5 1 7 8
In the end, I just return the index with the maximum damage.
This solution runs in O(n) but uses an extra O(n) space.
The next code is the complete version (also works for subsequent collapses):
public static int collapse(int[] buildings) {
int i, maxIndex, max;
int damage[] = new int[buildings.length];
for(i = buildings.length - 1; i >= 0; i--) {
// compute damage for each position
damage[i] = Math.min(buildings[i], buildings.length - i);
}
for(i = buildings.length - 1; i >= 0; i--) {
// update total accumulated damage for each position
if(damage[i] > 1) {
if(damage[i] + i - 1 < buildings.length && i != (i + damage[i] - 1) ) {
damage[i] += damage[i + damage[i] - 1] - 1;
}
}
}
max = damage[0];
maxIndex = 0;
for(i = 1; i < buildings.length; i++) {
// find the maximum damage
if(damage[i] > max) {
max = damage[i];
maxIndex = i;
}
}
return maxIndex;
}

Help with spiral matrix

I need to write a program for Pascal that makes array in spiral form like this:
(7) (8) (9) (10)
(6) (1) (2) (11)
(5) (4) (3) (12)
(16)(15)(14)(13)
Start from 1 and continue to 36 but this is not so important.
After 3 days thinking I have no idea how to realize this.
Problem is not in language syntax or arrays, it is just in the algorithm.
Can you help me with any ideas, links, pseudo-code or program code in any programming language?
Think of splitting the nxn matrix into concentric submatrixes of 2x2, 4x4, .. nxn. In your case we would have the outer sub-matrix (elements 5 to 16) and the inner one (elements 1 to 4).
Now, for each level you should iterate over the four edges, and fill them with the needed elements. You can go inside-out or outside-in. I will go outside-in. We keep a counter which is initially n*n (16 in our example).
For i going from 1 to n/2:
First take the bottom edge (elements 16-13 for outer level). We go from x[n-i+1][i] to x[n-i+1][n-i+1] and fill (this would be 16, 15, 14, 13 for the first level and 4,3 for the second level)
Then we take the right edge (elements 12-10 for outer level). We go from x[n-i][n-i+1] to x[i][n-i+1] (elements 12, 11, 10 for outer level).
Then we take the top edge (elements 9-7 for outer level). We go from x[i][n-i] to x[i][i] (elements 9, 8, 7 for outer level)
At last we take the left edge (elements 6-5 for outer level). We go from x[i+1][i] to x[n-i][i] and fill that side (this would be 6, 5 for outer level).
And at last you have the middle element if n is odd. Then all you have to do is to assign x[n/2+1][n/2+1] = 1
I hope I made the the idea clear; if there is something you don't understand, ask.
Also I didn't implement the solution because I assume that the problem you have is only the idea, not the implementation
There is one sweet idea you can use to change direction while iterating over the matrix. Look at the following table. Input (dX, dY) are the previous direction in increment values, and output (cwdx, cwdy) are the next clock-wise direction, and output (ccwdx, ccwdy) are the next counter-clockwise direction (coordinate (0,0) is in upper-left corner):
dx dy | cwdx cwdy | ccwdx ccwdy
-------------------------------
1 0 | 0 1 | 0 -1
0 1 | -1 0 | 1 0
-1 0 | 0 -1 | 0 1
0 -1 | 1 0 | -1 0
So, given direction (dx,dy) to turn clockwise you need direction (-dy,dx), and to turn counter-clockwise you need direction (dx,-dy). This means that you don't need a switch in your code to turn direction, you just do it by three lines of code:
temp = dx; // this is for clockwise turn
dx = -dy;
dy = temp;
And there is one more little trick. To fill the matrix you can actually start from the end and largest number, and make your way to center and number 1. If you start from edge and go to the center then you can fill the numbers in a line until you can (until you reach the edge of matrix or another number). If you can't fill in current direction anymore because (x+dx, y+dy) is not "fillable" then change direction.
The easiest idea is to start from the end of the spiral and work your way back.
Have four variables (left, top, right, bottom) that tell you how much you have filled appropriately from each side.
Make a matrix of appropriate size.
Initialize left = top = 0 and right and bottom to the last column and row index.
Fill the bottom row from left -> right. Decrease bottom by one.
Fill right from bottom -> top. Decrease right by one.
Fill top from right -> left. Increase top by one.
Fill left from top -> bottom. Increase left by one.
Iterate until you filled the whole matrix.
How about just apply the right-hand rule (like solving a maze).
Consider each cell after you walked become the wall.
Here's a snippet from a Java program to perform a spiral matrix visit. It tracks changes in directions to sense how many more visits to make while traveling in any given direction. The pattern that simplifies this problem is that while traveling in any given direction, the next time you visit that direction the number of visits to make is reduced by one. More simply put, if the first time you travel in the horizontal direction you will be making 6 visits the next time you travel in the horizontal direction you will make 5 visits. It should also be noted that the horizontal and vertical visits are tracked separately. A single equation below has been used to calculate the number of visits for a given direction after a change in direction is needed. This equation selects vertical or horizontal by deriving it from the total number of direction changes and using mod as a selector. Finally, thinking of the visits as a snake moving along the matrix I represented the step as the change in row/column as velocity (dy and dx). As another person pointed out there is a pattern that can be used and is expressed in the formula for dy and dx.
int[][] matrix = { { 1, 2, 3, 4, 5, 6, 7, 8 },
{ 24, 25, 26, 27, 28, 29, 30, 9 },
{ 23, 40, 41, 42, 43, 44, 31, 10 },
{ 22, 39, 48, 47, 46, 45, 32, 11 },
{ 21, 38, 37, 36, 35, 34, 33, 12 },
{ 20, 19, 18, 17, 16, 15, 14, 13 } };
int n = matrix.length;
int m = matrix[0].length;
int row = 0;
int col = 0;
int dx = 1;
int dy = 0;
int dirChanges = 0;
int visits = m;
for (int i = 0; i < n * m; i++) {
System.out.print(matrix[row][col] + " ");
visits--;
if (visits == 0) {
visits = m * (dirChanges %2) + n * ((dirChanges + 1) %2) - (dirChanges/2 - 1);
int temp = dx;
dx = -dy;
dy = temp;
dirChanges++;
}
col += dx;
row += dy;
}
The output of this program is:
1 2 3 4 5 6 7 8 9 10 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
To #1
I wrote the program but the result looks like this:
00000
10000
11000
11100
.....
I don't know maybe I have not understood your algorythm or any other problem happened.
Here is code:
n:=16;
x:=1;
For i:=1 to (n div 2) do
begin
For p:=i to n-i+1 do
begin
a[n-i+1,p]:=x;
end;
For q:=n-i to i do
begin
a[q,n-i+1]:=x;
end;
For o:=n-i to i do
begin
a[i,o]:=x;
end;
For u:=i+1 to n-i do
begin
a[u,i]:=x;
end;
end;
So I tried to write #2 program from php to pascal and it works.
Now I will fix it to write numbers clockwise and start from center of array.
Big thank you all.
CurValue = n * n;
End point is the most down left point.
We'll visit from the end point to the first point ( we assign values with visiting )
Every cell has zero value at the beginning.
x = n-1;
y = 0;
arr[x][y] = CurValue;
while ( CurValue greater than zero )
{
keep going right until you face a cell that has non-zero value or until you reach the most right cell
keep going top until you face a cell that has non-zero value or until you reach the most top cell
keep going left until you face a cell that has non-zero value or until you reach the most left cell
keep going down until you face a cell that has non-zero value or until you reach the most down cell
}
note: with each cell you visit then do the following :
CurValue --;
Assign CurValue to the current visited cell;
I hope the algorithm above is clear to understand.
Here's a recursive solution written in PHP.
<?php
header('Content-type: text/plain');
function fill($x, $y, $dir, $leftInDir, $index, $stepSize, $stop){
global $out;
// set the value for the current item //
$out[$y][$x] = $index;
// everything that comes after this point is computing for the parameters of the next call //
// activate this for debugging //
//echo $x, ',', $y, ',', $dir, ',', $leftInDir, ',', $index, ',', $stepSize, ',', $stop, "\n";
// decrease the number of steps left to take in the current direction //
$leftInDir--;
// check if this is the last item //
if($index == $stop)
return;
// we're going up for the next item //
if($dir == 'U')
$y--;
// we're going right for the next item //
if($dir == 'R')
$x++;
// we're going down for the next item //
if($dir == 'D')
$y++;
// we're going left for the next item //
if($dir == 'L')
$x--;
// if this was the last step in this direction we need to change the direction //
if($leftInDir == 0){
// after two direction changes we need to increase the numbers of steps to take //
if($dir == 'D' || $dir == 'U'){
$stepSize++;
}
// update the direction clockwise //
if($dir == 'U')
$dir = 'R';
else if($dir == 'R')
$dir = 'D';
else if($dir == 'D')
$dir = 'L';
else if($dir == 'L')
$dir = 'U';
// set the number of steps left as the step size //
$leftInDir = $stepSize;
}
// increase the number to put in the cell //
$index++;
// call for the next item //
fill($x,$y,$dir,$leftInDir,$index,$stepSize,$stop);
}
// set the size //
$size = 100;
// start the process from the center of the matrix //
fill((int)$size/2, (int)$size/2, 'R', 1, 1, 1, $size*$size);
// just output //
ksort($out);
foreach($out as $row){
ksort($row);
foreach($row as $item){
echo str_pad($item, 7);
}
echo "\n";
}
?>
The principle is quite straight forward (well, not straight, but in a spiral, forward :) ). You start from where 1 should be and start walking. 1 RIGHT, 1 DOWN, 2 LEFT, 2 UP, 3 RIGHT, etc. until you reach n*n.
I wrote it as a recursive function, but it can easily be converted to a loop.
Do you mean that it has to print out the numbers from left-to-right, top to bottom? It helps to know that to make square numbers, you add consecutive odd numbers together - 1 + 3 + 5 + 7 + 9 + 11 = 36.
In this spiral, the left-hand edge is simple ... except for the bottom row. So one way to go is to write your algorithm as if the spiral was one loop bigger, but don't print out the first row and first and last column.
import java.util.Scanner;
class CircularMatrixFromInnerClockwise
{
Scanner sc= new Scanner(System.in);
void main()
{
System.out.println("Enter size.");
int n=sc.nextInt();
int a[][]= new int [n][n];
int r1,c1,r2,c2;
if(n%2==0)
{
r1=n/2-1;
c1=n/2-1;
r2=n/2-1;
c2=n/2-1;
}
else
{
r1=(n+1)/2-1;
c1=(n+1)/2-1;
r2=(n+1)/2-1;
c2=(n+1)/2-1;
}
int k=1;
do
{
if(c2<n-1&&r2<n-1)
{
r2++;
c2++;
}
for(int i=c1;i<=c2;i++)
a[r1][i]=k++;
if(k>=n*n)
break;
for(int i=r1+1;i<=r2;i++)
a[i][c2]=k++;
if(k>=n*n)
break;
if(c1>0&&r1>0)
{
c1--;
r1--;
}
for(int i=c2-1;i>=c1;i--)
a[r2][i]=k++;
if(k>=n*n)
break;
for(int i=r2-1;i>=r1+1;i--)
a[i][c1]=k++;
if(k>=n*n)
break;
}while(k<=n*n);
System.out.println("Circular matrix");
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
System.out.print( a[i][j]+"\t");
}
System.out.println();
}
}
}
You're going from left to right, then down. left , up and all over again. Hope it helps. :)

Resources