Simple cycle and wrong element - c#

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.

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]);
}
}
}

How to perform combinatoric task in C#

i have a problem with an combinatoric task. I want to have a code which can handle this math calculation 48/5 = 1712304 (5! = 5*4*3*2*1 = 120 48*47*46*45*44 = 205476480 205476480/120 = 1712304)
Here some more details.
I have a string array with 48 strings. The strings have a length between 2 and 3 chars.
string array[] = new string[]{"A1","1D","410" /*[....]*/}
i want to combine 5 strings together, and i want to do this with the whole array, my biggest problem is that a combined string is just allowed to include each of the 48 strings just once. And each combined string have to be unique.
In the end i need a List with 1712304 string entries, which have to be between 10 and 15 degits long. For example one string could look like this "A11A4103E1T".
Back to the math, i know that there are 1712304 combined options so any other result must be wrong. That's where my problem appears.
I created the following code without succesful result
string[] siDigit = new string[iNumDigits];
List<string> liste = new List<string>();
const int iDigitBase = 48;
const int iNumDigits = 5;
for (int i = 0; i < 1712303; ++i)
{
int i2 = i;
for (int i3 = 0; i3 < iNumDigits; ++i3)
{
siDigit[i3] = array[i2 % iDigitBase];
i2 /= iDigitBase;
}
bool duplicate_free = siDigit.Distinct().Count() == siDigit.Length;
if (duplicate_free == true)
{
liste.Add(siDigit[0] + siDigit[1] + siDigit[2] + siDigit[3] + siDigit[4]);
Console.Write(siDigit[0] + siDigit[1] + siDigit[2] + siDigit[3] + siDigit[4]);
Console.WriteLine();
}
}
What i get is way to less entries in my list, i just get 1317051 entries and dont know why. I cant find any solution for my problem, may someone out there can help me out.
Any help would be greatly appreciated.
P.S In germany they dont teach better english :)
I think your algorithm is wrong.
Consider i equals 0, i2 equals 0, so siDigit[i3](i3 = 0, 1, 2, 3 ,4) are array[0], duplicate_free is false. You lose one. So, you can not get all entries.
Here is a recursive algorithm:
private static void GetCombination(ref List<string[]> list, string[] t, int n, int m, int[] b, int M)
{
for (int i = n; i >= m; i--)
{
b[m - 1] = i - 1;
if (m > 1)
{
GetCombination(ref list, t, i - 1, m - 1, b, M);
}
else
{
if (list == null)
{
list = new List<string[]>();
}
string[] temp = new string[M];
for (int j = 0; j < b.Length; j++)
{
temp[j] = t[b[j]];
}
list.Add(temp);
}
}
}
public static List<string[]> GetCombination(string[] t, int n)
{
if (t.Length < n)
{
return null;
}
int[] temp = new int[n];
List<string[]> list = new List<string[]>();
GetCombination(ref list, t, t.Length, n, temp, n);
return list;
}

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

String to Hex int array?

Is it possible to convert a HEX string to an integer array?
// This string...
string a = "8FCC44";
// Should look like this:
int[] b = {0x8f,0xcc,0x44};
But I don't have any idea how to do this.
I found this question, but i can't understand the answer. I am new to C#, so it would be nice if anybody could give me an example.
Thanks in advance!
int[] ConvertToIntArray(string a)
{
List<int> x = new List<int>();
for(int i=0; i<a.Length-1; i+=2)
x.Add(int.Parse(a.Substring(i, 2), System.Globalization.NumberStyles.HexNumber));
return x.ToArray();
}
You can then print them as Hex or Decimal using ToString() overloads of int (Int32) class.
Another way:
var a = "8fcc44";
var b = Enumerable.Range(0, a.Length / 2).Select(x =>
Convert.ToInt32(a.Substring(x * 2, 2), 16)).ToArray();
The answer focuses on Java, but it is also possible to do this in C# in a similar way. Basicly you have to divide the string into substrings, each 2 characters long:
"8FCC44" -> "8F", "CC", "44"
You can do this using a for loop:
for (int i = 0; i < a.Length; i += 2)
The loop variable i represents the start index of the current substring, this is why it always increases by 2. We can convert each substring using Int32.Parse:
Convert.ToInt32(a.Substring(i, 2), 16);
The last parameter represents the base of the source string (HEX = base 16).
Now we need an array to store the results. The size of the array can be calculated by the length of the string, divided by the length of each substring (= 2):
int[] b = new int[a.Length / 2];
To bring it all together your code could look like this:
string a = "8FCC44";
int[] b = new int[a.Length / 2];
for (int i = 0, int j = 0; i < a.Length; i += 2, j++)
b[j] = Convert.ToInt32(a.Substring(i, 2), 16);
Hope this helps!
static void Main(string[] args)
{
string a = "8fcc44";
int itemNumber = 0;
int[] iArray = new int[3];
for (int i = 0; i < a.Length - 1; i += 2)
{
iArray[itemNumber] = (int.Parse(a.Substring(i, 2), System.Globalization.NumberStyles.HexNumber));
itemNumber++;
}
}

Divide sequence elements into pairs

I have a sequence of 16 elements: 1,2,3,..., 16 ( or 2*n elements). Sequence elements always goes from 1 to length(sequence) that is sequence of 4 elements is 1,2,3,4.
Edit: first sequence element is always = 1, second sequence element = 2, third sequence element = 3 and so on. It's for a game "find a pair pictures".
I want to write an algorithm which divide elements into pairs. For Example,
1-15
2-16
3-13
4-9
5-14
6-10
7-11
8-12
PS: no linq please :) vs2005
Edit: As I can see, my question is so simple so no one can answer it :) Or everybody afraid something ?
Without a selection criteria, just take every other one.....
var result = new List<Tuple<int,int>>();
for (int i = 1; i < size; i+=2 )
{
var pair = new Tuple.Create(i,i+1);
result.Add(pair);
}
What about this?
class Program
{
static void Main(string[] args)
{
int size = 8;
List<int> tmpList = new List<int>();
for (int i = size; i <= size * 2; i++)
{
tmpList.Add(i);
}
List<Pair> result = new List<Pair>();
Random r = new Random();
for (int i = 1; i <= size; i++)
{
Pair pair = new Pair() { a = i, b = PopRandom(r, tmpList) };
result.Add(pair);
}
foreach (Pair p in result)
{
Console.WriteLine("{0} - {1}", p.a, p.b);
}
}
static private int PopRandom(Random r, List<int> list)
{
int i = r.Next(0, list.Count);
int result = list[i];
list.RemoveAt(i);
return result;
}
struct Pair
{
public int a;
public int b;
}
}
UPD: this was compiled successfully for .net 2.0 target platform
UPD 2: Random instance moved out from PopRandom()

Categories

Resources