C# naming array names on the fly - c#

I am trying to create a two dimensional array of random 1 and 0. These will be used to switch on or off I/O lines on an Arduino. The number of arrays (height) to create will come from a textbox on the UI as will the number of items (width) in each array.
This means I do not know how many arrays I will have so what I want to do is have a loop in which I name each array e.g. a0 then a1 then a2 etc.
I have tried to name them but as you can see below have not been able to get it right. What do I need to do?
private int[][] build_data(int height, int width)
{
Random randNum = new Random();
int Min = 0, Max = 2;
var array_name = "a";
rch_txtbx.AppendText(height.ToString() + "\r");
rch_txtbx.AppendText(width.ToString() + "\r");
for (int j = 0; j <= height; j++) //create a0 to ax
{
array_name = "a" + j; //this creates the name I want
int[] a = new int[width]; //need to initialise each array in turn but how?
for (int i = 0; i <= width; i++) //create number of items in each array
{
a[i] = randNum.Next(Min, Max);
}
}
/* This is what I am trying to create arayys of random 0 and 1
int[] a1 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] a2 = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
int[] a3 = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0 };
int[] a4 = { 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0 };
int[] a5 = { 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0 };
int[] a6 = { 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0 };
int[] a7 = { 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0 };
int[] a8 = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
int[] a9 = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0 };
int[] a10 = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0 };
int[] a11 = { 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0 };
int[] a12 = { 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0 };
int[] a13 = { 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0 };
int[] a14 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
*/
//get data ready to send back
int[][] arr = { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 };
return arr;
}

Instead of trying to dynamically create variables and then add them into the array just at the end of each outer loop iteration set the value of that array:
int[][] array = new int[height][];
for (int i = 0; i < height; i++)
{
int[] innerArray = new int[width];
for (int j = 0; j < width; j++)
innerArray[j] = r.Next(min, max);
array[i] = innerArray;
}
You can also replace the above for loops with Linq:
// Creates an enumerable with N
var array = Enumerable.Repeat(0, height) items
// For each item create an enumerable with M items
.Select(i => Enumerable.Repeat(0, width)
// Set the value of each inner item to a
// random number
.Select(j => r.Next(min,max))
// Convert to an array
.ToArray())
.ToArray();

You can use a multidimensional array:
int[,] random2dArray = new int[width, height];
for (int j = 0; j <= random2dArray.GetLength(0); j++)
{
for (int i = 0; i <= random2dArray.GetLength(1); i++)
{
random2dArray[j, i] = randNum.Next(Min, Max);
}
}
For more info you can look at MSDN.

According to the signature
private int[][] build_data(int height, int width)
you actually want to create an array of array int[][] (aka jagged array). You can do it quite direct:
// Simplest, but not thread-safe
private static Random s_Gen = new Random();
// static: there's no need in "this"
private static int[][] build_data(int height, int width) {
int[][] result = new int[height][];
for (int i = 0; i < result.Length; ++i) {
int[] line = new int[width];
for (int j = 0; j < line.Length; ++j)
line[j] = s_Gen.Next(2);
result[i] = line;
}
return result;
}
In case you want to have a collection of named arrays, I suggest using Dictionary<string, int[]> as a returned type:
private static Dictionary<string, int[]> build_named_data(int height, int width) {
Dictionary<string, int[]> result = new Dictionary<string, int[]>();
for (int i = 1; i <= height; ++i) {
int[] line = new int[width];
for (int j = 0; j < line.Length; ++j)
line[j] = s_Gen.Next(2);
result.Add($"a{i}", line);
}
return result;
}
....
var myData = build_named_data(15, 20);
int[] array = build_named_data["a3"];

Related

Integer array to int as map of set bits (one line shorthand)

