Best way to convert int[][] to int**? - c#

This is kind of a curiosity question. I do have an existing solution, but I wonder if people know of a better approach.
My callers want to call me with int[][]. I have a routine that needs to process an int**. What's the best way to do this conversion? In other words:
public static void Func1(int[][] data) {
Func2(data); //how to do this?
}
private unsafe static void Func2(int** data) {
//process data
}
Following is the best approach I could come up with. It works fine, but I can't say I'm 100% happy with the recursive approach (and the O(data.Length) stack space it requires)
public static void Main() {
var test=new[] {
new [] {10},
new [] {20,30},
new [] {40,50,60},
new [] {70,80,90,100},
};
MySolution_Func1(test);
}
public unsafe static void MySolution_Func1(int[][] data) {
var items=new int*[data.Length];
Recurse(0, data, items);
}
public unsafe static void Recurse(int index, int[][] data, int*[] build) {
if(index==data.Length) {
fixed(int** finalp=build) {
Func2(finalp);
}
} else {
fixed(int* nextp=data[index]) {
build[index]=nextp;
Recurse(index+1, data, build);
}
}
}
private unsafe static void Func2(int** data) {
for(var j=0; j<4; ++j) {
for(var i=0; i<j+1; ++i) {
Debug.WriteLine("{0},{1}: {2}", j, i, data[j][i]);
}
}
}

There's no need to copy the whole array. You can create an array of pointers (i.e. IntPtr[]), and then cast that to int**. It's not pretty, and I wouldn't suggest doing it. But it can be done. The code below shows how.
int[][] myArray = new int[10][];
for (int i = 0; i < 10; ++i)
{
int[] x = new int[10];
for (int j = 0; j < 10; ++j)
{
x[j] = 10 * i + j;
}
myArray[i] = x;
}
// Output the array
Console.WriteLine("int[][]");
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", myArray[i][j]);
}
Console.WriteLine();
}
// Convert to int*[]
unsafe
{
GCHandle[] handles = new GCHandle[10];
IntPtr[] ArrayOfPointer = new IntPtr[10];
for (int i = 0; i < 10; ++i)
{
handles[i] = GCHandle.Alloc(myArray[i], GCHandleType.Pinned);
ArrayOfPointer[i] = handles[i].AddrOfPinnedObject();
}
// Okay, let's output that
Console.WriteLine("int*[]");
for (int i = 0; i < 10; ++i)
{
int* p = (int*)ArrayOfPointer[i];
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
}
// now convert to int**
GCHandle bigHandle = GCHandle.Alloc(ArrayOfPointer, GCHandleType.Pinned);
int** ppInt = (int**)bigHandle.AddrOfPinnedObject();
// and output it
Console.WriteLine("int**");
int** pa = ppInt;
for (int i = 0; i < 10; ++i)
{
int* p = *pa;
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
++pa;
}
// Need to free the handles
bigHandle.Free();
for (int i = 0; i < 10; ++i)
{
handles[i].Free();
}
}

public unsafe void ConvertToNative(int[][] jarray, out int** ptr)
{
ptr= (int**)Marshal.AllocHGlobal(jarray.Length*sizeof(int));
for (int i = 0; i < jarray.Length; i++)
{
*(ptr+i) = (int*)Marshal.AllocHGlobal(jarray[i].Length*sizeof(int));
for (int j = 0; j < jarray[i].Length; j++)
{
(*(i + ptr))[j] = jarray[i][j];
}
}
}
This works but uses unmanaged memory, and there is no recursion, is that valid ?

You can do it with O(1) stack space, if you are willing to copy all the data into another buffer:
public unsafe static void AlternateSolution_Func1(int[][] data) {
var buffer=new int[data.Sum(a => a.Length)];
fixed(int* pBuffer=buffer) {
var items=new int*[data.Length];
int count=0;
for(int i=0; i<data.Length; ++i) {
items[i]=pBuffer+count;
var array=data[i];
for(int j=0; j<array.Length; ++j) {
pBuffer[count++]=array[j];
}
}
fixed(int** pItems=items) {
Func2(pItems);
}
}
}

