how to write value of multi-dimensional array to a text file - c#

let say I have this array
[0,0] = A
[0,1] = B
[0,2] = C
[1,0] = D
[1,1] = E
[1,2] = F
[2,0] = G
[2,1] = H
[2,2] = I
[3,0] = J
[3,1] = K
[3,2] = L
I want them to be written on a text file like this:
A B C
D E F
G H I
J K L
what am I supposed to do?

static void Main(string[] args)
{
var array = new string[4, 3];
array[0, 0] = "A";
array[0, 1] = "B";
array[0, 2] = "C";
array[1, 0] = "D";
array[1, 1] = "E";
array[1, 2] = "F";
array[2, 0] = "G";
array[2, 1] = "H";
array[2, 2] = "I";
array[3, 0] = "J";
array[3, 1] = "K";
array[3, 2] = "L";
using (var sw = new StreamWriter("outputText.txt"))
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
sw.Write(array[i,j] + " ");
}
sw.Write("\n");
}
sw.Flush();
sw.Close();
}
}

Jagged arrays are often more convenient than 2D ones.
public static class ArrayExtensions {
// In order to convert any 2d array to jagged one
// let's use a generic implementation
public static T[][] ToJagged<T>(this T[,] value) {
if (Object.ReferenceEquals(null, value))
return null;
// Jagged array creation
T[][] result = new T[value.GetLength(0)][];
for (int i = 0; i < value.GetLength(0); ++i)
result[i] = new T[value.GetLength(1)];
// Jagged array filling
for (int i = 0; i < value.GetLength(0); ++i)
for (int j = 0; j < value.GetLength(1); ++j)
result[i][j] = value[i, j];
return result;
}
}
so in your case you can convert 2d array into jagged and then use Linq:
var array = new string[,] {
{"A", "B", "C"},
{"D", "E", "F"},
{"G", "H", "I"},
{"J", "K", "L"},
};
File.WriteAllLines(#"C:\MyFile.txt", array
.ToJagged()
.Select(line => String.Join(" ", line));

Assume two dimensions x and y.
and an array to be like [x,y]
initiate x and y to 0
increment y one by one [x,y++]
at the end of y(when all y's have been consumed for an X), print a
new line character
increment x by one
continue

Related

How to copy from an array to a Vector256 and vice versa based on the array index?

Supposedly I have either an int[] array or Vector256<int>s. How can I copy the values from one to another using an array index?
At the moment I have to iterate over the array indices and copy the values one by one:
int[] input = ...; // length divisible by Vector256<int>.Count
int[] output = new int[intput.Length];
for (int i = 0; i < input.Length; i += Vector256<int>.Count)
{
Vector256<int> v = Vector256.Create(
array[i], array[i + 1], array[i + 2], array[i + 3],
array[i + 4], array[i + 5], array[i + 6], array[i + 7]);
Vector256<int> v2 = DoSomeWork(v);
for (int j = 0; j < Vector256<int>.Count; ++j)
{
output[i + j] = v2.GetElement(i + j);
}
}
In Java SDK 16, there are functions that can do exactly what I need. Is there any similar function in C#?
int[] input = ...;
int[] output = new int[values.length];
for (int i = 0; i < input.length; i += IntVector.SPECIES_256.length()) {
IntVector v = IntVector.fromArray(IntVector.SPECIES_256, input, i);
IntVector v2 = DoSomeWork(v);
v2.intoArray(output, i);
}
You can use Vector from System.Numerics. Something like this:
var vector = new Vector<int>(new Span<int>(ints, i, 8));
Vector256<int> v = vector.AsVector256();
......
v2.AsVector().CopyTo(output, i);
Also you can try straightly use System.Numerics.Vector for your computations.
Also can use unsafe with Avx.LoadVector256 and Avx.Store from System.Runtime.Intrinsics.X86. Something like this:
fixed (int* ptr = input)
fixed (int* ptrRes = output)
{
var vectorCount = Vector256<int>.Count;
for (int i = 0; i <= input.Length - vectorCount; i += vectorCount)
{
var v = Avx.LoadVector256(ptr + i);
....
Avx.Store(ptrRes + i, v2);
}
}
Another solution.
int[] input = ...;
int[] output = new int[input.Length];
Span<Vector256<int>> inputVectors = MemoryMarshal.Cast<int, Vector256<int>>(input);
Span<Vector256<int>> outputVectors = MemoryMarshal.Cast<int, Vector256<int>>(output);
for (int i = 0; i < inputVectors.Length; i++)
outputVectors[i] = DoSomeWork(inputVectors[i]);
The result will be automagically in the output array.
Unsafe version
int[] input = ...;
int[] output = new int[input.Length];
fixed (int* inPtr = input, outPtr = output)
{
Vector256<int>* src = (Vector256<int>*)inPtr;
Vector256<int>* dst = (Vector256<int>*)outPtr;
Vector256<int>* srcEnd = src + (input.Length >> 3);
while (src < srcEnd)
{
*dst = DoSomeWork(*src);
src++;
dst++;
}
}
All 3 solutions: unsafe from the accepted answer, and both above ones have nearly the same performance.

Compare chars in two strings of different length in C#

In C#, Im trying to compare two strings and find out how many chars are different.
I Tried this:
static void Main(String[] args)
{
var strOne = "abcd";
var strTwo = "bcd";
var arrayOne = strOne.ToCharArray();
var arrayTwo = strTwo.ToCharArray();
var differentChars = arrayOne.Except(arrayTwo);
foreach (var character in differentChars)
Console.WriteLine(character); //Will print a
}
but there are problems with this:
if the strings contain same chars but on different positions within the string
it removes the duplicate occurences
If the strings would be the same length I would compare the chars one by one but if one is bigger than the other the positions are different
You may want to have a look at the Leventshtein Distance Algorithm.
As the article says
the Levenshtein distance between two words is the minimum number of
single-character edits (insertions, deletions or substitutions)
required to change one word into the other
You can find many reference implementations in the internet, like here or here.
public static int LevenshteinDistance(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int i = 0; i <= n; d[i, 0] = i++)
{
}
for (int j = 0; j <= m; d[0, j] = j++)
{
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
}
How about this? Append two strings into one and group them, you will have the count of the chars, > 1 will give the repeatings and = 0 will give the unique ones.
var strOne = "abcd";
var strTwo = "bcd";
var arrayOne = strOne.Concat(strTwo).GroupBy(x => x).Select(x => new { Key = x.Key, Count = x.Count() });
foreach (var character in arrayOne) {
if (character.Count > 1)
{
Console.WriteLine(character.Key); // the repeating chars
}
}
If the same character appears twice in the same string,
var strOne = "abbcdd";
var strTwo = "cd";
var arrayTwo = strOne.Select(x => new { Key = x, IsExists = strTwo.Any(y => y == x) });
foreach (var character in arrayTwo) {
if (character.IsExists)
{
Console.WriteLine(character.Key);
}
}

Make list of number from paired number in C#

I have a list of sublists with paired indexed number and its binary value. For example:
Variable Value
route.x[0,0] 0
route.x[0,1] 1
route.x[0,2] 0
route.x[0,3] 0
route.x[1,0] 0
route.x[1,1] 0
route.x[1,2] 0
route.x[1,3] 1
route.x[2,0] 0
route.x[2,1] 0
route.x[2,2] 0
route.x[2,3] 0
route.x[3,0] 0
route.x[3,1] 0
route.x[3,2] 1
route.x[3,3] 0
If the value of route.x[i,j] is 1, then make a new list which contains that number in sequence. For that example, the new list will be: route = 0 1 3 2
So far, i have made this code:
//find optimal route
var route = new List<List<int>>();
for (int j = 0; j < C+1; ++j)
{
if (routeopt.x[0, j] != 1)
continue;
List<int> subroute = new List<int>();
subroute.Add(0);
subroute.Add(j);
route.Add(subroute);
}
This code's result is route = 0 1. After that I use this code to add new number (3 and 2).
for (int i = 1; i < C+1; ++i)
{
for (int j = 1; j < C+1; j++)
{
if (routeopt.x[i, j] == 1)
{
List<int> targetlist = route.Single(r => r.Contains(i));
targetlist.Add(j);
}
}
}
This code is worked if only I have a route.x[i,j] with value 1 in ordered number. But if it is not ordered, for example (I only show variable with value 1):
Variable Value
route.x[0,4] 1
route.x[0,3] 1
route.x[4,1] 1
route.x[1,2] 1
It should be route = 0 3 and route = 0 4 1 2. But it showed Sequence contains no matching element because index 1 is not contained in route = 0 3 or route = 0 4. How to handled that problem? Thank you
Try below code. It returns list of all routes. The List of int has route in inverse order so while displaying/using you should take care of it.
const int C = 4;
static int[,] route_x = new int[5, 5];
static void Main(string[] args)
{
var allRoutes = FindRoutes();
System.Console.ReadLine();
}
private static List<List<int>> FindRoutes()
{
route_x[0, 0] = 0;
route_x[0, 1] = 1;
route_x[0, 2] = 0;
route_x[0, 3] = 0;
route_x[1, 0] = 0;
route_x[1, 1] = 0;
route_x[1, 2] = 0;
route_x[1, 3] = 1;
route_x[2, 0] = 0;
route_x[2, 1] = 0;
route_x[2, 2] = 0;
route_x[2, 3] = 0;
route_x[3, 0] = 0;
route_x[3, 1] = 0;
route_x[3, 2] = 1;
route_x[3, 3] = 0;
route_x[0, 4] = 1;
route_x[0, 3] = 1;
route_x[4, 1] = 1;
route_x[1, 2] = 1;
var routes = new List<List<int>>();
for (int i = 0; i < C + 1; i++)
{
if (route_x[0, i] == 1)
{
var subroutes = FindNextRoute(i);
foreach (var item in subroutes)
{
item.Add(0);
routes.Add(item);
}
}
}
return routes;
}
private static List<List<int>> FindNextRoute(int i)
{
var subroute = new List<List<int>>();
bool found = false;
for (int j = 0; j < C + 1; j++)
{
if (route_x[i, j] == 1)
{
found = true;
var tempRoutes = FindNextRoute(j);
foreach(var item in tempRoutes)
{
item.Add(i);
subroute.Add(item);
}
}
}
if (!found)
{
var singleitem = new List<int>();
singleitem.Add(i);
subroute.Add(singleitem);
}
return subroute;
}
I already found it by myself. After I got the first part, I use this code to add new number. Here is my code:
foreach (var subroute in route)
{
int r = 0;
while (r != subroute[subroute.Count - 1])
{
r = subroute[subroute.Count-1];
for (int j = 1; j < C + 1; j++)
{
if (routeopt.x[r, j] == 1)
subroute.Add(j);
}
}
}
The Single method expects there is exactly 1 return value. if not it will throw an exception.
Try SingleOrDefault. This will return null if there is no element found.
List<int> targetlist = route.SingleOrDefault(r => r.Contains(i));
if(targetList != null)
targetlist.Add(j);
Edit:
This will still crash if there are 2 lists that contain i.
To avoid this you could use FirstOrDefault

Operations on arrays

How can i shorten this code? If i am not mistaken things like temp=temp2 are not working in c# because they create shallow copy not deep one. this is not entire code ofc
public struct node {
public int[, ] state;
public int ordering;
public int parent;
}
if (temp.state[0, 1] == 0) {
node temp1, temp2, temp3;
temp1.state = new int[3, 3];
temp2.state = new int[3, 3];
temp3.state = new int[3, 3];
temp1.parent = temp.ordering;
temp2.parent = temp.ordering;
temp3.parent = temp.ordering;
temp1.ordering = temp.ordering + 1;
temp2.ordering = temp.ordering + 2;
temp3.ordering = temp.ordering + 3;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
temp1.state[i, j] = temp.state[i, j];
temp2.state[i, j] = temp.state[i, j];
temp3.state[i, j] = temp.state[i, j];
}
}
temp1.state[0, 1] = temp1.state[0, 0];
temp1.state[0, 0] = 0;
temp2.state[0, 1] = temp2.state[0, 2];
temp2.state[0, 2] = 0;
temp3.state[0, 1] = temp3.state[1, 1];
temp3.state[1, 1] = 0;
new_nodes.Add(temp1);
new_nodes.Add(temp2);
new_nodes.Add(temp3);
}
You can easily reduce the size of the first part of the code with something like that :
node temp1, temp2, temp3;
temp1 = CreateNode(temp, 1);
temp2 = CreateNode(temp, 2);
temp3 = CreateNode(temp, 3);
public node CreateNode(node oldNode, int increment)
{
node newNode;
/*Note the Clone() here instead of nested for loops.
Works because it is a matrix of value type, so we are
not working with references inside the matrix.
The two arrays now have different references.*/
newNode.state = (int[,])oldNode.state.Clone();
newNode.parent = oldNode.ordering;
newNode.ordering = oldNode.ordering + increment;
}

