Fastest Way To Create an Array of a NumberSequence - c#

I would like to create an array with of length X, and i would like the following 'inteligence'
if , for exemple, X = 6,
myArray[x] = [0,1,2,3,4,5]
For the moment, i do
int[] availableIndex = new int[DestructiblesCubes.Count];
for (var i = 0; i < availableIndex.Length; i++)
{
availableIndex[i] = i;
}
But, i'm curious, is there a better (the faster way to execute it) and/or the faster(the shortest char length) way?
Thanks :)

This is short way to implement this. Not the performance best solution.
Enumerable.Range(0, 10).ToArray()
MSDN description for Enumerable.Range

I think the fastest method uses the unsafe context together with a proper fixed pointer to the array, as demonstrated below:
/*const*/ int availableIndex_Length = 6;
int[] availableIndex = new int[availableIndex_Length];
unsafe {
fixed(int* p = &availableIndex[0]) {
for(int i = 0; i < availableIndex_Length; ++i) {
*(p+i) = i;
}
}
}
This can be refactored to a method, optionally inlined:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static unsafe void FillRange(ref int[] array) {
int length = array.Length;
fixed(int* p = &array[0]) {
for(int i = 0; i < length; ++i) {
*(p + i) = i;
}
}
}
static void Main(string[] args) {
// Example usage:
int[] availableIndices = new int[6];
FillRange(ref availableIndices);
// Test if it worked:
foreach(var availableIndex in availableIndices) {
Console.WriteLine(availableIndex);
}
Console.ReadKey(true);
}

You could try this:
unsafe
{
int[] availableIndex = new int[DestructiblesCubes.Count];
int length = availableIndex.Length;
int n = 0;
fixed(int *p = availableIndex) {
while(n < length) *p++ = n++;
}
}
may be faster, depending on the optimization stage of your compiler.

The only optimisation I can see to apply to your code as it stands is to count down to zero, but any increase in performance will be tiny
int[] availableIndex = new int[DestructiblesCubes.Count];
for (var i = availableIndex.Length-1; i >= 0; i--)
{
availableIndex[i] = i;
}
Otherwise, especially if you're talking large arrays, one thing to try would be to create an array greater than your max envisioned value of DestructiblesCubes.Count and
Intialize that array as above, then use Array.Copy when you want the smaller array.
I would be confident that no code we hand roll will be faster than a single call to Array.Copy.
int[] availableIndex = new int[DestructiblesCubes.Count];
Array.Copy(LargeArray, availableIndex, availableIndex.Length);
Otherwise I can't think of anything that might be faster than the code you have.

Related

C# performance - pointer to span in a hot loop

