Defining an array list in c# unity. - c#

I am trying to make an array list of integer values and run some basic math operations as seen below.
int dice1 = 4;
int dice2 = 3;
int dice3 = 6;
int dice4 = 4;
int dice 5 = 5;
ArrayList numbers = new ArrayList();
numbers[4] = dice5;
numbers[3] = dice4;
numbers[2] = dice3;
numbers[1] = dice2;
numbers[0] = dice1;
numbers[3] = numbers[3] * numbers[2];
However, the computer does not allow me to do this and produces an error "Operator "*" cannot be applied to operands of the type 'object' and 'object'". How do I fix this? I think that I have to define the array list as an array of integers... however I am not too sure. Please keep the answers simple as I am quite new to C# unity.
Thanks!

ArrayList stores everything as an 'object', basically the most basic type something can be in C#. You have a few options. If you want to keep using ArrayList, then you'll need to do cast the things you're multiplying, like:
numbers[3] = ((int)numbers[3]) * ((int)numbers[2])
Alternatively, you can ditch ArrayList and use the more modern List<> type. You need to add using System.Collections.Generic to the top, then your code will be like:
int dice1 = 4;
int dice2 = 3;
int dice3 = 6;
int dice4 = 4;
int dice5 = 5;
List<int> numbers = new List<int>(); //List contains ints only
numbers[4] = dice5;
numbers[3] = dice4;
numbers[2] = dice3;
numbers[1] = dice2;
numbers[0] = dice1;
numbers[3] = numbers[3] * numbers[2]; //Works as expected
Finally, if you know that your collection will only have a certain number of things, you can use an array instead. Your code will now be:
int dice1 = 4;
int dice2 = 3;
int dice3 = 6;
int dice4 = 4;
int dice5 = 5;
int[] numbers = new int[5]; //Creates an int array with 5 elements
//Meaning you can only access numbers[0] to numbers[4] inclusive
numbers[4] = dice5;
numbers[3] = dice4;
numbers[2] = dice3;
numbers[1] = dice2;
numbers[0] = dice1;
numbers[3] = numbers[3] * numbers[2]; //Works as expected

Avoid using array list
Use List<int> or int[]
Then the objects contained are typed instead of being object

You can do it in one line:
List<int> numbers = new List<int>{ 4, 3, 6, 4, 5 };

You need to parse the object to string then to int value then use it with * operator.But you firstly have to initialize the arraylist with null values then assign number values So that,
use following code that I made clear changes for you.
int dice1 = 4;
int dice2 = 3;
int dice3 = 6;
int dice4 = 4;
int dice5 = 5;
int capacity=5;
ArrayList numbers = new ArrayList(capacity);
for (int i = 0; i < capacity;i++ )
{
numbers.Add(null);
}
numbers[4] = dice5;
numbers[3] = dice4;
numbers[2] = dice3;
numbers[1] = dice2;
numbers[0] = dice1;
numbers[3] = (int.Parse(numbers[3].ToString()) * int.Parse(numbers[2].ToString()));
print(numbers[3]);

Related

Find all match positions in SIMD Avx.CompareEqual, or for a whole array while counting matches

