How to iterate through a grid algorithm - c#

I am looking for an algorithm that can iterate through a grid and transform it into another grid with the indexes in a new order.
Basically, given a grid of size n*m:
1_1 1_2 1_3 ... 1_n
2_1 2_2 2_3 ... 2_n
.
.
.
m_1 m_2 m_3 ... m_m
How could I transform it to:
1_1 1_2 1_4 ...
1_3 1_5 ...
1_6 ...
...
.
.
.
Assume, you iterate through the first grid, going left to right in the top row, then
left to right in the second row, all the way to, left to right in the bottom row.
Basically I pushing the elements into an upper triangle.
Another problem is how do I figure out the length and width of the grid used to store the triangle just by knowing what n and m is?
Is there a formula for that?
For example, a grid of 5*6, gets changed to 8*7...
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
becomes:
1 2 4 7 11 16 22 29
3 5 8 12 17 23 30
6 9 13 18 24
10 14 19 25
15 20 26
21 27
28

The following seems to work for me:
public static T[,] ConvertToUpperTriangle<T>(T[,] arr)
{
// calculate the dimensions
int elements = arr.GetLength(0) * arr.GetLength(1);
double rows = 0.5 * (Math.Sqrt(8 * elements + 1) - 1);
int newHeight = (int)rows;
int newWidth = (int)Math.Ceiling(rows);
// create the new array
var arr2 = new T[newHeight, newWidth];
int j = 0;
int i = 0;
foreach (T element in arr)
{
arr2[j, i] = element;
i--;
j++;
if (i < 0)
{
i = j;
j = 0;
}
}
return arr2;
}
The 0.5 * (Math.Sqrt(8 * elements + 1) - 1) comes from running sum from 1 to n of n and then solve a = 0.5 * n * (n + 1) for n through Wolfram Alpha.
Edit:
You can get the indices i and j for a given index as follows:
int rows = (int)(0.5 * (Math.Sqrt(8 * index + 1) - 1));
int bottomLeft = (int)(0.5 * rows * (rows + 1));
int difference = index - bottomLeft;
int i;
int j;
if (bottomLeft == index)
{
i = 0;
j = rows - 1;
}
else
{
i = rows + 1 - difference;
j = difference - 1;
}

Let's define the "ordinal position" O(i,j) of each grid element (i,j) in a starting grid NxM, which is the function (i,j) -> i*N + j.
Now for the largest triangular number less than O(i,j), call it T == (k(k+1)/2 for some k, the new grid position for our (i,j) will be:
(i,j) -> ( O(i,j) - T, k + T - O(i,j) )
Now substitute for O(i,j) and T to get:
(i,j) -> ( i*N + j - k(k+1)/2, k + (k+1)(k+2)/2 - i*N + j)
= ( i*N + j - k(k+1)/2, (k+1)(k+2)/2 - i*N + j)
That's as far as I can get it just now.
Update:
Note again that k is the side-length for the triangualr number T == k(k+1)/2.

Related

Select Specific Coordinates From List

I have a list of coordinates (x, y) ordered from left to right, top to bottom:
My goal is to grab only some of them in a different order. I've numbered the only points I want to grab and in the order I want to grab them. Similar to Snake. The direction reverses each time I move down one:
I've attempted writing out the logic for how to select each point, but I can't seem to work out how to get it in a for loop. Or a nested for loop, I think I'll need.
length = 10 (the size of the square of coordinates I'm grabbing. Which is 10x10.)
Increments * +
1) length * 0 + 0 // +0 +0
2) length * 1 + 0 // +1 +0
3) length * 2 + 0 // +1 +0
4) length * 1 + 1 // -1 +1
5) length * 2 + 1 // +1 +0
6) length * 3 + 0 // +1 -1
7) length * 4 + 0 // +1 +0
8) length * 3 + 1 // -1 +1
9) length * 4 + 1 // +1 +0
10) length * 5 + 0 // +1 -1
So if I were to hard code the array for each coordinate I want, I would have:
1) 0
2) 10
3) 20
4) 11
5) 21
6) 30
7) 40
8) 31
9) 41
10) 50
I do not think this requires a nested loop.
You can use a flip variable to change whether or not a specific line is "flipped".
Each row has two indices to be taken
flip alternates between 0 and 1, every two indices (i.e. every row)
On even rows, the first index is length - 1 less than the second index
On odd rows, that relationship is flipped.
public static void Main(string[] args)
{
int length = 11;
for (int i = 0; i < 10; ++ i) {
int flip = (i / 2) % 2;
int index = (i / 2) * length + ((i + flip) % 2) * (length - 1);
Console.WriteLine(index);
}
}
Output:
0
10
11
21
22
32
33
43
44
54