I need a map of positive values.
And looking for one-line equivalent of following example:
int[] workplace = new int[]{1, 3, 5, 0, 7, 0, 9, 0, 3, 2, 0, 4};
int map = 0;
for (int i = 0; i < workplace.Length; i++)
map |= workplace[i] > 0 ? 1 << i : 0;
like:
int[] workplace = new int[]{1, 3, 5, 0, 7, 0, 9, 0, 3, 2, 0, 4};
int map = bla bla bla...;
Int32 map = workplace.Select( ( n, idx ) => ( n > 0 ) ? ( 1 << idx ) : 0 ).Aggregate( seed: 0, func: ( agg, n ) => agg | n );
Works for me:
I would suggest that you replace your current map calculation with a method call. By giving the method a descriptive name and clarifying your intention in the method body, I would argue that you are better off than by compressing logic inside a one-liner of code.
One possible approach is:
int[] workplace = new int[] { 1, 3, 5, 0, 7, 0, 9, 0, 3, 2, 0, 4 };
int map = GetPositiveFlagMapFor(workplace);
private static int GetPositiveFlagMapFor(int[] source)
{
int map = 0;
for (int i = 0; i < source.Length; i++)
{
if (source[i] > 0) // Easy to see that we only care about positive numbers
{
map |= 1 << i; // Easy to see what the calculation actually is
}
}
return map;
}
(Without knowing the actual purpose of the map calculation, the suggested method name is most likely not on point, but I trust that you get my intention.)

Save a matrix of zero and one as a sequence of bits

