So I have built my own (toy) encryption algorithm using matrices. The program is supposed to encrypt the plaintext with the key and then ask you the key and print out the decrypted plaintext. Everything is ok until the point when the C# program generates the 'key matrix' from the key to decrypt the cipher. Note that the first time that it generates the 'key matrix' from the key it is ok but the second time it freezes. Here is the code.
using System;
namespace MatrixEncryption
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine("Enter a relatively short piece of text:");
string txt = Console.ReadLine();
txt += "L";
Console.WriteLine("Enter an encryption key:");
string ekey = Console.ReadLine();
int times = 0;
while(true)
{
if(txt.Length + 1 < (Math.Pow((double)ekey.Length,(double)times))) break;
times++;
}
times++;
Console.WriteLine(times);
Matrix keym = new Matrix(ekey.Length^times, ekey.Length^times);
string res = ekey;
for(int i = 0; i<times - 1; i++)
{
res = GetCharRep(GenMatrix(res));
}
keym = GenMatrix(res);
Console.WriteLine(keym.cols + ":" + keym.rows);
Matrix passm = new Matrix(keym.rows, keym.cols);
int unicnt = 0;
Random a = new Random();
for(int i = 0; i<(keym.rows); i++)
{
for(int j = 0; j<(keym.cols); j++)
{
if(unicnt == 0)
{
passm[i, j] = (byte)txt.Length;
unicnt++;
continue;
}
if(unicnt < txt.Length)
{
passm[i, j] = (byte)txt[unicnt - 1];
}
else
{
int aa = a.Next();
passm[i, j] = (byte)(aa % byte.MaxValue);
}
unicnt++;
}
}
Matrix cipherm = new Matrix(keym.rows, keym.cols);
Matrix TwoMatrix = new Matrix(cipherm.rows, cipherm.cols);
for(int i = 0; i<TwoMatrix.rows; i++)
{
for(int j = 0; j<TwoMatrix.cols; j++)
{
TwoMatrix[i, j] = 2;
}
}
cipherm = NotMul(passm + TwoMatrix, keym + TwoMatrix);
Console.WriteLine("Enciphered text : " + GetCharRep(cipherm));
Console.WriteLine("Enter key now to check if decryptable cipher : ");
string keyy = Console.ReadLine();
int timesx = cipherm.cols;
double aaa = (double)timesx;
double bbb = (double)keyy.Length;
timesx = (int)Math.Log(aaa, bbb);
Matrix keymx = new Matrix(timesx, timesx);
string resss = keyy;
for(int i = 0; i<timesx; i++)
{
resss = GetCharRep(GenMatrix(resss));
}
keymx = GenMatrix(resss);
if(keymx != keym)
{
Console.WriteLine("STUPID COMPUTER xD");
Console.WriteLine(cipherm.cols.ToString() + ":" + cipherm.rows.ToString());
}
Matrix ress = new Matrix(keymx.rows, keymx.cols);
keymx = keymx + TwoMatrix;
ress = NotDiv(cipherm, keymx);
ress = ress - TwoMatrix;
Console.WriteLine(GetCharRep(ress).Substring(0, (int)(ress[0, 0])));
}
public static Matrix NotMul(Matrix m1, Matrix m2)
{
Matrix result = Matrix.ZeroMatrix(m1.cols, m1.rows);
for(int i = 0; i<m1.rows; i++)
{
for(int j = 0; j<m2.cols; j++)
{
result[i, j] = (m1[i, j] * m2[i, j]);
}
}
return result;
}
public static Matrix NotDiv(Matrix m1, Matrix m2)
{
Matrix result = Matrix.ZeroMatrix(m1.cols, m1.rows);
for(int i = 0; i<m1.rows; i++)
{
for(int j = 0; j<m2.cols; j++)
{
result[i, j] = m1[i, j] * (1/m2[i, j]);
}
}
return result;
}
public static Matrix GenMatrix(string key)
{
Matrix ret = new Matrix(key.Length, key.Length);
for(int i = 0; i<key.Length; i++)
{
for(int j = 0; j<key.Length; j++)
{
ret[i, j] = (byte)(Math.Pow((double)key[i], (double)key[j]) % byte.MaxValue);
}
}
return ret;
}
public static string GetCharRep(Matrix INM)
{
string ret = "";
for(int i = 0; i<INM.rows; i++)
{
for(int j = 0; j<INM.cols; j++)
{
ret += (char)((byte)INM[i, j] % byte.MaxValue);
}
}
return ret;
}
}
}
For a little bit of explanation:
1. The matrix class is burrowed from the internet and is too large to be put here.
2. Explaining the encryption algorithm:
Shortly all that happens is that the code generates two matrices, one from the plaintext and one from the key (you can guess how exactly it is generated by the code).
Then it multiplies each element of the key and the plaintext (NOT MATRIX MULITIPLICATION JUST EACH ELEMENT) the algorithm also involves random numbers e.t.c. But the problem I believe here is that the process of turning the key into the 'key matrix' is not repeated correctly the second time. Anyway I don't know a good solution so please help.
Ok, so I solved the first part, It isn't freezing any more I just changed the
for(int i = 0; i<times - 1; i++)
{
res = GetCharRep(GenMatrix(res));
}
to
for(int i = 0; i<times - 2; i++)
{
res = GetCharRep(GenMatrix(res));
}
But this time the dimensions of the ress matrix and the TwoMatrix Matrix don't match.
Related
Hello everyone I am new to programming in c#, what I am going to do is that I want to convert the 2D string array to 2D integer array, the reason for this conversion is that I want to pass that integer array to another method for some calculation. Thanks in advance for helping.
public void Matrix()
{
int a = int.Parse(txtRowA.Text);
int b = int.Parse(txtColA.Text);
Random rnd = new Random();
int[,] matrixA = new int[a, b];
string matrixString = "";
for (int i = 0; i < a; i++)
{
for (int j = 0; j < b; j++)
{
matrixA[i, j] = rnd.Next(1, 100);
matrixString += matrixA[i, j];
matrixString += " ";
}
matrixString += Environment.NewLine;
}
txtA.Text = matrixString;
txtA.TextAlign = HorizontalAlignment.Center;
}
Your code is actually pretty close. Try this:
private Random rnd = new Random();
public int[,] Matrix(int a, int b)
{
int[,] matrixA = new int[a, b];
for (int i = 0; i < a; i++)
{
for (int j = 0; j < b; j++)
{
matrixA[i, j] = rnd.Next(1, 100);
}
}
return matrixA;
}
What you have there is a function that does not rely on any WinForms controls and will produce your int[,] quickly and efficiently.
Let the calling code work with the WinForms controls:
int a = int.Parse(txtRowA.Text);
int b = int.Parse(txtColA.Text);
int[,] matrix = Matrix(a, b);
Now you can pass the matrix to anything that requires an int[,].
If you need to display the matrix then create a separate function for that:
public string MatrixToString(int[,] matrix)
{
StringBuilder sb = new();
for (int i = 0; i < matrix.GetLength(0); i++)
{
string line = "";
for (int j = 0; j < matrix.GetLength(1); j++)
{
line += $"{matrix[i, j]} ";
}
sb.AppendLine(line.Trim());
}
return sb.ToString();
}
Your calling code would look like this:
int a = int.Parse(txtRowA.Text);
int b = int.Parse(txtColA.Text);
int[,] matrix = Matrix(a, b);
UseTheMatrix(matrix);
txtA.Text = MatrixToString(matrix);
txtA.TextAlign = HorizontalAlignment.Center;
A sample run produces:
You can use List as a helper to store the elements of the array extracted from the string, but first I replaced the SPACE between elements in your string with a special character '|' as a separator to make it easier to extract the numbers from the string.
you can do somthing like this:
public static int[,] ConvertToInt(string matrix)
{
List<List<int>> initial = new List<List<int>>();
int lineNumber = 0;
int currenctIndex = 0;
int lastIndex = 0;
int digitCount = 0;
initial.Add(new List<int>());
foreach (char myChar in matrix.ToCharArray())
{
if (myChar == '|')
{
initial[lineNumber].Add(int.Parse(matrix.Substring(lastIndex, digitCount)));
lastIndex = currenctIndex+1;
digitCount = 0;
}
else
digitCount++;
if (myChar == '\n')
{
lineNumber++;
if(currenctIndex < matrix.Length-1)
initial.Add(new List<int>());
}
currenctIndex++;
}
int[,] myInt = new int[initial.Count, initial[0].Count];
for (int i = 0; i < initial.Count; i++)
for (int j = 0; j < initial[i].Count; j++)
myInt[i, j] = initial[i][j];
return myInt;
}
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.
You may think I am crazy, but I decided to write a neural network from scratch in C# for studying purposes. Please, be patient, I still have little experience)). English is not my first language, so I am sorry for it in advance.
I started with a program for handwritten digit recognizing with the MNIST database. I've read through a book about the algorithms inside the process and wrote this code.
public class NeuralNetwork
{
private List<Matrix<double>> weights = new List<Matrix<double>>();
private List<Vector<double>> biases = new List<Vector<double>>();
private Random random = new Random();
private List<Image> test_data;
private int[] layer_sizes;
public NeuralNetwork(params int[] layers)
{
layer_sizes = layers;
for (int i = 0; i < layers.Length - 1; i++)
{
var weigthLayer = Matrix<double>.Build.Dense(layers[i + 1], layers[i], (k, j) => random.NextDouble());
weights.Add(weigthLayer);
}
for (int i = 1; i < layers.Length; i++)
{
var biasesLayer = Vector<double>.Build.Dense(layers[i], (k) => random.NextDouble());
biases.Add(biasesLayer);
}
}
public Vector<double> FeedForward(Vector<double> a)
{
for (int i = 0; i < weights.Count; i++)
{
a = Sigmoid(weights[i].Multiply(a) + biases[i]);
}
return Sigmoid(a);
}
public void SGD(ITrainingDataProvider dataProvider, int epochs, int chuck_size, double eta)
{
test_data = new MnistReader().ReadTestData();
Console.WriteLine("SGD algorithm started");
var training_data = dataProvider.ReadTrainingData();
Console.WriteLine("Training data has beeen read");
Console.WriteLine($"Training data test: {Test(training_data)}%");
Console.WriteLine($"Test data test: {Test(test_data)}%");
for (int epoch = 0; epoch < epochs; epoch++)
{
training_data = training_data.OrderBy(item => random.Next()).ToList();
List<List<Image>> chunks = training_data.ChunkBy(chuck_size);
foreach (List<Image> chunk in chunks)
{
ProcessChunk(chunk, eta);
}
Console.WriteLine($"Epoch: {epoch + 1}/{epochs}");
Console.WriteLine($"Training data test: {Test(training_data)}%");
Console.WriteLine($"Test data test: {Test(test_data)}%");
}
Console.WriteLine("Done!");
}
private double Test(List<Image> data)
{
int count = 0;
foreach (Image im in data)
{
var output = FeedForward(im.DataToVector());
int number = output.MaximumIndex();
if (number == (int)im.Label)
{
count++;
}
}
return (double)count / data.Count * 100;
}
private void ProcessChunk(List<Image> chunk, double eta)
{
Delta[] deltas = new Delta[chunk.Count];
for (int i = 0; i < chunk.Count; i++)
{
Image image = chunk[i];
var input = image.DataToVector();
var desired_output = Vector<double>.Build.Dense(layer_sizes[layer_sizes.Length - 1]);
desired_output[(int)image.Label] = 1;
Delta delta = BackPropagation(input, desired_output);
deltas[i] = delta;
}
Delta sum = deltas[0];
for (int i = 1; i < deltas.Length; i++)
{
sum += deltas[i];
}
Delta average_delta = sum / deltas.Length;
for (int i = 0; i < layer_sizes.Length - 1; i++)
{
weights[i] += average_delta.d_weights[i].Multiply(eta);
biases[i] += average_delta.d_biases[i].Multiply(eta);
}
}
private Delta BackPropagation(Vector<double> input, Vector<double> desired_output)
{
List<Vector<double>> activations = new List<Vector<double>>();
List<Vector<double>> zs = new List<Vector<double>>();
Vector<double> a = input;
activations.Add(input);
for (int i = 0; i < layer_sizes.Length - 1; i++)
{
var z = weights[i].Multiply(a) + biases[i];
zs.Add(z);
a = Sigmoid(z);
activations.Add(a);
}
List<Vector<double>> errors = new List<Vector<double>>();
List<Matrix<double>> delta_weights = new List<Matrix<double>>();
List<Vector<double>> delta_biases = new List<Vector<double>>();
var error = CDerivative(activations[activations.Count - 1], desired_output).HProd(SigmoidDerivative(zs[^1]));
errors.Add(error);
int steps = 0;
for (int i = layer_sizes.Length - 2; i >= 1; i--)
{
var layer_error = weights[i].Transpose().Multiply(errors[steps]).HProd(SigmoidDerivative(zs[i - 1]));
errors.Add(layer_error);
steps++;
}
errors.Reverse();
for (int i = layer_sizes.Length - 1; i >= 1; i--)
{
var delta_layer_weights = (errors[i - 1].ToColumnMatrix() * activations[i - 1].ToRowMatrix()).Multiply(-1);
delta_weights.Add(delta_layer_weights);
var delta_layer_biases = errors[i - 1].Multiply(-1);
delta_biases.Add(delta_layer_biases);
}
delta_biases.Reverse();
delta_weights.Reverse();
return new Delta { d_weights = delta_weights, d_biases = delta_biases };
}
private Vector<double> CDerivative(Vector<double> x, Vector<double> y)
{
return x - y;
}
private Vector<double> Sigmoid(Vector<double> x)
{
for (int i = 0; i < x.Count; i++)
{
x[i] = 1.0 / (1.0 + Math.Exp(-x[i]));
}
return x;
}
private Vector<double> SigmoidDerivative(Vector<double> x)
{
for (int i = 0; i < x.Count; i++)
{
x[i] = Math.Exp(-x[i]) / Math.Pow(1.0 + Math.Exp(-x[i]), 2);
}
return x;
}
}
Delta class. A simple DTO to store weights and biases changes in a single object.
public class Delta
{
public List<Matrix<double>> d_weights { get; set; }
public List<Vector<double>> d_biases { get; set; }
public static Delta operator +(Delta d1, Delta d2)
{
Delta result = d1;
for (int i = 0; i < d2.d_weights.Count; i++)
{
result.d_weights[i] += d2.d_weights[i];
}
for (int i = 0; i < d2.d_biases.Count; i++)
{
result.d_biases[i] += d2.d_biases[i];
}
return result;
}
public static Delta operator /(Delta d1, double d)
{
Delta result = d1;
for (int i = 0; i < d1.d_weights.Count; i++)
{
result.d_weights[i] /= d;
}
for (int i = 0; i < d1.d_biases.Count; i++)
{
result.d_biases[i] /= d;
}
return result;
}
}
Everything ended up working fine, however complex networks with 1 or more hidden layers don't show any significant results. They are getting best 70% accuracy and then the learning curve drops. The accuracy returns to its 20-30%. Typically, the graph looks like a square root function, but in my case it is more like a turned around quadratic parabola the graph of my tries with different amounts of neurons in the first hidden layer
After a few tries, I found out, that without any hidden layers the algorithm works just fine. It learns up to 90% of accuracy and then the graph never falls down. Apparently, the bug is somewhere in back-propagation algorithm. It doesn't cause any problems with only input and output layers, but it does, when I add a hidden layer.
I have been trying to find the problem for a long time and I hope that someone, smarter than me, will be able to help.
Thanks in advance!
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();
}
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need help debugging and finishing a program that would: read a file with same number of lines and same number of integer values on each line (this will be a n x n matrix). The program should determines if the matrix is a magic square.
example of magic square: "ms.txt"
8,1,6;3,5,7;4,9,2
my code (working in progress), your help would be appreciated
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace MagicSquare
{
class Program
{
static void Main(string[] args)
{
int[,]S;
string line; //to hold one line of file
string[] token; //to hold each token in line
char[] separator = { ',' };
int N;
//open file
try
{
using (StreamReader sr = new StreamReader("..\\..\\ms.txt"))
{
line = sr.ReadLine();
token = line.Split(separator);
N = token.Count();
S = new int[N, N];
for (int i = 0; i < N; i++)
S[0, i] = Convert.ToInt32(token[i]);
for (int r = 1; r < N; r++)
{
line = sr.ReadLine();
token = line.Split(separator);
for (int c = 0; c < N; c++)
S[r, c] = Convert.ToInt32(token[c]);
}
sr.Close();
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
//find Magic Number
int magic = 0;
for (int i = 0; i < N; i++)
magic += S[i, i];
int sum = 0;
for (int i=0;i<N;i++)
sum += S[i,N -1-i];
if (magic!=sum)
{
Console.Write("Not Magic");
return;
}
//check each column
for (int c=0;c<N;c++)
{
int sum1 =0;
for (int r=0;r<N;r++)
sum1 += S[r,c];
if (sum1!=magic)
{
Console.WriteLine("Not magic");
return;
}
}
}
}
}
I edit your solution. This works for rows and columns.
static void Main(string[] args)
{
int[,] S = null;
int N = 0;
string line; //to hold one line of file
string[] token; //to hold each token in line
char[] separator = { ',' };
//open file
try
{
using (StreamReader sr = new StreamReader(#"C:\Users\sb9923\Desktop\ms.txt"))
{
line = sr.ReadLine();
token = line.Split(separator);
N = token.Count();
S = new int[N, N];
for (int i = 0; i < N; i++)
S[0, i] = Convert.ToInt32(token[i]);
for (int r = 1; r < N; r++)
{
line = sr.ReadLine();
token = line.Split(separator);
for (int c = 0; c < N; c++)
S[r, c] = Convert.ToInt32(token[c]);
}
sr.Close();
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
int magicValue = GetSum(N * N) / N;
//Check for magic
bool isMagic = true;
for (int counterY = 0; counterY < S.GetLength(1); counterY++)
{
int rowValue = 0;
int columnValue = 0;
for (int counterX = 0; counterX < S.GetLength(0); counterX++)
{
rowValue += Convert.ToInt32(S[counterY, counterX]);
columnValue += Convert.ToInt32(S[counterX, counterY]);
}
if (rowValue != magicValue)
{
isMagic = false;
break;
}
if (columnValue != magicValue)
{
isMagic = false;
break;
}
rowValue = 0;
columnValue = 0;
}
if (isMagic)
{
Console.WriteLine("Yeah it is magic! :)");
}
else
{
Console.WriteLine("No magic in the air!");
}
}
private static int GetSum(int maxValue)
{
if (maxValue < 1)
{
return 0;
}
return maxValue + GetSum(maxValue - 1);
}
If you have a question go for asking ;)
Just one simple variation about "how to check if square is magical?"(and unit test, for testing purpose):
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.IO;
namespace MSquareTest
{
[TestClass]
public class MSquareTest
{
/// <summary>
/// Checks if array of int's
/// is an magick square
/// </summary>
/// <param name="matrix">Input array</param>
/// <returns>True/False</returns>
public bool IsMagicSquare(int[] matrix)
{
if (matrix.Length % 3 != 0)
throw new ArgumentException("Invalid 2D cube!");
// 2x2(6 cells) is minimum
if (matrix.Length < 6)
throw new ArgumentException("Use at least 2x2 cube!");
// Cube face length
int length = matrix.Length / 3;
// calculate first row sum
int excepted = 0;
for (int y = 0; y < length; y++)
excepted += matrix[y];
// calculate and check second and another rows
for (int x = 1; x < length; x++)
{
int actual = 0;
for (int y = 0; y < length; y++)
actual += matrix[(length * x) + y];
if (actual != excepted)
return false;
}
// calculate and check columns
for (int x = 0; x < length; x++)
{
int actual = 0;
for (int y = 0; y < length; y++)
actual += matrix[(length * y) + x];
if (actual != excepted)
return false;
}
return true;
}
[TestMethod]
public void TestMS()
{
var GoodInput = "8,1,6;3,5,7;4,9,2"; // = File.ReadAllText("..\\..\\ms.txt");
var GoodArray = (from x in GoodInput.Split(',', ';') select int.Parse(x)).ToArray();
var BadInput = "6,4,1;3,0,3;1,5,9";
var BadArray = (from x in BadInput.Split(',', ';') select int.Parse(x)).ToArray();
// Good array is magick square, and bad array is not
var Result = IsMagicSquare(GoodArray) && !IsMagicSquare(BadArray);
Assert.IsTrue(Result);
}
}
}