I'm looking for a faster alternative to BitConverter:
But! Inside a "hot loop":
//i_k_size = 8 bytes
while (fs.Read(ba_buf, 0, ba_buf.Length) > 0 && dcm_buf_read_ctr < i_buf_reads)
{
Span<byte> sp_data = ba_buf.AsSpan();
for (int i = 0; i < ba_buf.Length; i += i_k_size)
{
UInt64 k = BitConverter.ToUInt64(sp_data.Slice(i, i_k_size));
}
}
My efforts to integrate a pointer with conversion - made performance worse. Can a pointer be used to maki it faster with span?
Below is the benchmark: pointer 2 array is 2x faster
Actually I want this code to be used instead of BitConverter:
public static int l_1gb = 1073741824;
static unsafe void Main(string[] args)
{
Random rnd = new Random();
Stopwatch sw1 = new();
sw1.Start();
byte[] k = new byte[8];
fixed (byte* a2rr = &k[0])
{
for (int i = 0; i < 1000000000; i++)
{
rnd.NextBytes(k);
//UInt64 p1 = BitConverter.ToUInt64(k);
//time: 10203.824
//time: 10508.981
//time: 10246.784
//time: 10285.889
//UInt64* uint64ptr = (UInt64*)a2rr;
//x2 performance !
UInt64 p2 = *(UInt64*)a2rr;
//time: 4609.814
//time: 4588.157
//time: 4634.494
}
}
Console.WriteLine($"time: {Math.Round(sw1.Elapsed.TotalMilliseconds, 3)}");
}
Assuming ba_buf is a byte[], a very easy and efficient way to run your loop is as such:
foreach(var value in MemoryMarshal.Cast<byte, ulong>(ba_buf))
// work with value here
If you need to finesse the buffer (for example, to cut off parts of it), use AsSpan(start, count) on it first.
You can optimise this quite a lot by initialising some spans outside the reading loop and then read directly into a Span<byte> and access the data via a Span<ulong> like so:
int buf_bytes = sizeof(ulong) * 1024; // Or whatever buffer size you need.
var ba_buf = new byte[buf_bytes];
var span_buf = ba_buf.AsSpan();
var data_span = MemoryMarshal.Cast<byte, ulong>(span_buf);
while (true)
{
int count = fs.Read(span_buf) / sizeof(ulong);
if (count == 0)
break;
for (int i = 0; i < count; i++)
{
// Do something with data_span[i]
Console.WriteLine(data_span[i]); // Put your own processing here.
}
}
This avoids memory allocation as much as possible. It terminates the reading loop when it runs out of data, and if the number of bytes returned is not a multiple of sizeof(ulong) it ignores the extra bytes.
It will always read all the available data, but if you want to terminate it earlier you can add code to do so.
As an example, consider this code which writes 2,000 ulong values to a file and then reads them back in using the code above:
using (var output = File.OpenWrite("x"))
{
for (ulong i = 0; i < 2000; ++i)
{
output.Write(BitConverter.GetBytes(i));
}
}
using var fs = File.OpenRead("x");
int buf_bytes = sizeof(ulong) * 1024; // Or whatever buffer size you need.
var ba_buf = new byte[buf_bytes];
var span_buf = ba_buf.AsSpan();
var data_span = MemoryMarshal.Cast<byte, ulong>(span_buf);
while (true)
{
int count = fs.Read(span_buf) / sizeof(ulong);
if (count == 0)
break;
for (int i = 0; i < count; i++)
{
// Do something with data_span[i]
Console.WriteLine(data_span[i]); // Put your own processing here.
}
}

is there a better way to expand array size in c#

When I run this code the array has a new size after, is there anything wrong or bad about it ?
static int[] ExpandArray(int[] input, int add_size)
{
for (int i = 0; i < add_size; i++)
{
int[] temp = input;
input = new int[input.Length + 1];
for (var j = 0; j < temp.Length; j++)
{
input[j] = temp[j];
}
}
return input;
}
static void Main(string[] args)
{
int[] ovride = new int[3] { 1, 2, 3 };
ovride = ExpandArray(ovride, 10);
ovride = ExpandArray(ovride, 10);
Console.WriteLine(ovride.Length);
}
is there anything wrong or bad about it ?
This isn't code review, but:
Yes. You should not resize arrays. This involves a new allocation and a copy of all elements. As does Array.Resize(), by the way.
Hey, there is a method that already does this: Array.Resize(). Don't reinvent the wheel.
You definitely should not do the resize in a loop.
So to clean up the code a little:
static int[] ExpandArray(int[] input, int sizeToAdd)
{
// Create a new array with the desired size
var ouput = new int[input.Length + sizeToAdd];
// Copy all elements from input to output
for (int i = 0; i < input.Length; i++)
{
output[i] = input[i];
}
// Return the new array, having the remaining
// items set to their default (0 for int)
return output;
}
You'd actually want input to be updatable by ref, and then end with input = output.
Ultimately, just use a List<int>, as that allows for more efficient resizing, and does so automatically when necessary.
You can use Array.Resize which:
Changes the number of elements of a one-dimensional array to the specified new size.
int[] ovride = new int[3] { 1, 2, 3 };
Array.Resize(ref ovride, ovride.Length + 10);
Array.Resize(ref ovride, ovride.Length + 10);
Console.WriteLine(ovride.Length); // prints 23
But if you expect collection size changes List can be a more suitable option for your goal.

Loop nested loops

