Related
I was examining a code about operator overloading, and I saw an interesting way of use of % to convert seconds to minutes if second variable is bigger than 59.
It seems while a<b (both int) a%b returns a, I havent read a rule about this before, I wanna learn why it returns a, is it about they are declared as integers, are there any more rules about %?
Thanks
% is the modulo operator. The modulo operation a % b returns the remainder z in the division
a / b = x, remainder z
In other words, it returns y in this equation:
x * b + y = a
*The second equation also shows why this works for fractional numbers too.**
Thus, the following examples (not complete) are true:
-5 % 4 = -1
-4 % 4 = 0
-3 % 4 = -3
...
1 % 4 = 1
2 % 4 = 2
3 % 4 = 3
4 % 4 = 0
5 % 4 = 1
...
101.4 % 100.3 = 1.1
In your example converting seconds to minutes and seconds, you probably read something like this:
int totalseconds = 72;
int minutes = totalseconds / 60; // == 1
int seconds = totalseconds % 60; // == 12
This is the same thing: the minutes are calculated as totalseconds / 60, which is an integral division that "rounds" to the lower integer for positive numbers, thus the result of 1. The seconds left are calculated as the remainder of 72 and 60.
You could also calculate the seconds like
int seconds = totalseconds - (minutes * 60)
In general, for any a and any b:
a / b = (SomeConstant * b) + RemainderOfb*
So if a = 2 and b = 5 means a < b then:
How many SomeConstant do you need to multiply b with, in order to get close to a? And once you get close, what is your remainder?
so if
a / b = (5 * 0) + 2
Means Remainder = 2 out of 5.
Then: a % b means the Remainder with respect to b, which is = 2.
And if a = 3 and b = 2 means a > b then:
If you remove all the "b"s from a, what is the Remainder? You can do
it the easy way: Subtract "a" from "b" till you can't subtract
anymore. Or:
a / b = SomeConstant * a (which is how many "a"s did you subtract) + Remainder
Substitute:
a / b = (1 * 2) + 1
Means Remainder = 1 out of the 2
Then a % b equals the Remainder with respect to a, which is = 1
a mod b is the remainder of a a / b, therefore if a < b AND a > -b the remainder is always a.
The following rules are valid for C#, but might differ in other languages, refer to Modulo operation page on Wikipedia for more information.
0 mod 3 = 0
1 mod 3 = 1
2 mod 3 = 2
3 mod 3 = 0
4 mod 3 = 1
-1 mod 3 = -1 // 2 in some languages
-2 mod 3 = -2 // 1 in some languages
-3 mod 3 = 0
-4 mod 3 = -1 // 2 in some languages
// if your language supports mod of floats
1.5 mod 3 = 1.5
5.5 mod 3 = 2.5
-1.5 mod 3 = -1.5 // 1.5 in some languages
-5.5 mod 3 = -2.5 // 0.5 in some languages
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;
}
}
}
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.
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.
I need to know column name of a spread sheet with a given starting colum upto n number of columns
let say starting column is "AB", I want to know the column (label) after 99 columns.
For those who need Ralph answer in T-SQL flavor
Create FUNCTION fsExcelValueToColum(#value int) returns varchar(3) as
begin
DECLARE #DIGIT INT,#RV VARCHAR(3);set #rv=''
IF #VALUE=0 RETURN #rv
WHILE #VALUE > 0
BEGIN
SET #DIGIT = #VALUE % 26
IF #DIGIT = 0
BEGIN
set #RV=#RV+'Z'
set #RV=#RV+dbo.fsExcelValueToColum(#value /26 -1)
return #rv
END
set #rv=#rv+char(#digit+64)
set #value=(#value-#digit) /26
END
return #rv
end
USE [ecs]
GO
/****** Object: UserDefinedFunction [dbo].[fnExcelColumnToValue] Script Date: 12/06/2009 10:33:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[fnExcelColumnToValue](#Column varchar(3)) returns int as
Begin
--declare #column varchar(10); select #column = 'AC'
declare #value int, #pow int,#i int,#n int
select #pow=1,#VALUE=0,#I=LEN(#COLUMN)
SET #I=LEN(#COLUMN)
WHILE #I >= 1
BEGIN
SET #VALUE=#VALUE+#POW*((ASCII(SUBSTRING(UPPER(#COLUMN),#I,1)) - 65) +1)
SET #POW=#POW *26
SET #I=#I-1
END
return #value
end
Think of the characters A, B, ... , Z as representing the values 1, 2, ... 26 (you can't quite think of this as being base-26 because there is no character representing 0 nor can there be as we don't want, for example, AA to mean 0). So we have to engage in some trickery to deal with this:
static int ColumnToValue(string column) {
int value = 0;
int pow = 1;
for (int i = column.Length - 1; i >= 0; i--) {
value += pow * (column[i] - 'A' + 1);
pow *= 26;
}
return value;
}
static string ValueToColumn(int value) {
if (value == 0) {
return string.Empty;
}
StringBuilder sb = new StringBuilder();
while (value > 0) {
int digit = value % 26;
if (digit == 0) {
sb.Insert(0, 'Z');
return sb.Insert(0, ValueToColumn(value / 26 - 1)).ToString();
}
sb.Insert(0,(char)(digit + 'A' - 1));
value = (value - digit) / 26;
}
return sb.ToString();
}
So that
Console.WriteLine(ValueToColumn(ColumnToValue("AB") + 99));
outputs DW and
Console.WriteLine(ValueToColumn(ColumnToValue("AB") - 2));
outputs Z. Obviously you can wrap this all up in a nice class and make it fluent or what have you.
Explanation: Think, for example, of the value 702 and a usual base-26 notation where there is a digit representing 0 (I will use the notation _ to represent this magical digit so that we don't get confused between the value 0 and the digit 0). Let's try to convert 702 (decimal) to base-26. The usual algorithm is compute 702 % 26 which is 0 so that we would have the last digit as being _. Then we would divide by 26 to obtain 27. We would note that 27 % 26 is 1 so that the penultimate digit is A. Then we would divide by 26 to obtain 1, compute 1 % 26 to obtain 1 and report that the most-significant digit is A. We would return AA_ as the string representing 702 in base-26 with digits (_ = 0, A = 1, ... Z = 26) (check: 1 * 26^2 + 1 * 26^1 + 0 * 26 = 702). For our purposes, this is wrong. We wanted to get back the string ZZ (because we have 26 digits A, B, C, ... Z representing 1, 2, ... 26 (remember, no digit representing the value 0!) so that ZZ = 26 * 26^1 + 26 * 26^0 = 702). It turns out in our system that numbers congruent to 0 modulo 26 should have least-significant digit Z. So this suggests that our algorithm should be check and see if value is congruent to 0 modulo 26. If it is, prepend a Z and then prepend the string representing the value value / 26 - 1. This is the algorithm that you see above.
I wrote this a while ago in Clipper (old XBASE compiler)
if nColumn <= 26 // Column 26 or less ?
retval := chr(nColumn+64)
else
temp := int(nColumn/26) // Compute first letter
remd := nColumn % 26 // and second letter and
retval:= if(remd=0,chr(temp+63)+"Z",;
chr(temp+64)+chr(remd+64))
endif
This works for spreadsheets with up to 256 columns, I am not sure if the formula is the same for columns beyond that. I am not sure what programming language you are using, but the Clipper code is pretty simple...
Here's my tuppence worth (quickly written - I'm sure it can be tidied up):-
public static string ToAlpha(int index)
{
if (index <= 0)
{
throw new ArgumentOutOfRangeException("index");
}
--index;
var chars = new List<char>();
int x = index;
do
{
int r = x % 26;
chars.Insert(0, Convert.ToChar(65 + r));
x /= 26;
} while (x > 26);
if (x > 0)
{
chars.Insert(0, Convert.ToChar(64 + x));
}
return new string(chars.ToArray());
}
public static int ToNumeric(string index)
{
int total = 0;
var chars = index.ToCharArray();
int chrIndex = chars.Length - 1;
foreach (char chr in chars)
{
total += (Convert.ToInt32(chr) - 64) * (int)(Math.Pow(26d, (double)chrIndex));
--chrIndex;
}
return total;
}
Usage
string input = "AB";
string output = ToAlpha(ToNumeric(input) + 99);