Swapping values of two variables - c#

I'm currently having a hard time swapping two variables. I'd like to be able swap values once the user enters a value which is next to a blank cell
Apologies for my extremely messy code, I'm just picking up C#.
static void SwapNums(string[,] theBoard)
{
int col, row;
string swap;
string number = ReadNumber();
for (col = 0; col if (theBoard[col, row] == "")
{
theBoard[col, row] = number;
}
}
}
}
}
}
}
} < 6; col++)
{
for (row = 0; row < 6; row++)
{
if (theBoard[col,row] == number)
{
if (theBoard[col + 1, row] == "-" || theBoard[col - 1, row] == "-" || theBoard[col, row + 1] == "" || theBoard[col, row - 1] == "-")
{
swap = theBoard[col, row];
theBoard[col, row] = "";
for (col = 0; col < 6; col++)
{
for (row = 0; row < 6; row++)
{
if (theBoard[col, row] == "")
{
theBoard[col, row] = number;
}
}
}
}
} if (theBoard[col, row] == "")
{
theBoard[col, row] = number;
}
}
}
}
}
}
}
}
}
}
}
At the moment, this code is replacing the blank cellwith what the user entered, but is not replacing the cell that contains the number to p.

Make a function that gets the "position" of an element. Something like this?
const int ROWS = 6;
const int COLUMNS = 6;
static Tuple<int, int> GetPosition(string[,] theBoard, string value)
{
for (int i = 0; i < ROWS; i++)
for (int j = 0; j < COLUMNS; j++)
if (theBoard[i, j] == value)
return new Tuple<int, int>(i, j);
return new Tuple<int, int>(-1, -1);
}
Then, just swap the elements, something like this:
var numberPosition = GetPosition(theBoard, number);
var minusPosition = GetPosition(theBoard, "-");
theBoard[numberPosition.Item1, numberPosition.Item2] = "-";
theBoard[minusPosition.Item1, minusPosition.Item2] = number;
Make sure to check if the element was found! (Item1 and Item2 will be -1 if not)
Here you go, complete code that illustrates the concept: http://pastebin.com/5kjDPeX8
Edit:
Oh yeah, it should be only swapped if the element is next to it, so then, just do a check on the returned positions. Here is a replacement for the SwapNums method: (I didn't update the pastebin code above)
static void SwapNums(string[,] theBoard, string number)
{
var numberPosition = GetPosition(theBoard, number);
var minusPosition = GetPosition(theBoard, "-");
if (numberPosition.Item1 == -1 || minusPosition.Item1 == -1)
throw new Exception("Element " + number + " or - was not found in theBoard!");
if (numberPosition.Item1 == minusPosition.Item1) //they are in the same row
{
if (numberPosition.Item2 + 1 == minusPosition.Item2 ||
numberPosition.Item2 - 1 == minusPosition.Item2) // if they are next to eachother
{
theBoard[numberPosition.Item1, numberPosition.Item2] = "-";
theBoard[minusPosition.Item1, minusPosition.Item2] = number;
}
}
else if (numberPosition.Item2 == minusPosition.Item2) // same column
{
if (numberPosition.Item1 + 1 == minusPosition.Item1 ||
numberPosition.Item1 - 1 == minusPosition.Item1) //if they are above or below
{
theBoard[numberPosition.Item1, numberPosition.Item2] = "-";
theBoard[minusPosition.Item1, minusPosition.Item2] = number;
}
}
}
A slight digression (might be educational):
That Tuple<int, int> thing is just a class that contains two elements (namely int Item1 and int Item2), which is really convenient to use when your function needs to return two things (in our case, the row and column position of the element).
The <int, int> part means that the types of Item1 and Item2 will be int. The <something something etc.> things on classes generally are a part of something called generics, which is an advanced programming concept.
In short (about generics), it allows you to create a 'general' kind of an object, which could manipulate different types of object. Tuple here can contain pairs of any type of object; Tuple<string, int> would have string Item1 and int Item2.
But this isn't something you should worry about right now. When you've made a few classes of your own, you'll understand why this is convenient. For now, the Tuple class is the thing when you need to return 2 somethings from a function quick and easy.

Related

c# how to check in 2d matrix if all numbers above or below the slant are equel to 0?

i was requested to write a program that check in 2d of 6x6 if all numbers above or below the slant are equel to 0,
so far i created a simple matrix to help me figure it out, but i got stuck in the conditon and im not sure what to do..
exmaple:
exmaple
my code so far:(got stack in the condition)
int[,] matrix = new int[6, 6]
{
{1,0,0,0,0,0},
{0,2,0,0,0,0},
{0,0,3,0,0,0},
{0,0,0,4,0,0},
{0,0,0,0,5,0},
{0,0,0,0,0,6},
};
int row, col;
int zeroabove = 0;
int zerobelow = 0;
for (row = 0; row < 6; row++)
{
for(col = 0; col < 6; col++)
{
if (row == 0 || col == 0)
{
//idk what to put here
}
}
}
You should use a code like this:
int row, col;
bool isZeroAbove = true;
bool isZeroBelow = true;
for (row = 0; row < 6 && (isZeroAbove || isZeroBelow); row++)
for (col = 0; col < 6 && (isZeroAbove || isZeroBelow); col++)
if (matrix[row, col] != 0)
if (row > col)
isZeroBelow = false;
else if (row < col)
isZeroAbove = false;
My understanding of your question is that you want to check certain cells in the matrix depending on their coordinates. For example, if you are trying to check all cells that are above the diagonal formed by the line x = y then you wish to only check cells where x > y.
This sort of thing is pretty easy with LINQ, but LINQ doesn't work with two-dimensional arrays very well. So to make this possible, we need an extension method that will select over a two-dimensional array and return the coordinates and value for each cell. This can be accomplished with a simple extension method:
public static class ExtensionMethods
{
public class MatrixItem<T>
{
public int X { get; set; }
public int Y { get; set; }
public T Value { get; set; }
}
static public IEnumerable<MatrixItem<T>> Flatten<T>(this T[,] source)
{
for (int i = source.GetLowerBound(0); i <= source.GetUpperBound(0); i++)
{
for (int j = source.GetLowerBound(1); j <= source.GetUpperBound(1); j++)
{
yield return new MatrixItem<T> { X = j, Y = i, Value = source[i, j] };
}
}
}
}
When used with a two-dimensional array, this method will return a one-dimensional enumerable containing every cell along with its coordinates in an object called MatrixItem. The coordinates and value are exposed as separate properties.
Now that we can easily query against the matrix, the solution to your problem is very simple:
bool zeroAbove = !matrix.Flatten()
.Where(item => item.X > item.Y)
.Any(item => item.Value != 0);

How to increment mixed Alphanumeric in C#?

I have requirements in a project to generate sequential rows and columns which are alphanumeric values.
The end user will pass the start value of row and column he would like to start from, and how many rows and columns he wants to generate.
For letters the max value is Z
For numbers the max values is 9
If the end user passed these parameters:
StartRow = 0A
StartColumn = A9Z
rowsCount = 2
columnsCount = 5
I would like to get this result:
You might want to reconsider your approach. Rather than maintaining an alphanumeric value and trying to increment it, maintain the value as a class containing Row and Column values, and then use ToString to convert it to the alphanumeric representation. Like this:
class RowCol
{
private int _row;
private int _col;
public int Row
{
get { return _row; }
set
{
// Row is of the form <digit><letter
// giving you 260 possible values.
if (value < 0 || value > 259)
throw new ArgumentOutOfRangeException();
_row = value;
}
}
public int Col
{
get { return _col; }
set
{
// Col is <letter><digit><letter>,
// giving you 6,760 possible values
if (value < 0 || value > 6759)
throw new ArgumentOutOfRangeException();
_col = value;
}
}
public string RowString
{
get
{
// convert Row value to string
int r, c;
r = Math.DivMod(_row, 26, out c);
r += '0';
c += 'A';
return string.Concat((char)r, (char)c);
}
set
{
// convert string to number.
// String is of the form <letter><digit>
if (string.IsNullOrEmpty(value) || value.Length != 2
|| !Char.IsDigit(value[0] || !Char.IsUpper(value[1]))
throw new ArgumentException();
_row = 26*(value[0]-'0') + (value[1]-'A');
}
}
public string ColString
{
get
{
int left, middle, right remainder;
left = Math.DivRem(_col, 260, out remainder);
middle = Math.DivRem(remainder, 26, out right);
left += 'A';
middle += '0';
right += 'A';
return string.Concat((char)left, (char)middle, (char)right);
}
set
{
// Do standard checking here to make sure it's in the right form.
if (string.IsNullOrEmpty(value) || value.Length != 3
|| !Char.IsUpper(value[0] || !Char.IsDigit(value[1]) || !Char.IsUpper(value[2]))
throw new ArgumentException();
_col = 260*(value[0] - 'A');
_col += 26*(value[1] - '0');
_col += value[2] - 'A';
}
}
public override string ToString()
{
return RowString + '-' + ColString;
}
public RowCol(int row, int col)
{
Row = _row;
Col = _col;
}
public RowCol(string row, string col)
{
RowString = row;
RowString = col;
}
}
(Code not yet tested, but that's the general idea.)
That's a bit more code than you have, it hides the complexity in the RowCol class rather than forcing you to deal with it in your main program logic. The point here is that you just want to increment the row or column; you don't want to have to think about how that's done. It makes your main program logic easier to understand. For example:
string startRow = "0A";
string startCol = "B0A";
RowCol rc = new RowCol("0A", "B0A");
for (int r = 0; r < rowsCount; r++)
{
rc.ColString = "B0A";
for (int c = 0; c < columnsCount; c++)
{
Console.WriteLine(rc);
rc.Row = rc.Row + 1;
}
rc.Col = rc.Col + 1;
}
By casting this as a simple conversion problem and encapsulating it in a class, I've made the code more robust and flexible, and easier to test, understand, and use.
I have come up with very simple solution to implement that and I would like to share this Console application :
class Program
{
static void Main(string[] args)
{
var row = "0A";
var column = "A9Z";
var rowsCount = 2;
var columnsCount = 5;
var rowCharArray =row.ToArray().Reverse().ToArray();
var columnCharArray = column.ToArray().Reverse().ToArray();
for (int i = 0; i < rowsCount; i++)
{
for (int j = 0; j < columnsCount; j++)
{
columnCharArray = incrementChar(columnCharArray);
var currentColumn = string.Join("", columnCharArray.Reverse().ToArray());
var currentRow= string.Join("", rowCharArray.Reverse().ToArray());
Console.WriteLine(currentRow + "-" + currentColumn);
}
columnCharArray = column.ToArray().Reverse().ToArray();
rowCharArray= incrementChar(rowCharArray);
Console.WriteLine("-------------------------------");
}
Console.ReadLine();
}
static char[] incrementChar(char[] charArray,int currentIndex=0)
{
char temp = charArray[currentIndex];
if (charArray.Length -1 == currentIndex && (temp == '9' || temp == 'Z'))
throw new Exception();
temp++;
if(Regex.IsMatch(temp.ToString(),"[A-Z]"))
{
charArray[currentIndex] = temp;
}
else
{
if (Regex.IsMatch(temp.ToString(), "[0-9]"))
{
charArray[currentIndex] = temp;
}
else
{
currentIndex++;
incrementChar(charArray, currentIndex);
}
}
if (currentIndex != 0)
charArray = resetChar(charArray, currentIndex);
return charArray;
}
static char[] resetChar(char[] charArray,int currentIndex)
{
for (int i = 0; i < currentIndex; i++)
{
if (charArray[i] == 'Z')
charArray[i] = 'A';
else if (charArray[i] == '9')
charArray[i] = '0';
}
return charArray;
}
}

How to check the surrounding cells of a specific cell in terms of a specific values in a rectangular array in C#

I used the following method to check the cells around a specific cell in terms of a given indexes (row & column) if it zeros or not, see this array:
The cell that I need to check the surroundings of zeros (horizontally, Vertically or diagonally) could be at the first row, last row, first column, last column or in between i.e. it could be any cell in the rectangular array depending to the "rowIndex" and "colIndex" which are passed to the method.
static Boolean TestZero(int[,] array,int colIndex, int rowIndex)
{
/*Check Corners*/
//First Corner
if ((rowIndex == 0) && (colIndex == 0))
{
if (array[1, 0] == 1 || array[0, 1] == 1 || array[1, 1] == 1) return false;
}
//Second Corner
if ((rowIndex == 0) && colIndex >= array.GetUpperBound(0))
{
if (array[array.GetUpperBound(0) - 1, 0] == 1 || array[array.GetUpperBound(0),1] == 1 || array[array.GetUpperBound(0)-1,1 ] == 1) return false;
}
//Third Corner
if ((rowIndex >= array.GetUpperBound(1)) && (colIndex == 0))
{
if (array[0, array.GetUpperBound(1) - 1] == 1 || array[1, array.GetUpperBound(1)] == 1 || array[1, array.GetUpperBound(1)-1] == 1) return false;
}
//Fourth Corner
if ((rowIndex >= array.GetUpperBound(1)) && (colIndex >= array.GetUpperBound(0)))
{
if (array[array.GetUpperBound(0), array.GetUpperBound(1) - 1] == 1 || array[array.GetUpperBound(0) - 1, array.GetUpperBound(1) - 1] == 1 || array[array.GetUpperBound(0) -1, array.GetUpperBound(1)] == 1) return false;
}
/* Check Boundries But Not Corners */
//First Row
if ((rowIndex == 0) && (colIndex != array.GetUpperBound(0)) && (colIndex != 0))
{
for (int i = rowIndex; i <= rowIndex + 1; i++)
{
for (int j = colIndex - 1; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
//Last Row
if ((rowIndex >= array.GetUpperBound(1)) && (colIndex != array.GetUpperBound(0)) && (colIndex != 0))
{
for (int i = rowIndex; i <= rowIndex - 1; i--)
{
for (int j = colIndex - 1; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
//First & Last Columns
if ((rowIndex != array.GetUpperBound(1)) && ((rowIndex != 0)))
{
//First column
if(colIndex==0)
{
for (int i = rowIndex-1; i <= rowIndex + 1; i++)
{
for (int j = colIndex; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
//Last Column
if (colIndex == array.GetUpperBound(0))
{
for (int i = rowIndex -1; i <= rowIndex + 1; i++)
{
for (int j = colIndex; j <= colIndex - 1; j--)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
}
/* In Between i.e. Not the Array Boundries */
if(colIndex!=0 && colIndex != array.GetUpperBound(0) && rowIndex !=0 && rowIndex != array.GetUpperBound(1)) {
for (int i = rowIndex - 1; i <= rowIndex + 1; i++)
{
for (int j = colIndex - 1; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
} // end if statment
return true;
}
I got some wrong result and I tried to figure out the problem, but I could not!.
Results:
1- Rectangular arrays (chromosomes in a genetic algorithm population):
2- The indexes of the cells that we need to check its surroundings:
|(2,3)||(2,3)||(0,1)||(1,3)||(0,3)||(1,3)|
3- Arrays that contains zero in at least one of the surrounding cells of each of the intended cells:
Chromosome 0 : True Chromosome 1 : True Chromosome 2 : False
Chromosome 3 : True Chromosome 4 : False Chromosome 5 : True
Any help to figure out why I got some wrong results!!.
From what I can see, your method checks if a cell is surrounded by cells filled with 1s and returns false if it is. Your code is too complicated for it because you try to look at everything as a different case instead of generilizing it making it very difficult to debug. The following method is an example of a better way to implement the check:
bool TestZero(int[,] mat, int row, int col)
{
int ones = 0, cells = 0;//define counters
//define bounderies
int rowLen = Math.Min(row + 1, mat.GetLength(0) - 1),
colLen = Math.Min(col + 1, mat.GetLength(1) - 1),
rowIdx = Math.Max(0, row - 1),
colIdx = Math.Max(0, col - 1);
for (int i = rowIdx; i <= rowLen; i++)
{
for (int j = colIdx; j <= colLen; j++)
{
//if it is our given index, continue
if (i == row && j == col)
continue;
++cells;//increment cells counter
if (mat[i, j] == 1)//if the value of the cell is 1
++ones;//increment the ones counter
}
}
return ones < cells;//if there are less cells with '1' then
//surrounding cells, return true.
}
What we do here is:
create two counters: one counts the amount of cells surrounding the given cell and another counts how many ones surround it.
We save the bounderies of the loops in variables:
rowLen: the last row index to visit. It is the smaller value between the row index of the given cell + 1 and the last row index in the matrix.
rowIdx: the starting row index to check in the loop. The bigger value between the row index of the given cell - 1 and the first row index in the matrix (0).
colLen: same as rowLen just for the columns.
colIdx: same as rowIdx just for columns.
Then we iterate over the mini-matrix we created with our bounderies. For each cell, if it not our given cell we increment the cells counter and if it is equal to 1, we increment the ones counter.
At the end, if the ones counter is smaller than the cells counter, we return true since our cell is not surrounded by 1s.
EDIT
The example above returns true if not all of the surrounding cells contain 1.
But it is possible to change the return value to match different cases:
If you want to return true only when there are 0 cells with 1, change the return line to the following: return ones == 0;
In this case, the cells counter is unecessary, only the ones counter is needed.
If you want to return true only when all the surrounding cells contain 1, change to the following: return ones == cells;
You can basically change the return value to whatever situation you need, it's very flexible.
As always, the first rule when programming is: break down the problem into smaller bits.
I'll be using C#7 features just for the fun of it. If you are not using C#7, consider translating it to previous versions as an excercise.
Ok, first step. You need neigbouring cells? Allright, lets get all possible neighbouring cells, not caring about wether they exist or not. We'll take care of that later; remember, one small problem at a time.
private static IEnumerable<(int Row, int Column)> GetAllNeighbouringCoordinates(int row, int column)
{
yield return (row - 1, column - 1);
yield return (row - 1, column);
yield return (row - 1, column + 1);
yield return (row, column + 1);
yield return (row + 1, column + 1);
yield return (row + 1, column);
yield return (row + 1, column - 1);
yield return (row, column - 1);
}
Ok, now we have a method that will give us all possible 8 neighbours. The order in which I'm returning them is clockwise, starting at the top left neighbour. Order is unimportant in this case, so consider it an implementation detail.
Now, we need someway to check if any given cell is valid. Ok, that seems easy too:
private static bool IsValidCoordinate((int Row, int Column) coord, int rowCount, int columnCount)
{
Debug.Assert(rowCount >= 0);
Debug.Assert(columnCount >= 0);
if (0 > coord.Row || coord.Row >= rowCount ||
0 > coord.Column || coord.Column >= columnCount)
return false;
return true;
}
Ok, that was pretty simply too. See how hard it is to introduce a bug in simple methods?
Also, notice the assertions at the start of the method. This method is not supposed to work with nonsensical values of rowCount and columnCount so I enforce that in code. Because the method is a private helper method, I can simply assert and not throw an exception. If an assertion fails in testing, I know I have a bug in my code.
Now, we just have to glue both things together. Lets build a method that returns the value of all neighbouring cells. We'll use some LINQ to remove the unsightly loops:
public static IEnumerable<T> GetNeighbouringCells<T>((int Row, int Column) coord, T[,] cells)
{
if (cells == null)
throw new ArgumentOutOfRangeException();
if (!IsValidCoordinate(coord, cells.GetLength(0), cells.GetLength(1)))
throw new ArgumentOutOfRangeException();
return GetAllNeighbouringCoordinates(coord.Row, coord.Column)
.Where(c => IsValidCoordinate(c, cells.GetLength(0), cells.GetLength(1)))
.Select(c => cells[c.Row, c.Column]);
}
And there you go, now you have a simple method that will return every neighbouring value of any given cell.
Now, you need all cells where at least one neighbouring cell is zero? Easy peasy:
public static IEnumerable<(int Row, int Column)> CellsWithAtLeastOneNeighbourEqualTo<T>(
this T[,] cells, T value)
{
for (var row = 0; row < cells.GetLength(0); row++)
{
for (var column = 0; column < cells.GetLength(1); column++)
{
if (GetNeighbouringCells((row, column), cells).Any(c => c.Equals(value)))
{
yield return (row, column);
}
}
}
}
And now if you take it for a small ride:
var cells = new[,] { { 0, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };
var n = cells.CellsWithAtLeastOneNeighbourEqualTo(0).ToList();
You will get the expected results:
[0, 1]
[1, 0]
[1, 1]
This seems like a simple game of life program. You should not check everything invidually but use for example a function to check if given a cell's x and y coordinates exist in the table.
Pseudocode:
for each cell in celltable
for each cell surrounding
if cell index is valid && alive
alive = alive + 1;
endif
endfor
if alive is valid
add cell to retList
alive = 0;
endfor
No-one wants to debug huge if-else systems.
This is not good in performance, but may solve your problem.
PS. please notice that I renamed your colIndex and rowIndex to x and y.
static bool TestZero(int[,] array, int x, int y)
{
try
{
if (array[x - 1, y - 1] == 1) return false;
}
catch { }
try
{
if (array[x, y - 1] == 1) return false;
}
catch { }
try
{
if (array[x + 1, y - 1] == 1) return false;
}
catch { }
try
{
if (array[x - 1, y] == 1) return false;
}
catch { }
try
{
if (array[x, y] == 1) return false;
}
catch { }
try
{
if (array[x + 1, y] == 1) return false;
}
catch { }
try
{
if (array[x - 1, y + 1] == 1) return false;
}
catch { }
try
{
if (array[x, y + 1] == 1) return false;
}
catch { }
try
{
if (array[x + 1, y + 1] == 1) return false;
}
catch { }
return true;
}
I test with your original case (the first image in your post), use the following code.
private static int[,] array = { { 0, 0, 1, 1 }, { 0, 0, 0, 1 }, { 0, 1, 1, 1 }, { 1, 0, 1, 0 } };
static void Main(string[] args)
{
for (int i = 0; i <= array.GetUpperBound(0); i++)
{
for (int j = 0; j <= array.GetUpperBound(1); j++)
{
Console.Write(TestZero(array, i, j) + " ");
}
Console.WriteLine();
}
Console.ReadKey();
}
And the result is
True False False False
False False False False
False False False False
False False False False
I'm going to test more cases, but at last your can take a try now.

Excel Interop - Insert Rows & Repeat

OK so I have this function that works fine at inserting rows and then putting data within those rows.
public void inputRowData(string[] data, int rds)
{
int bestRow = getRowByRDS(rds);
string val = getValueOfCell(bestRow, 6);
if (val == null || val.Equals(""))
{
shiftRows(bestRow, data.Length-1);
string[] formatedData = formatOutput(bestRow, data);
// transform formated data into string[,]
string[][] splitedData = formatedData.Select(s => s.Split('\t')).ToArray();
var colCount = splitedData.Max(r => r.Length);
var excelData = new string[splitedData.Length, colCount];
for (int i = 0; i < splitedData.Length; i++)
{
for (int j = 0; j < splitedData[i].Length; j++)
{
excelData[i, j] = splitedData[i][j];
}
}
oSheet.get_Range("A" + bestRow.ToString()).Resize[splitedData.Length, colCount].Value = excelData;
}
else
{
Console.WriteLine("Line has some information already, skipping 1 more");
shiftRows(bestRow, data.Length + 1);
}
}
Now I if you take a look i find the "bestRow" which is determined by the last row in the excel with a int value at a particular column the code is show here:
private int getRowByRDS(int id)
{
int bestfit = -1;
Boolean foundOne = false;
Microsoft.Office.Interop.Excel.Range usedRange = oSheet.UsedRange;
for (int i = 2; i < usedRange.Rows.Count; i++)
{
string val = getValueOfCell(i, 3);
if (val == null)
continue;
int rds = int.Parse(val);
Console.WriteLine(val + " " +i);
if (rds == id)
{
bestfit = i;
foundOne = true;
}
else
if (foundOne)
return bestfit;
}
return bestfit;
}
What happens is that when it finishes on set of data in the inputRowData method it will move to another set with a different rds value. It will try to call getRowByRDS but it will throw an error.
On debug it looks like it didnt update the sheet... so lets say the first set of 10 strings was inserted at row 900, the and if the next set was suppose to start right after it bestRow will return 901 not 911.
The error is
A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in TTE Tool.exe
I found the problem. I disposed of the excel beforehand by mistake.

Count similar adjacent items in List<string>

I'm trying to find similar adjacent items in List and count its number, e.g.:
List<string> list = new List<string> {"a", "a", "b", "d", "c", "c"};
Desired Output:
a = 2, c = 2
What I've done is use for loop to iterate over each element of the list and to see whether it has similar adjacent element, but understandably it gives ArgumentOutOfRangeException() because I don't know how to keep track of the position of the iterator so that it doesn't go out of bounds. Here's what I've done:
for (int j = 0; j < list.Count; j++)
{
if (list[j] == "b")
{
if ((list[j + 1] == "b") && (list[j - 1] == "b"))
{
adjacent_found = true;
}
}
}
Having said that, if there's another easier way to find similar adjacent elements in a List other than using for loop iteration, please advise. Thanks.
You can do something like this:
static IEnumerable<Tuple<string, int>> FindAdjacentItems(IEnumerable<string> list)
{
string previous = null;
int count = 0;
foreach (string item in list)
{
if (previous == item)
{
count++;
}
else
{
if (count > 1)
{
yield return Tuple.Create(previous, count);
}
count = 1;
}
previous = item;
}
if (count > 1)
{
yield return Tuple.Create(previous, count);
}
}
for (int i= 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
if (list[i] == list[j])
{
adjacent_found = true;
count++;
}
}
}
Check this:
Dictionary<char,int> dic=new Dictionary<char,int>();
for(int i=1;i<list.count;i++)
{
if(list[i]==list[i-1])
{
if(dic.ContainsKey(list[i]))
{
dic[list[i]]+=1;
}
else
{
dic.Add(list[i],2)
}
}
}
To avoid ArgumentOutOfRangeException use for (int j = 1; j < list.Count - 1; j++). Desired answer can't be achieved this way. Try this:
IEnumerable<Adjacent> CountAdjacents(List<string> source)
{
var result = new List<Adjacent>();
for (var i = 0; i < source.Count() - 1; i++)
{
if (source[i] == source[i + 1])
{
if (result.Any(x => x.Word == source[i]))
{
result.Single(x => x.Word == source[i]).Quantity++;
}
else
result.Add(new Adjacent
{
Word = source[i],
Quantity = 2
});
}
}
return result;
}
class Adjacent
{
public string Word;
public int Quantity;
}
Maintain an int array of 256 size, initialized to 1. Run a loop [O(n)] for i=0 to i-2, compare each char with the next char. If same then find the ascii value of the char and increment the corresponding value in array.
Hope this helps!

Categories