char 2D array compression - c#

There is a .txt file what I have to read, compress and make an output txt for the compressed txt. Could anyone tell me what should I fix in my code?
My code:
namespace Tomorites
{
class Compression
{
public void Compress(char[,] source)
{
for (int i = 0; i < source.GetLength(0); i++)
{
int white = 0;
int red = 0;
for (int j = 0; j < source.GetLength(1); j++)
{
if (source[i, j] == 'P')
{
if (source[i, j] > 0)
{
red++;
Console.Write(red + " P ");
}
}
else if(source[i,j]=='F')
{
if (source[i, j] > 0)
{
white++;
Console.Write(white + " F ");
}
}
}
Console.WriteLine();
}
}
}
}
My console output
Source txt file
The compressed txt file which has to be

You was pretty close, but messed one important thing: reset first char counter when second char appear or second char counter when first char appear.
Also source[i, j] > 0 condition do nothing for you.
So at result we may have:
Fill source array:
static void Main(string[] args)
{
// Declare array
char[,] source = new char[7, 10];
// Fill array as at example
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
source[i, j] = i == 3 || j == 3 ? 'F' : 'P';
// Print filled array to Console
Console.WriteLine("Source:\n" + new string('-', 10));
for (int i = 0; i < source.GetLength(0); i++)
{
for (int j = 0; j < source.GetLength(1); j++)
Console.Write(source[i, j] + " ");
Console.WriteLine();
}
// Just new line
Console.WriteLine();
// Now "compress"
Console.WriteLine("Compressed:\n" + new string('-', 10));
Compress(source);
Console.ReadKey();
}
Source output:
Compress source array:
static void Compress(char[,] source)
{
// Declare counters for P and F chars
int PCount = 0, FCount = 0;
for (int i = 0; i < source.GetLength(0); i++)
{
for (int j = 0; j < source.GetLength(1); j++)
{
if (source[i, j] == 'P')
{
// If char is P - then count P's up
PCount++;
// If there was F char counted before (> 0) - print it and reset counter
if (FCount > 0)
{
Console.Write(FCount + " F ");
FCount = 0;
}
}
else if (source[i, j] == 'F')
{
// If char is P - then count F's up
FCount++;
// If there was P char counted before (> 0) - print it and reset counter
if (PCount > 0)
{
Console.Write(PCount + " P ");
PCount = 0;
}
}
}
// Before go to next "row" - print remained P or F counts and again, reset counters
if (PCount > 0)
{
Console.Write(PCount + " P ");
PCount = 0;
}
else if (FCount > 0)
{
Console.Write(FCount + " F ");
FCount = 0;
}
// Go new "row"
Console.WriteLine();
}
}
Compressed output:
UPD.
My answer is just solution for a provided example source and example output. #Dmitry Bychenko's solution is universal, not dependent on any two specific characters so in general use I recommend his way.

You can try something like this (you can fiddle with the code):
public static string Compress(char[,] source) {
if (null == source || source.GetLength(0) <= 0 || source.GetLength(1) <= 0)
return "";
StringBuilder sb = new StringBuilder();
for (int row = 0; row < source.GetLength(0); ++row) {
if (sb.Length > 0)
sb.AppendLine();
int count = 0;
char prior = '\0';
bool left = true;
for (int col = 0; col < source.GetLength(1); ++col) {
if (count == 0 || prior == source[row, col])
count += 1;
else {
if (!left)
sb.Append(' ');
left = false;
sb.Append($"{count} {prior}");
count = 1;
}
prior = source[row, col];
}
if (!left)
sb.Append(' ');
sb.Append($"{count} {prior}");
}
return sb.ToString();
}
Demo:
char[,] test = new char[,] {
{'a', 'a', 'a', 'a'},
{'a', 'b', 'c', 'c'},
};
Console.WriteLine(Compress(test));
Outcome:
4 a
1 a 1 b 2 c

Related

How to count letter 'u' in given .txt file