Related

How to replace duplicates in an array with 0

I have two arrays that have 20 randomly assigned elements and I need to create a method that replaces the duplicate numbers in an array with zeros but when I display the output nothing is changed.
This is the method for removing the repeating numbers. Is there a problem with the way the for loop is set up?
public static void RemoveDuplicates (int [] xArray){
for (int i = 0; i > xArray.Length-1; i++){
if (xArray[i] == xArray[i+1])
xArray[i] = 0;
}
}
and this is the whole thing
using System;
class MainClass {
public static void Main (string[] args) {
int [] student1 = new int [20];
int [] student2 = new int [20];
//int [] both = new int [40];
FillArray(student1);
FillArray(student2);
//Console.WriteLine("---------- Unsorted ----------");
//DisplayOutput(student1,student2);
Sort2Arrays(student1,student2);
//Console.WriteLine("---------- Sorted ----------");
//DisplayOutput(student1,student2);
RemoveDuplicates(student1);
RemoveDuplicates(student2);
DisplayOutput(student1, student2);
Sort2Arrays(student1,student2);
Console.WriteLine("---------- 1 and 2 no duplicates ----------");
DisplayOutput(student1, student2);
Console.WriteLine("done");
}//end main
public static void FillArray (int [] xArray){
Random rnd = new Random();
for(int i = 0; i< xArray.Length; i++){
xArray.SetValue (rnd.Next(80, 101),i);
}//end for
}//end FillArray
public static void Sort2Arrays (int [] xArray, int [] yArray){
Array.Sort(xArray);
Array.Sort(yArray);
}//end Sort2Arrays
public static void DisplayOutput (int [] xArray, int [] yArray){
for(int i = 0; i< 20; i++){
Console.WriteLine("{0}-{1}",xArray.GetValue(i),yArray.GetValue(i));
}//end for
}//end DisplayOutput
public static void RemoveDuplicates (int [] xArray){
for (int i = 0; i > xArray.Length-1; i++){
if (xArray[i] == xArray[i+1])
xArray[i] = 0;
}
}
}
Your for-loop condition is wrong, not >:
for (int i = 0; i > xArray.Length - 1; i++){
but <
for (int i = 0; i < xArray.Length - 1; i++)
with your version you will never enter the loop.
May i suggest you a different way to replace the duplicates(what you actually do), which is more efficient, more readable and more reusable:
public static void ReplaceDuplicates<T>(IList<T> xArray, T replaceWith)
{
HashSet<T> set = new HashSet<T>();
for (int i = 0; i < xArray.Count; i++)
{
if(!set.Add(xArray[i]))
{
xArray[i] = replaceWith;
}
}
}
It also doesn't need to sort the collection.
You use it in this way:
ReplaceDuplicates(student1, 0);
ReplaceDuplicates(student2, 0);
the > shouldve been <
public static void RemoveDuplicates (int [] xArray){
for (int i = 0; i < xArray.Length - 2; i++){
if (xArray[i] == xArray[i+1])
xArray[i] = 0;
}//end for
}//end RemoveDuplicates
public static void RemoveDuplicates(int[] array)
{
var foundValues = new HashSet<int>();
for (var index = 0; index < array.Length; index++)
{
var currentValue = array[index];
if (foundValues.Contains(currentValue))
{
array[index] = 0;
}
else
{
foundValues.Add(currentValue);
}
}
}

How can i calculate all lottery combinations instead of printing them?(C#)

Lottery 6/49 Problem:
The below code prints all possible combinations
How can i calculate all combinations instead of printing them?
static void Main()
{
for(int i1=1; i1<=44; i1++)
{
for(int i2=i1+1;i2<=45;i2++)
{
for(int i3=i2+1;i3<=46;i3++)
{
for(int i4=i3+1;i4<=47;i4++)
{
for(int i5=i4+1;i5<=48;i5++)
{
for(int i6=i5+1;i6<=49;i6++)
{
Console.WriteLine(i1+" "+i2+" "+i3+" "+i4 +" "+i5+" "+i6);
}
}
}
}
}
}
}
This is a basic combination problem. nCk where n is the number of options(49) and k is the number of options to pick(6).
The formula is n!/k!(n-k)!
for (int i = 1; i < n; i++)
{
nfac = nfac * i;
}
for (int j = 1; j < k; j++)
{
kfac = kfac * j;
}
for (int p = 1; p < (n-k); p++)
{
nkfac = nkfac * p;
}
Console.WriteLine(mfac/(kfac*nkfac));

Converting Codility solution to C# (Grocery-store, Hydrogenium 2013)

In order to learn and understand how Dijkstra's algorithm is used to solve the "Grocery Store" ([Hydrogenium 2013]: https://codility.com/programmers/challenges/hydrogenium2013) problem on codility, I'm trying to rewrite the #2, O(n^2) solution(https://codility.com/media/train/solution-grocery-store.pdf) in C#.
1) What language are those solutions written in?
2) What would be the C# equivalent to this bit of code?
G = [[]] *N
for i in xrange(M):
G[A[i]] = G[A[i]] + [(B[i], C[i])]
G[B[i]] = G[B[i]] + [(A[i], C[i])]
This is what I have so far
int[] G = new int[N];
for (int i = 0; i < M; i++)
{
G[A[i]] = G[A[i]];
G[B[i]] = G[B[i]];
}
Thanks in advance,
Gregory
Downloaded IDLE (a python IDE...kind of) and figured it out. It appears to be adding pairs to each array element. Here's the code I came up with if anyone else happens to stumble across the same problem.
private struct nodePair
{
public int node;
public int time;
public nodePair(int node, int time)
{
this.node = node;
this.time = time;
}
}
public int solution(int[] A, int[] B, int[] C, int[] D)
{
int M = A.Length;
int N = D.Length;
//build the graph
List<nodePair>[] G = new List<nodePair>[N];
for (int i = 0; i < N; i++)
{
G[i] = new List<nodePair>();
}
for (int i = 0; i < M; i++)
{
G[A[i]].Add(new nodePair(B[i], C[i]));
G[B[i]].Add(new nodePair(A[i], C[i]));
}
//initialize the distance table
int[] dist = new int[N];
for (int i = 0; i < N; i++)
{
dist[i] = int.MaxValue;
}
bool[] visited = new bool[N];
for (int i = 0; i < N; i++)
{
visited[i] = false;
}
//look for the minimum value
int ii = 0; ;
dist[0] = 0;
for (int k = 0; k < N; k++)
{
int s = int.MaxValue;
//find the minimum
for (int j = 0; j < N; j++)
{
if ((dist[j] < s) && (visited[j] == false))
{
s = dist[j];
ii = j;
}
}
visited[ii] = true;
if (s < D[ii])
{
return s;
}
List<nodePair> thisNodeLIst = G[ii];
foreach (nodePair oneNode in thisNodeLIst)
{
dist[oneNode.node] = Math.Min(dist[oneNode.node], s + oneNode.time);
}
}//for
return -1;
}
}