I have a list with 13 numbers and i want to multiply them together

I have a string numbers which contains 13 digits, e.g.:
string numbers = "01234567890123456781";
and I have to multiply them:
0 * 1 * 2 * 3 * ... * 7 * 8 * 1
I've a got a solution for adding the digits together:
0 + 1 + 2 + 3 + ... + 7 + 8 + 1
I convert number string to List<int> numb and then sum items of the list with a help of Linq Sum() method:
string numbers = "01234567890123456781";
List<int> numb = new List<int>();
for (int i = 0; i < numbers.Length; i++)
{
int num = int.Parse(numbers[i].ToString());
numb.Add(num);
}
for (int b = 0; b <numb.Count()-12; b++)
{
var x = numb.Skip(b).Take(13);
int a = x.Sum(); // <- it's easy to sum, but what shall I do to multiply?
Console.WriteLine(a);
}
However, Linq doesn't have any Mult() or alike method, so what can I do to multiply the items together?
Providing that the numbers contains digits [0..9] only, a simple Linq will do:
// since 0 * anything == 0, I've removed all 0's to obtain non-zero result:
// 1 * 2 * 3 * ... * 7 * 8 * 1
string numbers = "123456789123456781";
// long: int is not large enough
long result = numbers
.Select(c => (long) (c - '0'))
.Aggregate((s, a) => s * a);
Outcome:
// 14631321600
Console.Write(result);
Aggregate (custom aggregation) will do if you want to change IEnumerable<T>.Sum() from summation (as in your current code) to multiplication:
...
var x = numb.Skip(b).Take(13); //TODO: get rid of magic number 13
// instead of summation
// int a = x.Sum();
// let's use multiplication as a custom aggregation:
// please, mind overflow: int is not enough when multiplying items
long a = x
.Select(item => (long) item)
.Aggregate((s, item) => s * item);

Get range in multiplication of 5

I have a number. For instance, my number is 19 . Then I want to populate my drop down with range in multiplication of 5. So my dropdownlist will consist of items of:
1-5
6-10
11-15
16-19
I tried modulus and division, however, I can't seems to get the range. Is there a fixed method?
Sample code
List<string> range = new List<string>();
int number = 19;
int numOfOccur = (19/5);
for (int i = 1; i < numOfOccur ; i++)
{
range.Add(i + " - " + (i * 5))
}
Sometime I think that old school code, without fancy linq is a bit more clear
int maximum = 19;
int multiple = 5;
int init = 1;
while (init + multiple <= maximum )
{
string addToDDL = init.ToString() + "-" + (init + multiple - 1).ToString();
Console.WriteLine(addToDDL);
init += multiple;
}
if(init <= maximum)
{
string last = init.ToString() + "-" + maximum.ToString();
Console.WriteLine(last);
}
Linq solution (modern techs allow us to put it consize):
int number = 19;
int div = 5;
List<string> range = Enumerable
.Range(0, number / div + (number % div == 0 ? 0 : 1))
.Select(i => $"{i * div + 1} - {Math.Min((i + 1) * div, number)}")
.ToList();
Test
Console.Write(string.Join(Environment.NewLine, range));
Returns
1 - 5
6 - 10
11 - 15
16 - 19
When using modulo arithmetics, do not forget about remainders: you have an error in int numOfOccur = (19/5); line. It should be
int numOfOccur = 19 / 5 + (19 % 5 == 0 ? 0 : 1);
for the last incomplete 16 - 19 range to be proceeded.
Add this package to your project : https://www.nuget.org/packages/System.Interactive/
Then you can do this:
IEnumerable<IList<int>> buffers2 = Enumerable.Range(1, 19).Buffer(5);
IList<int>[] result2 = buffers2.ToArray();
// { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10 }, ...
Don't forget to add System.Interactive namespace to your using block.

Sequence Alignment Algorithm with a group of characters instead of one character