cannot convert type char to string

I'm doing data involving arrays in C#, when I use the foreach loop it gave me an message
cannot convert type char to string
int[,] tel = new int[4, 8];
tel[0, 0] = 398;
tel[0, 1] = 3333;
tel[0, 2] = 2883;
tel[0, 3] = 17698;
tel[1, 0] = 1762;
tel[1, 1] = 176925;
tel[1, 2] = 398722;
tel[2, 0] = 38870;
tel[3, 1] = 30439;
foreach (string t in tel.ToString())
{
Console.WriteLine(tel +" " +"is calling");
Console.ReadKey();
}
That is becuase when you foreach over a string each value will be a char, but you are trying to cast them to string.
foreach(string t in tel.ToString())
But it's unlikely that you want to foreach on tel.ToString() as the will return the name of the type of tel (System.Int32[,]). Instead you probably want to iterate all the values in tel
for(int i=0; i<4; i++)
{
for(int j=0; j<8; j++)
{
Console.WriteLine(tel[i,j] +" is calling");
Console.ReadKey();
}
}
Or
foreach(int t in tel)
{
Console.WriteLine(t +" is calling");
Console.ReadKey();
}
Note that some of the values will be zero since you do not assign values to all the positions in the tel array.
Iterate over the values in the array like this:
int rowLength = tel.GetLength(0);
int colLength = tel.GetLength(1);
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Console.WriteLine(tel[i, j]+" is calling");
}
}
Console.ReadLine();

Categories

Resources