How to sort a 2D array filld with random numbers

I'm doing a class assignment,
I need to create an 2D array of random numbers and sort them either bubble or other sorting codes. I'm fine with single array, but the problem is a 2D array filled with random numbers, I just don't get it.
Random numbers should be made of (-I,I) interval it's a user input. Sorry for bad english, haven't gotten any degree. In working on visual C# windows form.
looking for simple couple cicles method.
example. : A[MxN] ->>> B[MxN] (Sorted 1.....n)
Getting the random numbers is trivial:
Random rnd;
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
array[y][x] = l - rnd.Next(2 * l + 1);
Random.Next() will return a random value between 0 and the given parameter (excluding the parameter; which is the reason for the + 1).
A 2D array can be sorted just like a 1D array, it only depends how you want to handle multiple lines, e.g. is it just for display or do you want to sort every line for itself, etc.
Here's a solution which first sorts each row's columns into order, then sorts each row comparing by first column, then second, etc:
namespace StackOverflow.Demos
{
class Program
{
public static void Main(string[] args)
{
new Program();
Console.WriteLine("Done");
Console.ReadKey();
}
Program()
{
double[,] data = GenerateData();
OutputData(data, "Before");
SortData(ref data);
OutputData(data, "After");
}
double[,] GenerateData()
{
Random randomGenerator = new Random(DateTime.UtcNow.Millisecond);
double[,] data = new double[5, 5];
for (int i = 0; i < data.GetLength(0); i++)
{
for (int j = 0; j < data.GetLength(1); j++)
{
data[i, j] = (randomGenerator.NextDouble() * 2) - 1;
}
}
return data;
}
void OutputData(double[,] data, string message)
{
Console.WriteLine("=====================");
Console.WriteLine(message);
Console.WriteLine("=====================");
for (int i = 0; i < data.GetLength(0); i++)
{
for (int j = 0; j < data.GetLength(1); j++)
{
Console.Write(data[i, j]);
Console.Write("\t");
}
Console.WriteLine();
}
}
void SortData(ref double[,] data)
{
//sort sub arrays
SortDataRows(ref data);
//sort this array
for (int i = 0; i < data.GetLength(0)-1; i++)
{
for (int j = i; j < data.GetLength(0); j++)
{
for (int k = 0; k < data.GetLength(1); k++)
{
if (data[i, k].CompareTo(data[j, k]) < 0) //if already in order exit loop
{
break;
} else if (data[i, k].CompareTo(data[j, k]) > 0) //if out of order switch and loop
{
SwapRows(ref data, i, j);
break;
}//else orders are equal so far; continue to loop
}
}
}
}
void SortDataRows(ref double[,] data)
{
for (int row = 0; row < data.GetLength(0); row++)
{
for (int i = 0; i < data.GetLength(1) - 1; i++)
{
for (int j = i; j < data.GetLength(1); j++)
{
if (data[row, i].CompareTo(data[row, j]) > 0)
{
Swap<double>(ref data[row, i], ref data[row, j]);
}
}
}
}
}
void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
void SwapRows(ref double[,]data, int i, int j)
{
for (int k = 0; k < data.GetLength(1); k++)
{
Swap<double>(ref data[i, k], ref data[j, k]);
}
}
}
}
The code's not the best (haven't had a cup of tea yet), but should do what you're after.
Here's a better solution (not using a 2D array as such, but using a structure which can easily be converted to/from such an array):
sing System.Diagnostics;
namespace StackOverflow.Demos
{
class Program
{
public static void Main(string[] args)
{
new Program();
Console.WriteLine("Done");
Console.ReadKey();
}
Program()
{
List<List<double>> data = GenerateData(5, 5).ToList<List<double>>();
OutputData(data,"Before");
foreach (List<double> item in data)
{
item.Sort();
}
data.Sort(CompareListOfDoubles);
OutputData(data,"After");
}
private IEnumerable<List<double>> GenerateData(int index1, int index2)
{
Random rnd = new Random(DateTime.UtcNow.Millisecond);
List<double> result;
for (int i = 0; i < index1; i++)
{
result = new List<double>(index2);
for (int j = 0; j < index2; j++)
{
result.Add(rnd.NextDouble() * 2 - 1);
}
yield return result;
}
}
private void OutputData(List<List<double>> data, string message)
{
Console.WriteLine(message);
foreach (List<double> list in data)
{
foreach (double datum in list)
{
Console.Write(datum);
Console.Write("\t");
}
Console.WriteLine();
}
}
static int CompareListOfDoubles(List<double> a, List<double> b)
{
for (int i = 0; i < a.Count; i++)
{
if (i > b.Count) return -1;
if (a[i] > b[i]) return -1;
if (a[i] < b[i]) return 1;
}
if (b.Count > a.Count) return 1;
return 0;
}
double[,] ConvertListListDoubleTo2DArray(List<List<double>> data)
{
double[,] result = new double[data.Count, data[0].Count];
for (int i = 0; i < result.GetLength(0); i++)
{
for (int j = 0; j < result.GetLength(1); j++)
{
result[i, j] = data[i][j];
}
}
return result;
}
}

Is it possible to specialize generics

I'm having a generic Converter class
public class Converter
{
public static TargetType[] Convert<SourceType, TargetType>(SourceType[] data)
where SourceType : struct
where TargetType : struct
{
int N = data.Length;
TargetType[] result = new TargetType[N];
for (int i = 0; i < N; i++)
{
// We does this not work, what can I do else
result[i] = (TargetType)data[i];
}
return result;
}
}
Question 1: Why is is not possible to do the cast? What can I do else? Convert.ChangeType is to slow.
Because of slow performance in general I decided to do it in unsafe code. Unfortunately it's not possible to create pointers to generics - as it is widely known. For that reason I created a converter that decides the type at runtime and performs the casts with a lot of if's.
No one question came up. Can I create a generic Convert routine and specialize it in a way, that in some cases I have defined datatypes. I currently don't know how, but maybe I you read the example you get a clue:
public static double[] Convert<double, int>(int[] data)
{
int N = data.Length;
double[] result = new double[N];
unsafe
{
fixed (int* data_pinned = data)
fixed (double* out_pinned = result)
{
int* A = data_pinned;
double* B = out_pinned;
for (int i = 0; i < N; i++, A++, B++)
{
*B = ((double)*A);
}
}
}
return result;
}
Below you can find a "small" demo project which shows the performance values of different casts:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication1
{
public static class CastTest
{
public static unsafe double[] Cast1(int[] input)
{
int N = input.Length;
double[] output = new double[N];
for (int i = 0; i < N; i++) output[i] = (double)(input[i]);
return output;
}
public static unsafe double[] Cast2(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++, inp++, outp++) *outp = (double)(*inp);
}
return output;
}
}
public static unsafe double[] Cast3(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++) outp[i] = (double)(inp[i]);
}
return output;
}
}
public static unsafe double[] Cast4(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
fixed (int* input_pinned = input)
{
for (int i = 0; i < N; i++) output_pinned[i] = (double)(input_pinned[i]);
}
}
return output;
}
public static unsafe double[] Cast5(int[] input)
{
double[] output = new double[input.Length];
for (int i = 0; i < input.Length; i++) output[i] = (input[i]);
return output;
}
public static unsafe double[] Cast6(int[] input)
{
Converter<int, double> converter = (A) =>
{
return A;
};
return Array.ConvertAll<int, double>(input, converter);
}
public static void StartTest()
{
int[] A = new int[100000];
int N = 10000;
var w1 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A1 = Cast1(A); }
w1.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 1, w1.ElapsedMilliseconds));
var w2 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A2 = Cast2(A); }
w2.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 2, w2.ElapsedMilliseconds ));
var w3 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A3 = Cast3(A); }
w3.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 3, w3.ElapsedMilliseconds));
var w4 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A4 = Cast4(A); }
w4.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 4, w4.ElapsedMilliseconds));
var w5 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A5 = Cast5(A); }
w5.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 5, w5.ElapsedMilliseconds));
var w6 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A6 = Cast6(A); }
w6.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 6, w6.ElapsedMilliseconds));
}
}
}
Any help is greatly appreciated to improve the performance.
The sizes for array size and repetitions are real values for me. In fact for testing purpose these values are also a little lower than normally used.
Is there a possibility to do this?
Thanks
Martin
It's not possible to do the cast because there's no guarantee that there is a conversion between the two types involved. What if SourceType is Guid and TargetType is double? The compiler basically can't emit a conversion.
The simplest approach is probably to provide a delegate:
public static TTarget[] Convert<TSource, TTarget>(TSource[] data,
Func<TSource, TTarget> conversion)
{
TargetType[] result = new TargetType[data.Length];
for (int i = 0; i < data.Length; i++)
{
result[i] = conversion(data[i]);
}
return result;
}
Of course this is basically the same as calling Array.ConvertAll... does that not do what you want?
Yes, there'll be a small performance overhead from calling the conversion frequently - but have you proved to yourself that that performance overhead is a problem? I would at least try using Array.ConvertAll as a first attempt.

Categories

Resources