Summary:
I'm beginning with some details about alignment algorithms, and at the end, I ask my question. If you know about alignment algorithm pass the beginning.
Consider we have two strings like:
ACCGAATCGA
ACCGGTATTAAC
There is some algorithms like: Smith-Waterman Or Needleman–Wunsch, that align this two sequence and create a matrix. take a look at the result in the following section:
Smith-Waterman Matrix
§ § A C C G A A T C G A
§ 0 0 0 0 0 0 0 0 0 0 0
A 0 4 0 0 0 4 4 0 0 0 4
C 0 0 13 9 4 0 4 3 9 4 0
C 0 0 9 22 17 12 7 3 12 7 4
G 0 0 4 17 28 23 18 13 8 18 13
G 0 0 0 12 23 28 23 18 13 14 18
T 0 0 0 7 18 23 28 28 23 18 14
A 0 4 0 2 13 22 27 28 28 23 22
T 0 0 3 0 8 17 22 32 27 26 23
T 0 0 0 2 3 12 17 27 31 26 26
A 0 4 0 0 2 7 16 22 27 31 30
A 0 4 4 0 0 6 11 17 22 27 35
C 0 0 13 13 8 3 6 12 26 22 30
Optimal Alignments
A C C G A - A T C G A
A C C G G A A T T A A
Question:
My question is simple, but maybe the answer is not easy as it looks. I want to use a group of character as a single one like: [A0][C0][A1][B1]. But in these algorithms, we have to use individual characters. How can we achieve that?
P.S. Consider we have this sequence: #read #write #add #write. Then I convert this to something like that: #read to A .... #write to B.... #add to C. Then my sequence become to: ABCB. But I have a lot of different words that start with #. And the ASCII table is not enough to convert all of them. Then I need more characters. the only way is to use something like [A0] ... [Z9] for each word. OR to use numbers.
P.S: some sample code for Smith-Waterman is exist in this link
P.S: there is another post that want something like that, but what I want is different. In this question, we have a group of character that begins with a [ and ends with ]. And no need to use semantic like ee is equal to i.
I adapted this Python implementation (GPL version 3 licensed) of both the Smith-Waterman and the Needleman-Wunsch algorithms to support sequences with multiple character groups:
#This software is a free software. Thus, it is licensed under GNU General Public License.
#Python implementation to Smith-Waterman Algorithm for Homework 1 of Bioinformatics class.
#Forrest Bao, Sept. 26 <http://fsbao.net> <forrest.bao aT gmail.com>
# zeros() was origianlly from NumPy.
# This version is implemented by alevchuk 2011-04-10
def zeros(shape):
retval = []
for x in range(shape[0]):
retval.append([])
for y in range(shape[1]):
retval[-1].append(0)
return retval
match_award = 10
mismatch_penalty = -5
gap_penalty = -5 # both for opening and extanding
gap = '----' # should be as long as your group of characters
space = ' ' # should be as long as your group of characters
def match_score(alpha, beta):
if alpha == beta:
return match_award
elif alpha == gap or beta == gap:
return gap_penalty
else:
return mismatch_penalty
def finalize(align1, align2):
align1 = align1[::-1] #reverse sequence 1
align2 = align2[::-1] #reverse sequence 2
i,j = 0,0
#calcuate identity, score and aligned sequeces
symbol = []
found = 0
score = 0
identity = 0
for i in range(0,len(align1)):
# if two AAs are the same, then output the letter
if align1[i] == align2[i]:
symbol.append(align1[i])
identity = identity + 1
score += match_score(align1[i], align2[i])
# if they are not identical and none of them is gap
elif align1[i] != align2[i] and align1[i] != gap and align2[i] != gap:
score += match_score(align1[i], align2[i])
symbol.append(space)
found = 0
#if one of them is a gap, output a space
elif align1[i] == gap or align2[i] == gap:
symbol.append(space)
score += gap_penalty
identity = float(identity) / len(align1) * 100
print 'Identity =', "%3.3f" % identity, 'percent'
print 'Score =', score
print ''.join(align1)
# print ''.join(symbol)
print ''.join(align2)
def needle(seq1, seq2):
m, n = len(seq1), len(seq2) # length of two sequences
# Generate DP table and traceback path pointer matrix
score = zeros((m+1, n+1)) # the DP table
# Calculate DP table
for i in range(0, m + 1):
score[i][0] = gap_penalty * i
for j in range(0, n + 1):
score[0][j] = gap_penalty * j
for i in range(1, m + 1):
for j in range(1, n + 1):
match = score[i - 1][j - 1] + match_score(seq1[i-1], seq2[j-1])
delete = score[i - 1][j] + gap_penalty
insert = score[i][j - 1] + gap_penalty
score[i][j] = max(match, delete, insert)
# Traceback and compute the alignment
align1, align2 = [], []
i,j = m,n # start from the bottom right cell
while i > 0 and j > 0: # end toching the top or the left edge
score_current = score[i][j]
score_diagonal = score[i-1][j-1]
score_up = score[i][j-1]
score_left = score[i-1][j]
if score_current == score_diagonal + match_score(seq1[i-1], seq2[j-1]):
align1.append(seq1[i-1])
align2.append(seq2[j-1])
i -= 1
j -= 1
elif score_current == score_left + gap_penalty:
align1.append(seq1[i-1])
align2.append(gap)
i -= 1
elif score_current == score_up + gap_penalty:
align1.append(gap)
align2.append(seq2[j-1])
j -= 1
# Finish tracing up to the top left cell
while i > 0:
align1.append(seq1[i-1])
align2.append(gap)
i -= 1
while j > 0:
align1.append(gap)
align2.append(seq2[j-1])
j -= 1
finalize(align1, align2)
def water(seq1, seq2):
m, n = len(seq1), len(seq2) # length of two sequences
# Generate DP table and traceback path pointer matrix
score = zeros((m+1, n+1)) # the DP table
pointer = zeros((m+1, n+1)) # to store the traceback path
max_score = 0 # initial maximum score in DP table
# Calculate DP table and mark pointers
for i in range(1, m + 1):
for j in range(1, n + 1):
score_diagonal = score[i-1][j-1] + match_score(seq1[i-1], seq2[j-1])
score_up = score[i][j-1] + gap_penalty
score_left = score[i-1][j] + gap_penalty
score[i][j] = max(0,score_left, score_up, score_diagonal)
if score[i][j] == 0:
pointer[i][j] = 0 # 0 means end of the path
if score[i][j] == score_left:
pointer[i][j] = 1 # 1 means trace up
if score[i][j] == score_up:
pointer[i][j] = 2 # 2 means trace left
if score[i][j] == score_diagonal:
pointer[i][j] = 3 # 3 means trace diagonal
if score[i][j] >= max_score:
max_i = i
max_j = j
max_score = score[i][j];
align1, align2 = [], [] # initial sequences
i,j = max_i,max_j # indices of path starting point
#traceback, follow pointers
while pointer[i][j] != 0:
if pointer[i][j] == 3:
align1.append(seq1[i-1])
align2.append(seq2[j-1])
i -= 1
j -= 1
elif pointer[i][j] == 2:
align1.append(gap)
align2.append(seq2[j-1])
j -= 1
elif pointer[i][j] == 1:
align1.append(seq1[i-1])
align2.append(gap)
i -= 1
finalize(align1, align2)
If we run this with the following input:
seq1 = ['[A0]', '[C0]', '[A1]', '[B1]']
seq2 = ['[A0]', '[A1]', '[B1]', '[C1]']
print "Needleman-Wunsch"
needle(seq1, seq2)
print
print "Smith-Waterman"
water(seq1, seq2)
We get this output:
Needleman-Wunsch
Identity = 60.000 percent
Score = 20
[A0][C0][A1][B1]----
[A0]----[A1][B1][C1]
Smith-Waterman
Identity = 75.000 percent
Score = 25
[A0][C0][A1][B1]
[A0]----[A1][B1]
For the specific changes I made, see: this GitHub repository.
Imagine we have a log file with alphabetic sequences. Like something you said, I converted sequences to A0A1... . For example, if there was a sequence like #read #write #add #write, it converted to A0A1A2A1. Every time, I read two character and compare them but keep score matrix like before. Here is my code in C# for smith-waterman string alignment.
Notice that Cell is a user defined class.
private void alignment()
{
string strSeq1;
string strSeq2;
string strTemp1;
string strTemp2;
scoreMatrix = new int[Log.Length, Log.Length];
// Lists That Holds Alignments
List<char> SeqAlign1 = new List<char>();
List<char> SeqAlign2 = new List<char>();
for (int i = 0; i<Log.Length; i++ )
{
for (int j=i+1 ; j<Log.Length; j++)
{
strSeq1 = "--" + logFile.Sequence(i);
strSeq2 = "--" + logFile.Sequence(j);
//prepare Matrix for Computing optimal alignment
Cell[,] Matrix = DynamicProgramming.Intialization_Step(strSeq1, strSeq2, intSim, intNonsim, intGap);
// Trace back matrix from end cell that contains max score
DynamicProgramming.Traceback_Step(Matrix, strSeq1, strSeq2, SeqAlign1, SeqAlign2);
this.scoreMatrix[i, j] = DynamicProgramming.intMaxScore;
strTemp1 = Reverse(string.Join("", SeqAlign1));
strTemp2 = Reverse(string.Join("", SeqAlign2));
}
}
}
class DynamicProgramming
{
public static Cell[,] Intialization_Step(string Seq1, string Seq2,int Sim,int NonSimilar,int Gap)
{
int M = Seq1.Length / 2 ;//Length+1//-AAA //Changed: /2
int N = Seq2.Length / 2 ;//Length+1//-AAA
Cell[,] Matrix = new Cell[N, M];
//Intialize the first Row With Gap Penality Equal To Zero
for (int i = 0; i < Matrix.GetLength(1); i++)
{
Matrix[0, i] = new Cell(0, i, 0);
}
//Intialize the first Column With Gap Penality Equal To Zero
for (int i = 0; i < Matrix.GetLength(0); i++)
{
Matrix[i, 0] = new Cell(i, 0, 0);
}
// Fill Matrix with each cell has a value result from method Get_Max
for (int j = 1; j < Matrix.GetLength(0); j++)
{
for (int i = 1; i < Matrix.GetLength(1); i++)
{
Matrix[j, i] = Get_Max(i, j, Seq1, Seq2, Matrix,Sim,NonSimilar,Gap);
}
}
return Matrix;
}
public static Cell Get_Max(int i, int j, string Seq1, string Seq2, Cell[,] Matrix,int Similar,int NonSimilar,int GapPenality)
{
Cell Temp = new Cell();
int intDiagonal_score;
int intUp_Score;
int intLeft_Score;
int Gap = GapPenality;
//string temp1, temp2;
//temp1 = Seq1[i*2].ToString() + Seq1[i*2 + 1]; temp2 = Seq2[j*2] + Seq2[j*2 + 1].ToString();
if ((Seq1[i * 2] + Seq1[i * 2 + 1]) == (Seq2[j * 2] + Seq2[j * 2 + 1])) //Changed: +
{
intDiagonal_score = Matrix[j - 1, i - 1].CellScore + Similar;
}
else
{
intDiagonal_score = Matrix[j - 1, i - 1].CellScore + NonSimilar;
}
//Calculate gap score
intUp_Score = Matrix[j - 1, i].CellScore + GapPenality;
intLeft_Score = Matrix[j, i - 1].CellScore + GapPenality;
if (intDiagonal_score<=0 && intUp_Score<=0 && intLeft_Score <= 0)
{
return Temp = new Cell(j, i, 0);
}
if (intDiagonal_score >= intUp_Score)
{
if (intDiagonal_score>= intLeft_Score)
{
Temp = new Cell(j, i, intDiagonal_score, Matrix[j - 1, i - 1], Cell.PrevcellType.Diagonal);
}
else
{
Temp = new Cell(j, i, intDiagonal_score, Matrix[j , i - 1], Cell.PrevcellType.Left);
}
}
else
{
if (intUp_Score >= intLeft_Score)
{
Temp = new Cell(j, i, intDiagonal_score, Matrix[j - 1, i], Cell.PrevcellType.Above);
}
else
{
Temp = new Cell(j, i, intDiagonal_score, Matrix[j , i - 1], Cell.PrevcellType.Left);
}
}
if (MaxScore.CellScore <= Temp.CellScore)
{
MaxScore = Temp;
}
return Temp;
}
public static void Traceback_Step(Cell[,] Matrix, string Sq1, string Sq2, List<char> Seq1, List<char> Seq2)
{
intMaxScore = MaxScore.CellScore;
while (MaxScore.CellPointer != null)
{
if (MaxScore.Type == Cell.PrevcellType.Diagonal)
{
Seq1.Add(Sq1[MaxScore.CellColumn * 2 + 1]); //Changed: All of the following lines with *2 and +1
Seq1.Add(Sq1[MaxScore.CellColumn * 2]);
Seq2.Add(Sq2[MaxScore.CellRow * 2 + 1]);
Seq2.Add(Sq2[MaxScore.CellRow * 2]);
}
if (MaxScore.Type == Cell.PrevcellType.Left)
{
Seq1.Add(Sq1[MaxScore.CellColumn * 2 + 1]);
Seq1.Add(Sq1[MaxScore.CellColumn * 2]);
Seq2.Add('-');
}
if (MaxScore.Type == Cell.PrevcellType.Above)
{
Seq1.Add('-');
Seq2.Add(Sq2[MaxScore.CellRow * 2 + 1]);
Seq2.Add(Sq2[MaxScore.CellRow * 2]);
}
MaxScore = MaxScore.CellPointer;
}
}
}