I have a grid which, you can see in the image. Firstly, I needed to find how many different connections of letter 'u' are there. I used a youtube explanation video where they talked about Number Of Islands from LeetCode. Using +- same strategy I found that there's 2 different connections of letter 'u'. The first connection contains 22 letter 'u' and the second connection contains 14 letter 'u'. My Output shoud look like this 2 (Different connections, which I already found), 22(dont have this), 14(dont have this
InPut1 :
Input1 data
6 and 15 are dimensions.
OutPut1 :
2
22
14
InPut2 :
Input2 data
OutPut2 :
1
5
Now , I need to write an algorithm to calculate how many 'u' letters does each connection has. For example the first connection (In Input1 photo it's colored red) has 22 letter 'u' connected to each other. The second connection (In Input1 photo it's colored pink) has 14 letter 'u' connected to each other.
Also, I can't use linq.
In this code you can see that I already found that there are 2 different connections.
I also wrote a code to find how many letters 'u' does each connection contains method called : public static int CountLetterUInConnection(char[][] grid), but it doesn't work.
Maybe someone can spot my mistake and show me the right way? Or maybe I'm doing it all wrong and I need to redo it?
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string path = "App_Data/Map.txt";
string[] lines = File.ReadAllLines(HttpContext.Current.Server.MapPath(path));
int Width = int.Parse(lines[0]);
int Height = int.Parse(lines[1]);
Label4.Text = "Width: " + Width.ToString();
Label5.Text = "Height: " + Height.ToString();
for (int i = 2; i < lines.Length; i++)
{
var newRow = new TableRow();
var newCell = new TableCell();
newCell.Text = lines[i];
newRow.Cells.Add(newCell);
Table1.Rows.Add(newRow);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
string path = "App_Data/Map.txt";
string map = File.ReadAllText(HttpContext.Current.Server.MapPath(path));
char[][] grid = GetGridGFromMap(map);
int NumberOfMoles = TaskUtils.LettersIsU(grid);
int Count = TaskUtils.CountLetterUInConnection(grid);
// Label1.Text = "Cave count: " + NumberOfMoles.ToString();
Label1.Text = Count.ToString();
}
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
}
protected void TextBox2_TextChanged(object sender, EventArgs e)
{
}
private char[][] GetGridGFromMap(string map)
{
string[] lines = map.Split('\n');
char[][] grid = new char[lines.Length][];
for(int i =0; i < lines.Length; i++)
{
grid[i] = lines[i].ToCharArray();
}
return grid;
}
}
class TaskUtils
{
public static int LettersIsU(char[][] grid)
{
int count = 0;
for (int i = 0; i < grid.Length; i++)
{
for (int j = 0; j < grid[i].Length; j++)
{
if (grid[i][j] == 'u')
{
count++;
SetCountedLetters(grid, i, j);
}
}
}
return count;
}
private static void SetCountedLetters(char[][] grid, int i, int j)
{
if (i < 0 || i >= grid.Length || j < 0 || j >= grid[i].Length || grid[i][j] == 'z')
return;
grid[i][j] = 'z';
SetCountedLetters(grid, i + 1, j);
SetCountedLetters(grid, i - 1, j);
SetCountedLetters(grid, i, j + 1);
SetCountedLetters(grid, i, j - 1);
}
public static int CountLetterUInConnection(char[][] grid)
{
int count = 0;
for (int i = 0; i < grid.Length; i++)
{
for (int j = 0; j < grid[i].Length; j++)
{
if (grid[i][j] == 'u')
{
count++;
if ((i - 1 >= 0 && grid[i - 1][j] == 'u') || (i + 1 < grid.Length && grid[i + 1][j] == 'u')
|| (j - 1 >= 0 && grid[i][j - 1] == 'u') || (j + 1 < grid[i].Length && grid[i][j + 1] == 'u'))
{
count++;
}
}
}
}
return count;
}
}`
If this were me, I'd refactor your int LettersIsU(char[][] grid) to become int[] LettersIsU(char[][] grid) whereby the length of the array is the number of contiguous groups found and each value in the array is the count in each group.
I'd do something like this:
public static int[] LettersIsU(char[][] grid)
{
int[][] found = new int[grid.Length][];
Dictionary<int, int> count = new();
void SetCountedLetters(char[][] grid, int i, int j)
{
if (i < 0 || i >= grid.Length || j < 0 || j >= grid[i].Length || found[i][j] != 0 || grid[i][j] != 'u')
return;
found[i][j] = count.Count;
count[count.Count] += 1;
SetCountedLetters(grid, i + 1, j);
SetCountedLetters(grid, i - 1, j);
SetCountedLetters(grid, i, j + 1);
SetCountedLetters(grid, i, j - 1);
}
for (int i = 0; i < grid.Length; i++)
found[i] = new int[grid[i].Length];
for (int i = 0; i < grid.Length; i++)
for (int j = 0; j < grid[i].Length; j++)
if (grid[i][j] == 'u' && found[i][j] == 0)
{
count[count.Count + 1] = 0;
SetCountedLetters(grid, i, j);
}
int[] output = new int[count.Count];
for (int k = 0; k < count.Count; k++)
output[k] = count[k + 1];
return output;
}

LCS C# Algorithm - Get the deleted lines and added lines in previous and current text

I have to rewrite the LCS algorithm because some company policies.
I've already get done the LCS algorithm, but next step is to identify which lines were removed from the previous text and which one were added in the current text.
I tried a simple check thought the lines, but it won't work if I got a text with duplicated lines.
He is my code:
LCS Method
private static string[] LcsLineByLine(string previous, string current)
{
string[] Previous = previous.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string[] Current = current.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string lcsResult = string.Empty;
int a = Previous.Length;
int b = Current.Length;
int[,] table = new int[a + 1, b + 1];
//create a table with first line and column equal 0
for (int i = 0; i <= a; i++)
table[i, 0] = 0;
for (int j = 0; j <= b; j++)
table[0, j] = 0;
//create a table matrix
for (int i = 1; i <= a; i++)
{
for (int j = 1; j <= b; j++)
{
if (string.Equals(Previous[i - 1].Trim(), Current[j - 1].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
table[i, j] = table[i - 1, j - 1] + 1;
}
else
{
table[i, j] = Math.Max(table[i, j - 1], table[i - 1, j]);
}
}
}
//get the lcs string array with the differences
int index = table[a, b];
string[] lcs = new string[index + 1];
lcs[index] = "0";
while (a > 0 && b > 0)
{
if (string.Equals(Previous[a - 1].Trim(), Current[b - 1].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
lcs[index - 1] = Previous[a - 1].Trim();
a--;
b--;
index--;
}
else if (table[a - 1, b] > table[a, b - 1])
a--;
else
b--;
}
return lcs;
}
And this is the code that is not working with duplicated lines with same value.
Method to get all deleted items in the previous text:
private List<DiffItem> GetDiffPrevious(string[] previous, string[] diff)
{
List<DiffItem> differences = new List<DiffItem>();
//check items deleted
int line = 0;
for (int i = 0; i < previous.Length; i++)
{
bool isAbsent = false;
for (int j = 0; j < diff.Length; j++)
{
if (string.Equals(previous[i].Trim(), diff[j].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
differences.Add(new DiffItem() { Position = line, Text = diff[j], Status = DiffStatus.Equal });
line++;
isAbsent = false;
break;
}
else
{
isAbsent = true;
}
}
//mark as deleted
if (isAbsent)
{
differences.Add(new DiffItem() { Position = line, Text = previous[i].Trim(), Status = DiffStatus.Deleted });
line++;
}
}
return differences;
}
If anyone could help me or any feedback would be great. Just a reminder, I cannot use third party libraries.
Thanks in advance.
I found the solution!
Basically, I rewrite the two lists and translated using Hashtable, so all the values will be unique by line. Then, I use the method LCS and got the result as expected.
I hope it helps somebody.

Magic Square Code Single Even number in C#

can you help me to create a logic for magic square metric. In given example, I have created a code for generate Magic Square for odd numbers like 3x3, 5x5, 7x7 metric and double even numbers like 4×4 , 8×8 but unable to found a proper solution for create single even value magic square metric like 6x6, 10x10 etc.
In current implementation anyone can enter a number (n) in input and it will create a nxn magic square metric. But not working fine with single even numbers
class Program
{
public static void Main(string [] args )
{
Console.WriteLine("Please enter a number:");
int n1 = int.Parse(Console.ReadLine());
// int[,] matrix = new int[n1, n1];
if (n1 <= 0)
{
Negativ();
}
else if (n1 == 2)
{
Zwei();
}
else if ((n1 != 2) && !(n1 < 0) && (n1 % 2 != 0))
{
Odd (n1 );
}
else if ((n1 != 2) && !(n1 < 0) && ((n1 - 2) % 4 == 0))
{//singl Even
SingleEven(n1);
}
else if ((n1 != 2) && !(n1 < 0) && (n1 % 4 == 0))
{
DoubleEven (n1);
}
}
private static void Negativ(){
Console.WriteLine("Sorry, the number must be positive and greater than 3 ");
Console.ReadLine();
}
public static void Zwei(){
Console.WriteLine("Sorry,there is no magic square of 2x2 and the number must be and greater than 3 ");
Console.ReadLine();
}
public static void Odd ( int n)// odd method
{
int[,] magicSquareOdd = new int[n, n];
int i;
int j;
// Initialize position for 1
i = n / 2;
j = n - 1;
// One by one put all values in magic square
for (int num = 1; num <= n * n; )
{
if (i == -1 && j == n) //3rd condition
{
j = n - 2;
i = 0;
}
else
{
//1st condition helper if next number
// goes to out of square's right side
if (j == n)
j = 0;
//1st condition helper if next number is
// goes to out of square's upper side
if (i < 0)
i = n - 1;
}
//2nd condition
if (magicSquareOdd[i, j] != 0)
{
j -= 2;
i++;
continue;
}
else
{
//set number
magicSquareOdd[i, j] = num++;
//1st condition
j++; i--;
}
}
// print magic square
Console.WriteLine("The Magic Square for " + n + " is : ");
Console.ReadLine();
for ( i = 0; i < n; i++)
{
for ( j = 0; j < n; j++)
Console.Write(" " + magicSquareOdd[i, j] + " ");
Console.WriteLine();
Console.ReadLine();
}
Console.WriteLine(" The sum of each row or column is : " + n * (n * n + 1) / 2 + "");
Console.ReadLine();
}
public static void SingleEven(int n )
{
// int n = magic .Length ;
int[,] magicSquareSingleEven = new int[n, n];
int halfN = n / 2;
int k = (n - 2) / 4;
int temp;
int[] swapcol = new int[n];
int index = 0;
int[,] minimagic = new int[halfN, halfN];
*Odd(minimagic) ;* // here is the problem
for (int i = 0; i < halfN; i++)
for (int j = 0; j < halfN; j++)
{
magicSquareSingleEven[i, j] = minimagic[i, j];
magicSquareSingleEven[i+ halfN , j+halfN ] = minimagic[i, j]+ halfN *halfN ;
magicSquareSingleEven[i, j + halfN] = minimagic[i, j] +2* halfN * halfN;
magicSquareSingleEven[i + halfN, j] = minimagic[i, j] +3* halfN * halfN;
}
for (int i =1; i< k ;i ++)
swapcol [index ++]=i ;
for (int i = n-k+2; i <= n ; i++)
swapcol[index++] = i;
for (int i =1; i<=halfN ;i ++)
for (int j = 1; j<= index ; j ++)
{
temp = magicSquareSingleEven[i - 1, swapcol[j - 1] - 1];
magicSquareSingleEven[i-1,swapcol[j-1]-1]=magicSquareSingleEven[i +halfN-1,swapcol[j-1]-1];
magicSquareSingleEven[i+halfN-1,swapcol[j-1]-1]=temp;
}
//swaping noses
temp=magicSquareSingleEven[k,0];
magicSquareSingleEven[k,0]=magicSquareSingleEven[k+halfN,0];
magicSquareSingleEven[k+halfN,0]=temp;
temp=magicSquareSingleEven[k+halfN,k];
magicSquareSingleEven[k+halfN,k]=magicSquareSingleEven[k,k];
magicSquareSingleEven[k,k]=temp;}
//end of swaping
// print magic square
Console.WriteLine("The Magic Square for " + n + " is : ");
Console.ReadLine();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
Console.Write(" " + magicSquareSingleEven[i, j] + " ");
Console.WriteLine();
Console.ReadLine();
}
Console.WriteLine(" The sum of each row or column is : " + n * (n * n + 1) / 2 + "");
Console.ReadLine();
}

How to get all possible 2x2 sub matrices in a 3x3 matrix in C#?

If matrix A of size (3x3), then should i use the method of finding determinants, like grabbing the rows and column of first element and removing it from the array 2D array to get the remaining elements and then moving to the next element and repeating the same steps ?
[{1,2,3},
{4,5,6},
{7,8,9}]
I finally was able to do it, here's what I did :
enter image description here
class program
{
public static void Main()
{
int[,] arr = new int[3, 3];
Console.WriteLine("Enter elements of " + (arr.GetUpperBound(0) + 1) + "x" + (arr.GetUpperBound(1) + 1) + " matrix:");
for (int i = 0; i < (arr.GetUpperBound(0) + 1); i++)
{
for (int j = 0; j < (arr.GetUpperBound(1) + 1); j++)
{
arr[i, j] = Convert.ToInt32(Console.ReadLine());
}
}
Console.WriteLine("Matrix entered: ");
for (int i = 0; i < (arr.GetUpperBound(0) + 1); i++)
{
for (int j = 0; j < (arr.GetUpperBound(1) + 1); j++)
{
Console.Write("\t" + arr[i, j]);
}
Console.WriteLine();
}
Console.WriteLine("Possible sub-matrices: ");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j< 3; j++)
{
TrimArray(i,j,arr);
}
}
}
public static int[,] TrimArray(int row, int column, int[,] original)
{
int[,] resultant = new int[original.GetLength(0) - 1, original.GetLength(1) - 1];
for (int i = 0, j = 0; i < original.GetLength(0); i++)
{
if (i == row)
continue;
for (int k = 0, u = 0; k < original.GetLength(1); k++)
{
if (k == column)
continue;
resultant[j, u] = original[i, k];
u++;
}
j++;
}
Console.WriteLine();
for (int i = 0; i < 2; i++)
{
for (int j = 0; j< 2; j++)
{
Console.Write("\t"+resultant[i,j]);
}
Console.WriteLine();
}
return resultant;
}
}
I did this for you yesterday, I created a method that will return a square matrix, given a parent matrix and the length.
static void Main(string[] args)
{
int[][] parentMatrix = new int[][]
{
new int [] { 1, 2, 3 },
new int [] { 4, 5, 6 },
new int [] { 7, 8, 9 }
};
var chunks = GetSubMatrices(parentMatrix, 2);
Console.WriteLine(chunks);
}
static List<int[][]> GetSubMatrices(int[][] parentMatrix, int m)
{
int n = parentMatrix.Length > m ? parentMatrix.Length : throw new InvalidOperationException("You can't use a matrix smaller than the chunk size");
var chunks = new List<int[][]>();
int movLimit = n - m + 1;
var allCount = Math.Pow(movLimit, 2);
for (int selRow = 0; selRow < movLimit; selRow ++)
{
for (int selCol = 0; selCol < movLimit; selCol ++)
{
// this is start position of the chunk
var chunk = new int[m][];
for (int row = 0; row < m; row++)
{
chunk[row] = new int[m];
for (int col = 0; col < m; col++)
{
chunk[row][col] = parentMatrix[selRow + row][selCol + col];
}
}
chunks.Add(chunk);
}
}
return chunks;
}
If you have any problems using it, you can simply comment below.
I needed to solve a problem like and came up with this answer. Hope it adds to your library of answers. If the submatrix specified is not greater than 1, do nothing.
public static void GetSubMatrixes(int[,] arr, int size)
{
int parentMatrixRowLength = arr.GetLength(0);
int parentMatrixColLength = arr.GetLength(1);
var overall = new List<object>();
if(size > 1)
{
for (int i = 0; i < parentMatrixRowLength; i++)
{
//get the columns
for (int j = 0; j < parentMatrixColLength; j++)
{
var subMatrix = new int[size, size];
/*if the new matrix starts from second to the last value in either the row(horizontal or column)
* do not proceed, go to the row or column in the parent matrix
* */
if (j < parentMatrixColLength - (size - 1) && i < parentMatrixRowLength - (size - 1))
{
//add
for (int m = 0; m < subMatrix.GetLength(0); m++)
{
for (int n = 0; n < subMatrix.GetLength(1); n++)
{
/*check the sum of current column value and the sum of the current row value
* of the parent column length and row length if it goes out of bounds
*/
var row = i + m; var col = j + n;
//actual check here
if (row < parentMatrixRowLength && col < parentMatrixColLength)
{
subMatrix[m, n] = arr[i + m, j + n];
}
}
}
overall.Add(subMatrix);
}
}
}
//display the sub matrixes here
for (int i = 0; i < overall.Count; i++)
{
var matrix = overall[i] as int[,];
for (int y = 0; y < matrix.GetLength(0); y++)
{
for (int x = 0; x < matrix.GetLength(1); x++)
{
Console.Write(string.Format("{0} ", matrix[y, x]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
Console.WriteLine();
}
}
}

Count No Of 1's Colony From [1,0] 2D Array Using C#

I have a 2D array of integers which stores only values [1,0] as shown below.
int[,] INPUT = new int[10, 10] {
{1,1,0,0,0,1,1,1,0,0},
{1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,1,0,0,1,0,1},
{1,1,0,0,0,0,0,1,1,0},
{0,1,0,0,0,1,0,1,1,0},
{0,0,0,0,1,0,1,0,0,0},
{1,0,0,1,0,0,1,1,1,0},
{0,1,0,0,1,1,0,0,1,1},
{0,1,1,1,0,1,0,1,1,0},
{0,0,0,0,0,1,1,0,0,0},
};
I need to identify a Colony count for the input image, where a Colony is defined as a contiguous sequence of 1s (Like in this array, there are 3 colony of 1's). Connection between 1s can be either adjacent or on the diagonal.
I am required to use recursion for this.
class Program
{
public static int count;
public static int colony;
public static int[,] INPUT;
public static int rows = 10;
public static int cols = 10;
static void Main(string[] args)
{
int[,] INPUT = new int[10, 10] {
{1,1,0,0,0,1,1,1,0,0},
{1,0,0,0,1,0,0,0,1,0},
{0,0,0,1,1,0,0,1,0,1},
{1,1,0,0,0,0,0,1,1,0},
{0,1,0,0,0,1,0,1,1,0},
{0,0,0,0,1,0,1,0,0,0},
{1,0,0,1,0,0,1,1,1,0},
{0,1,0,0,1,1,0,0,1,1},
{0,1,1,1,0,1,0,1,1,0},
{0,0,0,0,0,1,1,0,0,0},
};
// Showing All Values From Upper 2D array
Console.WriteLine("Input File Contain: \n");
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
Console.Write(INPUT[i, j]);
}
Console.WriteLine();
}
// Getting Total 1's Count Only
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (INPUT[i, j] == 1)
{
count = count + 1;
}
}
Console.WriteLine();
}
// Getting Total 1's Colony Only
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (INPUT[i, j] == 1)
{
INPUT[i, j] = 0;
colony = GetColony(i, j);
}
}
}
Console.WriteLine("Counts Of 1 Are: " + count);
Console.WriteLine("Counts Of 1's Colony Are: " + colony );
}
static public int GetColony(int i, int j)
{
if ((i < rows) && (j < cols))
{
if ((INPUT[i - 1, j] == 1) || (INPUT[i + 1, j] == 1) || (INPUT[i, j - 1] == 1) || (INPUT[i, j + 1] == 1))
{
INPUT[i, j] = 0;
return GetColony(i, j);
}
else
{
return 1;
}
}
else
{
return 1;
}
}
}

Categories