I would like to create a nested loop where the nesting depth determined by the size on an array. For example I have an array of integers and I would like to check all tuples where . Is there a way to do this simply in c# (or any other language)?
The only easy idea I had was to just multiply the numbers and do a for loop up to that number but unfortunately the product reaches the int limit. Also in this case I have no way to add extra conditions on each level.
Here's a small example and the product approach:
int[] a = new int[]{2, 3, 2}; //we have an array like this. In the description above it is a_1, a_2, a_3
void f(int[] i) //I have a function that works on an array input
{...}
bool check(int[] i) //I have a checker function, with an array parameter too
{...}
//And I would like to perform this function on all these arrays
//f({0, 0, 0})
//f({0, 0, 1})
//010
//011
//020
//021
//100
//101
//110
//111
//120
//f({1, 2, 1})
//But if let's say check({1, 0}) is false then don't perform the f function on {1, 0, 0} and {1, 0, 1}
//A simple implementation if we know the size of the array a is the following
for(int i1=0;i1<a[0];i1++)
{
if(!check({i1}))
continue;
for(int i2=0;i2<a[1];i2++)
{
if(!check({i1, i2}))
continue;
for(int i3=0;i3<a[2];i3++)
{
if(!check({i1, i2, i3}))
continue;
f({i1, i2, i3});
}
}
}
//But this obviously fails as we have no idea apriori of the size of the array a
//An alternative I have is the following:
int prod = 1;
foreach(int x in a)
{
prod *= x;
}
for(int c=0;c<prod;c++)
{
int d=c;
int[] i = new int[a.Length];
for(int l=0;l<a.Length;l++)
{
i[l]=d%(a[l]);
d /= a[l];
}
f(i);
}
//But the problem with this implementation is that in my case prod is larger than the int limit. Also this loops through all the incorrect cases too, where the check function can highly reduce the number of cases to calculate.
I've managed to solve the problem. The idea is that increasing the i value by one is really easy and we can check the condition that we don't overstep the a values and don't violate the check function easily. Below is a code that works
int[] a = ...;
void f(int[] i){...}
bool check(int[] i){...}
int n = a.Length;
int[] i = new int[n];
while (true) //keep increasing the coordinates of i, while we can
{
for (int l = 0; l < n; l++)
{
int[] il = copyFirst(i, l);
while(!check(il)) //check for all first few coordinates if it is correct, skip if incorrect.
//There is a way to improve this even further, as we don't have to check the first few
// coords if it was correct before, so should only care about the recently changed section
{
i = increase(a, i, l);
if (i == null)
{
return;
}
else
{
il = copyFirst(i, l);
}
}
}
f(i);
i = increase(a, i, n-1);
if (i == null) return;
}
int[] copyFirst(int[] i, int l) //this is just a small helper function to copy the first few elements of i, to use in the check
{
int[] ret = new int[l];
for (int k = 0; k < l; k++)
{
ret[k] = i[k];
}
return ret;
}
int[] increase(int[] a, int[] i, int l) //this results in the increased vector and in null if we've reached the end
{
for (int k = l; k >= 0; k--)
{
i[k] = i[k] + 1;
if (i[k] >= a[k])
{
i[k] = 0;
}
else
{
return i;
}
}
return null;
}

Shifting A single element in an array