I have a binary matrix 8x8 represented as an one-dimensional array
byte[] m = { 0, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 0, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1 };
Is there a way how to save it in to binary file which would have total size of 8 bytes? Each 0 and 1 zero would be a 1 bit size.
You can use the following function to compress an array of 0s and 1s to an array of bytes:
IEnumerable<byte> Compress(byte[] a)
{
for (var i = 0; i < a.Length / 8f; i++)
{
var slice = a.Skip(i * 8).Take(8);
byte b = 0;
foreach (var s in slice)
{
b <<= 1;
if (s == 1)
b |= 1;
}
yield return b;
}
}
Then save to file using File.WriteAllBytes.
For example:
var result = Compress(m).ToArray();
File.WriteAllBytes(#"d:\test.bin", result);

Solve non square linear system with Math.net

I'm trying to solve a non square linear system with Math.net.
But I get an error Matrix dimensions must agree: 3x7.
Here is some example code:
using MathNet.Numerics.LinearAlgebra;
var mBuilder = Matrix<double>.Build;
var vBuilder = Vector<double>.Build;
var A = mBuilder.DenseOfArray(new double[,]
{
{ 3, 2, 1, 5, -1, 0, 0 },
{ 2, 1, 1, 2, 0, -1, 0 },
{ 5, 1, 3, 4, 0, 0, -1 }
});
var b = vBuilder.DenseOfArray(new double[] { -3, -5, -2 });
Vector<double> x;
x = A.Solve(b);
Cleary the system has a solution (e.g. X = {0, 0, 0, 0, 3, 5, 2}).
How can I solve such a system with Math.Net?
You can not use the Matrix.Solve function with a non-square matrix because there is no inverse and no unique solutions for a rectangular matrix. Google "inverse of rectangular matrix" for explanations galore. You can use pseudoinverse however, as shown below.
var mBuilder = Matrix<double>.Build;
var A = mBuilder.DenseOfArray(new double[,]
{
{ 3, 2, 1, 5, -1, 0, 0 },
{ 2, 1, 1, 2, 0, -1, 0 },
{ 5, 1, 3, 4, 0, 0, -1 }
});
Matrix<double> b = Matrix<double>.Build.Dense(3, 1);
b[0, 0] = -3.0;
b[1, 0] = -5.0;
b[2, 0] = -2.0;
var p = A.PseudoInverse();
var x = p * b;
// verify
var o = A * x;

Displaying mutiple instances of an image in a 2d array

This is what i have decided to start with a winForm & 1 button called btnCreate and I have 2 images 35px X 35px floor.bmp and wall.bmp
public partial class Form1 : Form
{
int x;
int y;
int[] Row0 = new int[10] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
int[] Row1 = new int[10] { 1, 1, 1, 1, 0, 0, 1, 1, 0, 1 };
int[] Row2 = new int[10] { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 };
int[] Row3 = new int[10] { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1 };
int[] Row4 = new int[10] { 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 };
int[] Row5 = new int[10] { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 };
int[] Row6 = new int[10] { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 };
int[] Row7 = new int[10] { 1, 1, 1, 1, 0, 0, 1, 1, 0, 1 };
int[] Row8 = new int[10] { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 };
int[] Row9 = new int[10] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
int[,] LevelA = new int[10,10];
private void Form1_Load(object sender, EventArgs e)
{
for (x = 0; x < 10; x++)
{
//load all arrays
LevelA[0, x] = Row0[x];
LevelA[1, x] = Row1[x];
LevelA[2, x] = Row2[x];
LevelA[3, x] = Row3[x];
LevelA[4, x] = Row4[x];
LevelA[5, x] = Row5[x];
LevelA[6, x] = Row6[x];
LevelA[7, x] = Row7[x];
LevelA[8, x] = Row8[x];
LevelA[9, x] = Row9[x];
}
}
private void btnCreate_Click(object sender, EventArgs e)
{
for (int X = 0; X < 10; X++)
{
for (int Y = 0; Y < 10; Y++)
{
//the following is the idea of what I would like to accomplish
//if (LevelA[Y,X] == 0)
//{
//Bitmap myBmp = new Bitmap(Image.FromFile(#"C:\My Documents\floor2.bmp"));
//myBmp.Top == Y * 35;
//myBmp.left == X * 35;
//}
}
}
}
}
Would the CODE above work as I intend it too >? or would the end of the for-loop only display the last tile as it would keep replacing(destroying) the previous one with a new one? In witch case I would need to have 100 myBmp's for a 10 by 10 grid?
You can get the bitmap of an image file by creating a Bitmap object.
Bitmap bmp = new Bitmap(Image.FromFile(#"D:\MyImageFile.bmp"));
You can place that or draw that anywhere as long as you get hold of a Graphics instance.
You can find asimple example here about that.

Collection was modified; enumeration operation may not execute." Collection elements are not modified

I have a nested loop "structure" in my code. Sometimes, I get the below message.
Collection was modified; enumeration operation may not execute.
I have a collection I am looping through, like below. Coll is a List<string>
foreach (string[] s1 in obj.Coll
{
foreach (string s in s1) { }
}
For each string in the array, I need to work with it (read as read the value, not write).
All I do with it is get directories (this value is a path) and split this string into an array.
How can this be resolved?
The obj.Coll is changed while you are enumerating it. If it is not changed by the current thread, it may be changed by some other thread. If the collection is changed by the current thread, there are basically two ways to solve the problem: You can create a copy of the collection and enumerate the copy or you can postpone the changes until you have enumerated the collection.
However, if the collection is changed by another thread, you should access the collection in a thread-safe manner (not just here but everywhere).
EDIT for Kieren Johnstone:
I wrote a short code to demonstrate that List<T>.ToArray() is not thread-safe.
var list = new List<int>();
Task.Factory.StartNew(() => {
for (int i = 0; i < 1000000; ++i) {
list.Clear();
// Add values from 1 to 9
for (int j = 1; j < 10; ++j) {
list.Add(j);
}
}
Console.WriteLine("Thread Exit: list.Add()");
});
Task.Factory.StartNew(() => {
for (int i = 0; i < 100; ++i) {
var array = list.ToArray();
if (array.Length > 0) {
Console.WriteLine("ToArray(): {0}", string.Join(", ", array));
}
}
Console.WriteLine("Thread Exit: list.ToArray()");
});
And below is a snippet of the output. I guess that it proves my claim. The snippet contains 15 lines and nine of them contain bad data.
ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 6, 7, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 0, 0, 0, 4, 5, 6, 7
ToArray(): 1, 2, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3
ToArray(): 1, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2
ToArray(): 1, 2, 3
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 6, 7, 8
There would be more variations if we had used list.Insert(0, j) instead of list.Add(j).
You can try:
foreach (string[] s1 in obj.Coll.ToArray())
{
That will take a copy before starting iteration!

Categories

Resources