I have a question if this is possible using SIMD instructions at all or if there could be some kind of Hybrid solution SIMD/Normal C# code solution to what I am trying to do or if it is not possible and will sacrifice to much speed of the SIMD instructions for it to be interesting.
My code counts how many 0,1,2,3 that exists in: inputArray (Micro Optimization of a 4-bucket histogram of a large array or list). Result is shown in: countArray
The correct answer to this is: 3,9,1,3.
My question now is this:
As seen we also have passed along: indexArray to the function. If we take 0 from inputArray as an example where we have 3 occurrences. We can see in the indexArray that those occurrences are at indexes: 9,43,5
I wonder if it is possible to add/collect this information in for example 4 buckets as well for each of the possible element values (0,1,2,3) in inputArray?
In the below code part we can see where the indexes for example: val = 1 is found: 0,9,10
I don't know if it is possible to catch those indexes somehow that could map/get the indexes from the indexArray?
The main goal to for example: ´0´ is to get an array in the end like this:
int[] indexes0 = new int[3]; //But we dont know that it will be 3 beforehand
indexes0[0] = 9;
indexes0[1] = 43;
indexes0[2] = 5;
[1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0]
// accumulate match counts into 4 vectors of 8-bit counters, one for each val
var v = Avx.LoadVector128(&fixedInput[0]);
for (byte val = 0; val < 4; val++)
{
//[1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0] -CompareEqual to: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
var match = Avx.CompareEqual(v, Vector128.Create(val));
counts[val] = Avx.Subtract(counts[val], match); // count -= 0 or -1
}
(Please note: I have a Piledriver CPU that can't run AVX2)
Complete Code (simplified for an array that's only one vector-width long):
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
private void button3_Click(object sender, EventArgs e)
{
//Create 16 indexes with numbers between: 0-3. The goal is to count how many of those occurences we have for the numbers: 0-3
byte[] v1 = new byte[16]; int[] v2 = new int[16];
v1[0] = 0; v2[0] = 9;
v1[1] = 1; v2[1] = 12;
v1[2] = 2; v2[2] = 55;
v1[3] = 3; v2[3] = 23;
v1[4] = 1; v2[4] = 568;
v1[5] = 1; v2[5] = 4;
v1[6] = 1; v2[6] = 6;
v1[7] = 1; v2[7] = 1008;
v1[8] = 1; v2[8] = 188800;
v1[9] = 0; v2[9] = 43;
v1[10] = 0; v2[10] = 5;
v1[11] = 3; v2[11] = 2;
v1[12] = 1; v2[12] = 1;
v1[13] = 1; v2[13] = 58;
v1[14] = 1; v2[14] = 8;
v1[15] = 3; v2[15] = 15;
/*---------------*/
ReadOnlySpan<byte> inputArray = v1;
ReadOnlySpan<int> indexArray = v2;
//Call function
countElements(inputArray, indexArray);
}
// simplified for inputArray.Count == 16 exactly, no looping or cleanup
// shows counts, doesn't find positions at all
private unsafe static void countElements(ReadOnlySpan<byte> inputArray, ReadOnlySpan<int> indexArray)
{
int[,] indexes0123 = new int[,] { }; //Store arrays for indexes found for the numbers: 0,1,2,3 in the "indexArray"
//Below starts the SIMD calculations!
int[] countArray = new int[4];
Span<Vector128<byte>> counts = stackalloc Vector128<byte>[4];
Span<Vector128<UInt64>> sum64 = stackalloc Vector128<UInt64>[4];
unsafe
{
fixed (byte* fixedInput = inputArray)
{
var v = Avx.LoadVector128(&fixedInput[0]);
for (byte val = 0; val < 4; val++)
{
//[1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0] -CompareEqual to: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
var match = Avx.CompareEqual(v, Vector128.Create(val));
counts[val] = Avx.Subtract(counts[val], match);
}
//Here SumAbsoluteDifferences
for (int i3 = 0; i3 < 4; i3++)
{
sum64[i3] = Sse2.Add(sum64[i3], Sse2.SumAbsoluteDifferences(counts[i3], Vector128<byte>.Zero).AsUInt64()); //sum64: <2,0,0,0,3,0,0,0>
}
//UnpackHigh and get the lower element from the Vector128<UInt64>
for (int i3 = 0; i3 < 4; i3++)
{
Vector128<UInt64> upper = Sse2.UnpackHigh(sum64[i3], sum64[i3]).AsUInt64(); //3
countArray[i3] += Sse2.Add(sum64[i3], upper).ToScalar();
}
//We now know how many 0,1,2,3 we have of each: (But we also need to collect which indexes from "indexlist" each of these 4 buckets has)
//3,9,1,3
MessageBox.Show(countArray[0] + "," + countArray[1] + "," + countArray[2] + "," + countArray[3]);
}
}
}

Simple cycle and wrong element

Here`s some code:
foreach (int[] temp in intList)
{
string str = GenerateGamma(0,1,10,temp);
if (str == "924890128")
answer.Add(temp);
}
Where in intList there are int arrays and each one of them has the following property: array[1] = 1(length of array is 10). Well, when I looked in answer, then I saw the array 1 4 6 0 9 3 2 7 5 8, so array[1] = 4.
Here is code of GenerateGamma().
public static string GenerateGamma(int i0, int j0, int m, int[] b)
{
Constants ct = new Constants();
int[] gamma = new int[9];
int[] inside_array = b;
string result = "";
int temp_i = i0, temp_j = j0, inttemp = 0;
for (int t = 1; t <= 9; t++)
{
temp_i = ((temp_i + 1) % m);
temp_j = ((temp_j + inside_array[temp_i]) % m);
inttemp = inside_array[temp_i];
inside_array[temp_i] = inside_array[temp_j];
inside_array[temp_j] = inttemp;
gamma[t-1] = (inside_array[(inside_array[temp_i]+inside_array[temp_j])%m]%m);
}
result = string.Join("",gamma);
return result;
}
Arrays are reference types, if you change passed array inside GenerateGamma() method the original array will be changed too.
Your array is changed because inside method you have:
int[] inside_array = b;
Here you don't create a copy of passed array, you just create copy of reference to array. So, you have one array and two references (b and inside_array) which point to the same array: b[0] = 1; and inside_array[0] = 1; do the same - they modify the same array.
If you want copy:
int[] inside_array = new int[b.Length];
for (int a = 0; a < inside_array.Length; a++)
{
inside_array[a] = b[a];
}
After this you will have two arrays and when you change one array another one won't be changed.

Creating random Numbers, store them in array and sort them in two listboxes c#

I am trying to generate random int numbers, once I Generate them I want to store them in a listBox, after this sort them in second listBox. The code that I have:
int Min = 0;
int Max = 6;
// this declares an integer array with 5 elements
// and initializes all of them to their default value
// which is zero
int[] test2 = new int[6];
Random randNum = new Random();
for (int i = 1; i < test2.Length; i++)
{
test2[i] = randNum.Next(Min, Max);
}
arrayListbox.ItemsSource = test2;
Array.Sort(test2);
foreach (int value in test2)
{
arrayListboxOrder.ItemsSource = test2;
}
The ItemsSource needs to be a different array - otherwise they both fundamentally have the same data. Sort one, sort them "both".
Try:
arrayListbox.ItemsSource = test2;
int[] sorted = (int[])test2.Clone();
Array.Sort(sorted);
arrayListboxOrder.ItemsSource = sorted;
int Min = 0;
int Max = 6;
// this declares an integer array with 5 elements
// and initializes all of them to their default value
// which is zero
//int[] test2 = new int[6];
arrayListboxOrder.ItemsSource = Enumerable.Range(Min, Max).OrderBy(x => Guid.NewGuid()).Take(5).OrderBy(n=>n).ToArray();
I saved a snippet here:
http://rextester.com/GBM61947

How to use 3D array's Sum function?

I have a 3d array double[][][] arr, which it's actually an array of double[][] matrix, I want to Sum all the matrices inside the array, I was going to write a Sum function, but I saw this function which I don't know how to use it in multidimensional array and I'm not sure if it's what I'm looking for.
double[][][] m;
m.Sum<double>();
The problem is that it can't be Sum<double> because double[][][] implements IEnumerable<double[][]>. So you can have two solutions here, using the Aggregate LINQ method:
1) Write a method double[][] AddMatrices(double[][] m1, double[][] m2) and then use:
var result = arr.Aggregate(AddMatrices);
2) Create a class Matrix (or just download one of many existing solutions), which has Add method, or overloaded operator+ and then similarly:
var result = arr.Aggregate(Matrix.Add);
The latter is of course advised, since it's explicit and thus more readable.
And to answer your question directly: no Sum doesn't have multidimensional equivalent out-of-box, as you can see looking at its overload list in the documentation.
double[][][] m = new double[2][][];
m[0] = new double[2][];
m[1] = new double[2][];
m[0][0] = new double[2];
m[0][1] = new double[2];
m[1][0] = new double[2];
m[1][1] = new double[2];
m[0][0][0] = 0;
m[0][0][1] = 1;
m[0][1][0] = 2;
m[0][1][1] = 3;
m[1][0][0] = 4;
m[1][0][1] = 5;
m[1][1][0] = 6;
m[1][1][1] = 7;
var summ = m.SelectMany(f => f.SelectMany(g => g)).Sum(); // summ = 28.0
double[, ,] n = new double[2, 2, 2];
n[0, 0, 0] = 0;
n[0, 0, 1] = 1;
n[0, 1, 0] = 2;
n[0, 1, 1] = 3;
n[1, 0, 0] = 4;
n[1, 0, 1] = 5;
n[1, 1, 0] = 6;
n[1, 1, 1] = 7;
var sumn = n.Cast<double>().Sum(); // sumn = 28.0

I am working with arrays and need to sort the array. This array keeps showing out of range exceptions

I have established an array and a large textbox which displays the array. Basically, you enter a name, 4 quarterly sales figures and it calculates the yearly total. I am now starting on the sort button. This would sort given columns numbers from most to least. I have gotten an if statement that looks like it should work for column five (the total column). I keep getting an out of range exception and am not sure why. Any ideas out there? I am sure this is a simple problem I am not seeing.
do {
swapFlag = false;
for (n=0; n < lastIndexUsed; n++)
{
if (quarters[n, sortCol] < quarters[n+1, sortCol])
{
//Column 5
temp = quarters[n,5];
quarters[n,5] = quarters[n +1, 3];
quarters[n +1, 3] = temp;
//swapflag
swapFlag = true;
}
}
} while (swapFlag);
This shows how I get 0-5 for sortCol:
if (rbRegion.Checked)
sortCol = 0;
if (rb1.Checked)
sortCol = 1;
if (rb2.Checked)
sortCol = 2;
if (rb3.Checked)
sortCol = 3;
if (rb4.Checked)
sortCol = 4;
if (rbTotal.Checked)
sortCol = 5;
Button Variables:
int n;
int temp;
int sortCol = 0;
string ntemp;
bool swapFlag;
Global Variables
int lastIndexUsed = -1;
int[,] quarters = new int[10, 5];
string[] Branch = new string[10];
quarters is defined as
int[,] quarters = new int[10, 5];
since arrays are zero based this gives you index 0...4 on the second dimension but you are trying to access index 5:
temp = quarters[n,5];
It seems to me, that you could have n = quaters.size - 1, and therefore n + 1 = quaters.size.
So it gets out of array's bound.
I smell the problem is with these:
quarters[n+1, sortCol]
quarters[n+1, 3]
Make sure n+1 is a valid index. What if lastIndexUsed itself is the maximum valid index? Then n+1 would cause IndexOutOfRangeException.
I'd suggest to use more instances of List<int> quartersSortCol0 and use if (rbRegion.Checked) quartersSortCol0.Sort() and avoid ineffective constructions like your "while-for" above. While you can use overload of Sort method with custom comparison.

Categories

Resources