I want to shift one element in an array to the right each time whilst leaving the original elements in their specific order in C#.
Ok so I've been asked to reword the code I can understand why so here we go:
I might have a number 48390
//the ar elements have been commented out to show that we never know what ar contains but only the that I will always want to shift; ar[4]
int[] ar = new int[5];
//ar[0] = 4
//ar[1] = 8
//ar[2] = 3
//ar[3] = 9
//ar[4] = 0
while(ar != 04839)
{
Shift code
}
I might input 5 numbers 48390 if you notice its the same number but one digit is out. I want a while loop to rotate that 4 ar[1] to shift until the number forms 04839
I hope this makes sense. I am posting this question because most pages posting information about shifting based on shifting all elements to the right and I only really want to shift one specific element.
Thanks for looking.
edit: I should have been more specific. What if you don't know what each of the array elements could be? So I couldn't depend on "0" as an anchor. as another set of numbers might include another number for example "00238."
This method will give you a sequence of arrays made by inserting a single element into (between) each position in a given array:
public static IEnumerable<T[]> InsertElementBetweenAllPositions<T>(
T[] array, T element)
{
int newLength = array.Length + 1;
for (int i = 0; i < newLength; i++)
{
T[] rtn = new T[newLength];
rtn[i] = element;
Array.Copy(array, 0, rtn, 0, i);
Array.Copy(array, i, rtn, i + 1, array.Length - i);
yield return rtn;
}
}
For your example, you might call it as
foreach (int[] arr in InsertElementBetweenAllPositions(new[] { 6, 7, 8, 9 }, 0))
{
foreach (int i in arr)
Console.Write(i + " ");
Console.WriteLine();
}
How about this:
List<int> l = new List<int>(){0,6,7,8,9};
for (int i=1;i<5;i++)
{
l.Remove(0);
l.Insert(i, 0);
}
What's in your example is a swap, which can be implemented like:
private void Swap(ref int[] array, int index1, int index2)
{
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
Calling Swap(ref source, 0, 1) would exchange the first and second element. What you want then is:
for (int i = 0; i < a.Length-1; i++)
{
Swap(ref a, i, i+1);
}
This "bubbles" the first element up to the last position in each iteration.
From the example you need to shift elements around, and the example is a bit confusing over whether you need to loop them around to the start again. I have provided the below example that will loop around to the start - If you do not need to do that, the you can rework the if the statement.
private int[] Shift(int[] a)
{
int zeroPos = Array.IndexOf(a, 0);
int[] rtn = new int[a.Length];
a.CopyTo(rtn, 0);
if (zeroPos + 1 == a.Length)
{
rtn[0] = 0;
for (int i = 0; i < a.Length - 1; i++)
{
rtn[i + 1] = a[i];
}
}
else
{
rtn[zeroPos] = rtn[zeroPos + 1];
rtn[zeroPos + 1] = 0;
}
return rtn;
}
r=ar[0];
for (int i = 0; ar.lenght;i++)
{
ar[i]=ar[i + 1];
}
ar[ar.lenght] = r;
Have you thought about using a LinkedList instead? A linked list data structure is probably more suited to what you are trying to do than an array. The AddFirst, AddLast, AddAfter and AddBefore methods allow you to insert elements into the list in a much more efficient way than re-organizing your array each time.
The disadvantage of linked lists is that you need to read the elements in order. So, it's very efficient for inserting/deleting elements but inefficient for accessing elements randomly.
There is a good overview of LinkedLists here.
Perhaps
int oldLast = ar[ar.Length - 1];
for (int i = ar.Length - 1; i >= 0; i--)
ar[i] = i == 0 ? oldLast : ar[i - 1];
Demo
It is just a permutation of an item , below is the full source code of permutation algorithm.
static List<string> Put(char s1, string list)
{
List<string> str =new List<string>();
for (int i = 0; i < list.Length+1; i++)
{
string s = list.Substring(0, i) + s1.ToString() + list.Substring(i);
str.Add(s);
}
return str;
}
static List<string> Permute(string list,int x)
{
List<string> Result = new List<string>();
if (list.Length == 1)
{
Result.Add(list[0].ToString());
return Result;
}
else
{
char first = list[0];
list = list.Substring(x+1);
List<string> part = Permute(list,0);
foreach (string str in part)
{
List<string> hasBeenPlaced = Put(first, str);
foreach (string str2 in hasBeenPlaced)
{
Result.Add(str2);
}
}
}
return Result;
}
static void Main(string[] args)
{
List<string> per = Permute("abc",0);
for (int i = 0; i < per.Count; i++)
{
Console.WriteLine(per[i]);
}
Console.ReadKey();
}
Now if I add a break after the foreach , your problem has been solved . (it will writes all permuation for just an item which you want , not all of them....)
So change that to :
foreach (string str in part)
{
List<string> hasBeenPlaced = Put(first, str);
foreach (string str2 in hasBeenPlaced)
{
Result.Add(str2);
}
break;
}
Hope to helps you
If you you linq, that's simple :-) But you need a size larger than the array.
ShiftLeft(ar, 1);
private static int[] ShiftLeft(int[] value, int countOfShift = 1)
{
var length = value.Length;
if (countOfShift > length)
{
throw new InvalidOperationException("countOfShift must less then value's length.");
}
var tempList = new List<int>(value);
tempList.RemoveRange(length - countOfShift, countOfShift);
tempList.InsertRange(0, value.Skip(length - countOfShift));
return tempList.ToArray();
}

Redim Preserve in C#?

I was shocked to find out today that C# does not support dynamic sized arrays. How then does a VB.NET developer used to using ReDim Preserve deal with this in C#?
At the beginning of the function I am not sure of the upper bound of the array. This depends on the rows returned from the database.
VB.NET doesn't have the idea of dynamically sized arrays, either - the CLR doesn't support it.
The equivalent of "Redim Preserve" is Array.Resize<T> - but you must be aware that if there are other references to the original array, they won't be changed at all. For example:
using System;
class Foo
{
static void Main()
{
string[] x = new string[10];
string[] y = x;
Array.Resize(ref x, 20);
Console.WriteLine(x.Length); // Prints out 20
Console.WriteLine(y.Length); // Still prints out 10
}
}
Proof that this is the equivalent of Redim Preserve:
Imports System
Class Foo
Shared Sub Main()
Dim x(9) as String
Dim y as String() = x
Redim Preserve x(19)
Console.WriteLine(x.Length)
Console.WriteLine(y.Length)
End Sub
End Class
The two programs are equivalent.
If you truly want a dynamically sized collection, you should use List<T> (or something similar). There are various issues with using arrays directly - see Eric Lippert's blog post for details. That's not to say you should always avoid them, by any means - but you need to know what you're dealing with.
Use ArrayLists or Generics instead
Use a List<T>. It will dynamically size as needed.
You really shouldn't be using ReDim, it can be very expensive. I prefer List(Of T), but there are many options in this area.
That said, you had a question and here is your answer.
x = (int[]) Utils.CopyArray((Array) x, new int[10]);
I couldn't help but notice that none of the above answers approach the concept of multidimensional arrays. That being said, here's an example. The array in question is predefined as x.
int[,] temp = new int[newRows, newCols];
int minRows = Math.Min(newRows, x.GetUpperBound(0) + 1);
int minCols = Math.Min(newCols, x.GetUpperBound(1) + 1);
for (int i = 0; i < minRows ; ++i)
for (int j = 0; j < minCols; ++j)
temp[i, j] = x[i, j];
x = temp;
Just for fun, here's one way to use generics in order to redim/extend a unidimensional array (add one more "row") :
static T[] Redim<T>(T[] arr, bool preserved)
{
int arrLength = arr.Length;
T[] arrRedimed = new T[arrLength + 1];
if (preserved)
{
for (int i = 0; i < arrLength; i++)
{
arrRedimed[i] = arr[i];
}
}
return arrRedimed;
}
And one to add n rows (though this doesn't prevent user from undersizing the array, which will throw an error in the for loop) :
static T[] Redim<T>(T[] arr, bool preserved, int nbRows)
{
T[] arrRedimed = new T[nbRows];
if (preserved)
{
for (int i = 0; i < arr.Length; i++)
{
arrRedimed[i] = arr[i];
}
}
return arrRedimed;
}
I'm sure you get the idea.
For a multidimensional array (two dimensions), here's one possibility:
static T[,] Redim<T>(T[,] arr, bool preserved)
{
int Ubound0 = arr.GetUpperBound(0);
int Ubound1 = arr.GetUpperBound(1);
T[,] arrRedimed = new T[Ubound0 + 1, Ubound1];
if (preserved)
{
for (int j = 0; j < Ubound1; j++)
{
for (int i = 0; i < Ubound0; i++)
{
arrRedimed[i, j] = arr[i, j];
}
}
}
return arrRedimed;
}
In your program, use this with or even without the type specified, the compiler will recognize it :
int[] myArr = new int[10];
myArr = Redim<int>(myArr, true);
or
int[] myArr = new int[10];
myArr = Redim(myArr, true);
Not sure if all this is really relevant though. =D
Please feel free to correct me or improve my code. ;)
Even though it's a long time ago it might help someone looking for a simple solution - I found something great in another forum:
//from Applied Microsoft.NET framework Programming - Jeffrey Richter
public static Array RedimPreserve(Array origArray, Int32 desiredSize)
{
System.Type t = origArray.GetType().GetElementType();
Array newArray = Array.CreateInstance(t, desiredSize);
Array.Copy(origArray, 0, newArray, 0, Math.Min(origArray.Length, desiredSize));
return newArray;
}
Source: https://social.msdn.microsoft.com/Forums/en-US/6759816b-d525-4752-a3c8-9eb5f4a5b194/redim-in-c?forum=csharplanguage

Categories