Wrong N times matrix rotation

I have a task to rotate 2D matrix R`times what has n columns and m rows. Rotation should be in anti-clockwise direction.
The problems with my code below:
Looks like the StepValuesOperation method wrongly get or set values from matrix. I've already break a head to find out where is a problem.
Is it possible to rotate values without moving it into separated array?
About the code:
I have and a console application, which randomly initialize the matrix size, its values and count of rotation by InitializeParams method;
I get the count of iterations of matrix and for each get an array of values of the current iteration by StepValuesOperation method;
From the count of rotations, which could be greater than the count of digits in the current iteration, I get rotCount by mod operation.
Then rotate values by the RorateValues method and move it back to matrix by StepValuesOperation
private static void Main(string[] args)
{
int m, r, n;
long[,] matrix;
InitializeParams(out n, out m, out r, out matrix);
Console.WriteLine("Rotation times: " + r);
Console.WriteLine("Input matrix:");
PrintMatrix(matrix);
Console.WriteLine();
int deep = Math.Min(m, n) / 2;
for (int step = 0; step < deep; step++)
{
List<long> oldArr = new List<long>((n + m) * 2);
StepValuesOperation(false, step, oldArr, matrix);
int perim = oldArr.Count;
int rotCount = perim < r ? r % perim : r;
if (rotCount != 0 && rotCount != perim)
{
long[] newArr = new long[perim];
Console.WriteLine($"Rest rotation count {rotCount} from {r} with perimeter {perim}");
Console.WriteLine(string.Join(", ", oldArr));
RorateValues(rotCount, newArr, oldArr);
Console.WriteLine(string.Join(", ", newArr));
StepValuesOperation(true, step, newArr, matrix);
}
Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("Output matrix:");
PrintMatrix(matrix);
Console.ReadLine();
}
private static void RorateValues(int rotCount, IList<long> newArr, IList<long> oldArr)
{
int perim = oldArr.Count;
for (int i = 0; i < perim; i++)
{
int pos = i + rotCount;
if (pos >= perim)
{
pos -= perim;
}
newArr[pos] = oldArr[i];
}
}
Random initialization parameters of the matrix
private static void InitializeParams(out int n, out int m, out int r, out long[,] matrix)
{
Random rand = new Random();
n = 4;//rand.Next(2, 7) * 2;
m = 6;//rand.Next(1, 5) * 2;
r = rand.Next(1, 10000);
matrix = new long[n, m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i, j] = rand.Next(i + j, i + j + n * 10);
}
}
}
Move out of or into array the values of matrix
private static void StepValuesOperation(bool initialized, int step, IList<long> arr, long[,] matrix)
{
int sizeI = matrix.GetLength(0) - step;
int sizeJ = matrix.GetLength(1) - step;
int pos = 0;
for (int i = step; i < sizeI; i++, pos++)
{
if (!initialized)
arr.Add(matrix[i, step]);
else
matrix[i, step] = arr[pos];
}
for (int j = step; j < sizeJ; j++, pos++)
{
if (!initialized)
arr.Add(matrix[sizeI - 1, j]);
else
matrix[sizeI - 1, j] = arr[pos];
}
for (int i = sizeI - 1; i > step; i--, pos++)
{
if (!initialized)
arr.Add(matrix[i, sizeJ - 1]);
else
matrix[i, sizeJ - 1] = arr[pos];
}
for (int j = sizeJ - 1; j > step; j--, pos++)
{
if (!initialized)
arr.Add(matrix[step, j]);
else
matrix[step, j] = arr[pos];
}
}
private static void PrintMatrix(long[,] matrix)
{
int n = matrix.GetLength(0);
int m = matrix.GetLength(1);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
Console.Write(matrix[i, j] + " ");
Console.WriteLine();
}
}
My wrong output:
Rotation times: 9402
Input matrix:
29 3 24 9 39 28
9 38 31 20 24 44
27 27 38 31 10 37
32 15 25 40 40 42
Output matrix:
44 37 42 42 40 40
28 20 24 10 10 25
39 38 27 27 31 15
24 3 29 9 27 32
Yes the rotation can be done In Place. I am not a C# programmer so I stick to C++ syntax which is pretty close.
I would create function that rotate rectangle circumference
It can be done in place with single temp value (exactly as jackmott suggest). something like this:
void matrix_rect_ccw(int **a,int x0,int y0,int xs,int ys)
{
int x,y,xx,yy,x1,y1,a0;
// prepare constants
x1=x0+xs-1;
y1=y0+ys-1;
// rotate CCW
a0=a[x0][y0]; // store first element to temp
x=x0; y=y0; // destination
xx=x; yy=y; // source
for (xx++;x<x1;x++,xx++) a[x][y]=a[xx][yy]; xx--;
for (yy++;y<y1;y++,yy++) a[x][y]=a[xx][yy]; yy--;
for (xx--;x>x0;x--,xx--) a[x][y]=a[xx][yy]; xx++;
for (yy--;y>y0;y--,yy--) a[x][y]=a[xx][yy]; yy++;
a[x0][y0+1]=a0; // restore last element from temp
}
where x0,y0 is upper left corner of rectangle and xs,ys its size. The a[][] is the matrix. No need for matrix size parameter if the rectangle is fully inside...
To debug you can instead rotating filling the loop with increasing index for example:
int i=0;
for (xx++;x<x1;x++,xx++,i++) a[x][y]=i; xx--;
for (yy++;y<y1;y++,yy++,i++) a[x][y]=i; yy--;
for (xx--;x>x0;x--,xx--,i++) a[x][y]=i; xx++;
for (yy--;y>y0;y--,yy--,i++) a[x][y]=i; yy++;
or:
int i=0;
for (xx++;x<x1;x++,xx++,i++) a[xx][yy]=i; xx--;
for (yy++;y<y1;y++,yy++,i++) a[xx][yy]=i; yy--;
for (xx--;x>x0;x--,xx--,i++) a[xx][yy]=i; xx++;
for (yy--;y>y0;y--,yy--,i++) a[xx][yy]=i; yy++;
So you can check if the iterations goes through the right elements in the right order. This is the result for (x,y) called for all loops:
0 1 2 3 4
13 0 1 2 5
12 5 4 3 6
11 10 9 8 7
This is the (xx,yy) case:
13 0 1 2 3
12 5 0 1 4
11 4 3 2 5
10 9 8 7 6
do a for loop to rotate whole matrix
simply call the rotate from #1 for all loops. And also the whole thing step times. Something like this:
void matrix_ccw(int **a,int xs,int ys,int step)
{
int i,j,n;
// smallest size / 2 ... number of loops to rotate
n=xs; if (n<ys) n=ys; n/=2;
for (j=0;j<step;j++)
for (i=0;i<n;i++)
matrix_rect_ccw(a,i,i,xs-i-i,ys-i-i);
}
You should handle the CW/CCW separately just by changing the for loops order in the #1. Also you should bound step to modulo loop size. If the step is larger then half of the loop size then convert it to the opposite direction rotation to speed up the process. This is the input matrix I tested on:
11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
41 42 43 44 45
And this is rotated by step=1 in CCW direction:
12 13 14 15 25
11 23 24 34 35
21 22 32 33 45
31 41 42 43 44
You should also handle invalid matrix sizes for rotation to avoid confusion in future use...
[Notes]
The rotation can be done also without the step looping the whole thing by copying directly with step offset but for that you need to store a0[step] values instead of single one complicating this all a lot ...
I wonder if you could simplify it by representing the outer points as one circularly linked list and the inner points as another. Then it becomes pretty easy to rotate them in place with a single temp variable. If performance is a concern you can use a 1 dimensional array for each, and just handle the edge cases at the start and end.
edit - looks like the algorithm has to be more general than that, which would mean "n" circularly linked lists, which might not be any simpler.

Categories