Efficient conversion of an array into a two-dimensional one using LINQ - c#

I want to do the below in a performant way in C#, preferably using LINQ.
Array[Length] to Array[Length/Row][Row] where Row and Length are variables.

You can use Buffer.BlockCopy to efficiently convert between n-dimensional arrays of blittable types:
int[] a = new int[] { 1, 2, 3, 4, 5, 6 };
int rows = 2;
int columns = a.Length / rows;
int[,] b = new int[columns, rows];
Buffer.BlockCopy(a, 0, b, 0, sizeof(int) * a.Length);
// b[0, 0] == 1
// b[0, 1] == 2
// b[1, 0] == 3
// b[1, 1] == 4
// b[2, 0] == 5
// b[2, 1] == 6
This takes advantage of the fact that multi-dimensional (not jagged!) arrays are laid out continuously in memory by the CLR.
For non-blittable types, simply use some good ol' for loops.

That's not a two dimensional array, that's a jagged array. I assume that you mean Array[Length/Row,Row].
There isn't anything in LINQ that does exactly that, so you will have a bit of overhead if you want to use it. The most performant way is straight forward code:
public T[,] MakeRows<T>(T[] values, int rowSize) {
T[,] result = new T[values.Length / rowSize, rowSize];
int row = 0, col = 0;
foreach (T value in values) {
resul[row, col] = value;
if (++col == rowsize) {
col = 0;
row++;
}
}
return result;
}
Note: The method assumes that the items are evenly divisable into rows.

Related

Get all split options to k chunks

I need to split an array arr into k chunks where the union of all the chucks is arr and there in no same element in two chunks.
For example for
int[] arr = new int[] {1, 2, 3, 4, 5};
int k = 3;
I need to return all the possible splits:
[[1], [2], [3,4,5]]
[[1], [2,3], [4,5]]
[[1], [2,3,4], [5]]
[[1,2], [3], [4,5]]
[[1,2], [3,4], [5]]
[[1,2,3], [4], [5]]
How can I do that efficiently in C#?
You have a combinatoric problem: given an array of n item you should sample k subarrays or, put it differently, k - 1 splits from n - 1:
[A, B, C, D, E] n items, n - 1 possible splits
^ ^
| | k - 1 splits from n - 1 avaialable
| |
[A] [B, C] [D, E] k chunks
Note that we have standard combinatoric problem
k - 1 from n - 1 unordered without repetitions
Code for such sampling can be
private static IEnumerable<int[]> Samples(int take, int from) {
if (take > from || take <= 0 || from <= 0)
yield break;
int[] array = Enumerable.Range(0, take).ToArray();
for (bool agenda = true; agenda; ) {
agenda = false;
yield return array.ToArray();
for (int i = array.Length - 1; i >= 0; --i)
if (array[i] < from - take + i) {
agenda = true;
array[i] += 1;
for (int j = i + 1; j < array.Length; ++j)
array[j] = array[i] + j - i;
break;
}
}
}
Having this sampling routine, we can implement splitting into chunks:
private static IEnumerable<T[][]> MyChunks<T>(T[] array, int take) {
if (take > array.Length)
yield break;
foreach (var sample in Samples(take - 1, array.Length - 1)) {
T[][] result = new T[take][];
for (int i = 0, from = 0, to; i <= sample.Length; ++i, from = to) {
to = i < sample.Length ? sample[i] + 1 : array.Length;
result[i] = array
.Skip(from)
.Take(to - from)
.ToArray();
}
yield return result;
}
}
Demo:
var arr = new int[] { 1, 2, 3, 4, 5};
int k = 3;
string report = string.Join(Environment.NewLine, MyChunks(arr, k)
.Select(chunk => "[" + string.Join(", ", chunk
.Select(item => $"[{string.Join(",", item)}]")) + "]"));
Console.Write(report);
Output:
[[1], [2], [3,4,5]]
[[1], [2,3], [4,5]]
[[1], [2,3,4], [5]]
[[1,2], [3], [4,5]]
[[1,2], [3,4], [5]]
[[1,2,3], [4], [5]]
On way to solve such a problem is to divide and conquer. We could first solve how we compute the possible splits of an array if we only ever wanted to split into two sub arrays (k = 2).
I.e. our function, when given 1,2,3,4, should return 1|2,3,4, 1,2|3,4, and 1,2,3|4 where | marks the border between the left and right subarrays.
Note how the | starts at the left-most position (that still produces a non-empty split on the left) and gradually moves to the right, until no more non-empty split can be produced for the right.
A C# function that does this is shown below:
IEnumerable<(Memory<int>, Memory<int>)> PossibleSplits(
Memory<int> xs) {
for (var i = 1; i < xs.Length; i++)
yield return (xs[..i], xs[i..]);
}
var splits = PossibleSplits(new[] { 1, 2, 3, 4, 5 }.AsMemory());
As you can see it returns a sequence of left/right tuples.
I'm using Memory so no new arrays are allocated when splitting the input data.
One nice property of this function is that it returns an empty sequence when the input array's length is smaller than 2.
So how do we split to an abritrary number of splits, not only 2? One trick is to recursively split the left side of a split again until the left side becomes to small to be split.
To that end we have to modify the above function in several ways:
The return value must change from a sequence of Memory tuples to a sequence of Memory sequences.
i cannot always start at position 1. When splitting into an arbitrary number k of splits, our function must make sure that the left side always holds enough elements for it to be split again into at least k - 1 subarrays. Therefor i must start at k - 1.
Obviously the function needs to call itself to become recursive. And it must do so with one of the two subarrays (we choose left) and the predecssor of k. Decrementing k accounts for the other subarray that won't be split up any further, but will be returned as part of the result of course.
We must add an exit condition to break the recursive cycle. When k is below 2 then we cannot meaningfully split the array (regardless of its size) and just return the input array wrapped as a singleton sequence.
Below is a recursive version of the function above that does just that:
public static class Ext {
public static IEnumerable<IEnumerable<Memory<int>>> PossibleSplits(
this Memory<int> xs,
int k) {
if (k < 2) {
yield return Enumerable.Repeat(xs, 1);
yield break;
}
for (var i = k - 1; i < xs.Length; i++) {
var (left, right) = (xs[..i], xs[i..]);
foreach (var split in left.PossibleSplits(k - 1))
yield return split.Append(right);
}
}
}
var splits = new[] { 1, 2, 3, 4, 5 }
.AsMemory()
.PossibleSplits(k: 3);
It's an extension method, just because I like them.
You asked for an efficient solution, but efficiency is relative. This solution is efficient in terms of...
...memory because now new arrays are allocated (hush, we don't talk about all the enumerators created by this code);
...laziness, because only requested values will be computed;
...code size.
It's not the most efficient in terms of runtime speed, because of all the overhead enumerators introduce.

Performant Concatenating 2D Arrays stored as sub-arrays [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Imagine we got a couple of 3x3 2D arrays that are identified by a X Y coordinate.
Pseudo code:
Array 0-0 Array 1-0
[[1,2,1] [[1,2,1]
[2,3,2] [2,3,2]
[3,1,2]] [3,1,2]]
Array 0-1 Array 1-1
[[1,2,1] [[1,2,1]
[2,3,2] [2,3,2]
[3,1,2]] [3,1,2]]
And we also have an index array, to index all this sub-arrays.
chunk_array = [
[Array 0-0, Array 0-1],
[Array 1-0, Array 1,1]
]
The problem is how to quickly create a final array, 6x6 containing all sub-arrays without having to iterate all elements of the array as this is a very critical place that has to operate in the minimal time possible.
So question: What would be the quickest way to perform this operation ? I've looked at Buffer copy, but not sure still what would be the best approach here.
Here's a solution based on the suggestion of Alexei Levenkov in the comments. From his comment: Fastest way to do something is not to do it at all... Does that work in your case (i.e. by wrapping all 4 into a class that exposes indexing the way you like)?
You create your four individual arrays and then add them to a wrapper capable of holding those arrays in a rectangular array. I use a function to access the individual elements, but you could use an indexer instead (if you are inclined that way - I'm not, that accessor seems a bit too complex for a simple indexer).
Here's the main class:
public class CompositeArray<T> where T:new()
{
private readonly T[,][,] _componentArray = null;
public int IndividualArrayWidth { get; }
public int IndividualArrayHeight { get; }
public int ComponentArrayWidth { get; }
public int ComponentArrayHeight { get; }
public int OverallArrayWidth => IndividualArrayWidth * ComponentArrayWidth;
public int OverallArrayHeight => IndividualArrayHeight * ComponentArrayHeight;
public CompositeArray(int individualArrayWidth, int individualArrayHeight, int componentArrayWidth,
int componentArrayHeight)
{
IndividualArrayWidth = individualArrayWidth;
IndividualArrayHeight = individualArrayHeight;
ComponentArrayWidth = componentArrayWidth;
ComponentArrayHeight = componentArrayHeight;
_componentArray = new T[ComponentArrayWidth, ComponentArrayHeight][,];
}
public void SetIndividualArray(int x, int y, T[,] array)
{
if (x < 0 || x >= IndividualArrayWidth)
{
throw new ArgumentOutOfRangeException(nameof(x), x, $#"Must be between 0 and {IndividualArrayWidth - 1}");
}
if (y < 0 || y >= IndividualArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(y), y, $#"Must be between 0 and {IndividualArrayHeight - 1}");
}
if (array.GetLength(0) != IndividualArrayWidth || array.GetLength(1) != IndividualArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(array), $#"Must be between an array that is {IndividualArrayWidth} by {IndividualArrayHeight}");
}
_componentArray[x, y] = array;
}
public T GetOverallElement(int x, int y)
{
if (x < 0 || x >= OverallArrayWidth)
{
throw new ArgumentOutOfRangeException(nameof(x), x, $#"Must be between 0 and {OverallArrayWidth - 1}");
}
if (y < 0 || y >= OverallArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(y), y, $#"Must be between 0 and {OverallArrayHeight - 1}");
}
int whichArrayX = x / IndividualArrayWidth;
int innerX = x % IndividualArrayWidth;
int whichArrayY = y / IndividualArrayHeight;
int innerY = y % IndividualArrayHeight;
return (_componentArray[whichArrayX, whichArrayY][innerX, innerY]);
}
}
Note that I create a rectangularly jagged rectangular array. It took a bit to figure out the syntax.
Note that there is no copying at all. You only pay for two integer divisions and two integer modulus operations per element access. If you only use 2x2 arrays, you could reduce that to two bit-shifts and two bit-tests (since division by two is a simple bit-shift, and checking for even/odd is simply a test of the least significant bit).
Here's some code that exercises that class:
int[,] array00 = new int[,]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int[,] array01 = new int[,]
{
{11, 12, 13},
{14, 15, 16},
{17, 18, 19}
};
int[,] array10 = new int[,]
{
{21, 22, 23},
{24, 25, 26},
{27, 28, 29}
};
int[,] array11 = new int[,]
{
{31, 32, 33},
{34, 35, 36},
{37, 38, 39}
};
CompositeArray<int> bigArray = new CompositeArray<int>(array00.GetLength(0), array00.GetLength(1), 2,2);
bigArray.SetIndividualArray(0, 0, array00);
bigArray.SetIndividualArray(0, 1, array01);
bigArray.SetIndividualArray(1, 0, array10);
bigArray.SetIndividualArray(1, 1, array11);
var shouldBe2 = bigArray.GetOverallElement(0, 1);
var shouldBe6 = bigArray.GetOverallElement(1, 2);
var shouldBe28 = bigArray.GetOverallElement(5, 1);
var shouldBe16 = bigArray.GetOverallElement(1, 5);
var shouldBe32 = bigArray.GetOverallElement(3, 4);
I think the best you can do is copy chunks of 3 values as they are all the source values that are contiguous in the destination array:
var ans = new int[6,6];
for (int row = 0; row < 2; ++row) {
for (int col = 0; col < 2; ++col) {
var srcArray = chunk_array[row, col];
for (int subRow = 0; subRow < 3; ++subRow) {
Array.Copy(srcArray, subRow*3, ans, subRow*6+row*18+col*3, 3);
}
}
}
Some performance testing doesn't show much optimization of this code possible.

Finding smallest number using tournament bracket

I'm writing a program that has to find the smallest number through the tournament bracket. For example there is an array
int[] a = new int[4] {4, 2, 1, 3}
and by comparing numbers standing next to each other I've to choose the smallest one. (min(4, 2) -> 2, min(1, 3) -> 1, and then I'm comparing 1 and 2, 1 is the smallest so it's the winner, but it's not possible to compare 2 and 1. Just a[0] with a1, a[2] with a[3] and so. In general a[2*i] with a[(2*i)+1] for(int i=0; i<a.Length/2; i++) <- something like this
First question: If there are n numbers, the whole tree consists of 2n-1 brackets. Am I supposed to create an array of 4 or 7 elements? 4 seems like a better option.
Second question: if I'm comparing 4 and 2, and 2 is smaller should I make a[0] = 2, and then while comparing 1 and 3 a1 = 1? Finally comparing a[0] with a1 and putting the smallest number to a[0]? Temporary int might be needed.
Last question: what do you propose to do it in the simplest way? I could hardly find any info about this algorithm. I hope you will direct my mind into working algorithm.
Not much, but I'm posting my code:
int[] a = new int[4] { 4, 2, 1, 3 };
int tmp = 0;
for (int i = 0; i < (a.Length)/2; i++)
{
if (a[tmp] > a[tmp + 1])
{
a[i] = a[i + 1];
}
else if(a[tmp] < a[tmp +1])
{
a[i] = a[i + 1];
}
tmp = tmp + 2;
}
Can you point what I'm doing ok, and what should be improved?
If tournament style is a must, a recursive approach seems the most appropriate:
int Minimum (int [] values, int start, int end)
{
if (start == end)
return values [start];
if (end - start == 1)
if ( values [start] < values [end])
return values [start];
else
return values [end];
else
{
int middle = start + (end - start) / 2;
int min1 = Minimum (values, start, middle);
int min2 = Minimum (values, middle + 1, end);
if (min1 < min2)
return min1;
else
return min2;
}
}
EDIT: Code is untested and errors might have slipped in, since it's been typed on the Android app.
EDIT: Forgot to say how you call this method. Like so:
int min = Minimum (myArray, 0, myArray.Length -1);
EDIT: Or create another overload:
int Minimum (int [] values)
{
return Minimum (values, 0, values.Length -1);
}
And to call use just:
int min = Minimum (myArray);
EDIT: And here's non-recursive method (bare in mind that this method actually modifies the array):
int Minimum(int[] values)
{
int step = 1;
do
{
for (int i = 0; i < values.Length - step; i += step)
if(values[i] > values[i + step])
values[i] = values[i + step];
step *= 2;
}
while(step < values.Length);
return values[0];
}
There are various simple solutions that utilize functions set up in C#:
int min = myArray.Min();
//Call your array something other than 'a' that's generally difficult to figure out later
Alternatively this will loop with a foreach through all of your values.
int minint = myArray[0];
foreach (int value in myArray) {
if (value < minint) minint = value;
}
1 - What tree are you talking about? Your array has n values to start with, so it will have n values max. If you mean the number of values in all the arrays you will create is 2n-1, it still doesn't mean you need to fit all of these in 1 array, create an array, use it and then create another array. C# GC will collect Objects of a reference type that have no pointers (are not going to be used again) so it will be fine memory wise if that's your concern?
2 - Post your code. There are a few gotchas but likely you will be fine changing the current array values or creating a new array. Temp int will not be needed.
3 - The above posted algos are the "simplest" using built in functions available to C#. If this is a homework assignment, please post some code.
As a general direction, using a recursive function would likely be most elegant (and some general reading on merge sorts would prove useful to you going forward).

Add Int[] array into List<int[]>

I'm having trouble with int[] arrays and adding them to a List<>. I'd like to add the values of my int[] array to something each loop but every time I do this my "something" gets the same value for every element I add. Very annoying. I understand arrays are always reference vars. However even the "new" key word doesn't seem to help. What needs to happen is to add result to some enumerated object like a List or Array or ArrayList.
Here's the codility question:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max_counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max_counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
I copied some code from others and the variable "result" does indeed load the data correctly. I just wanted to copy it back to the main program so I could see it. The only method that works is += add it into a string. Thus losing any efficiency I might have gained.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testarray
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[7];
A[0] = 3;
A[1] = 4;
A[2] = 4;
A[3] = 6;
A[4] = 1;
A[5] = 4;
A[6] = 4;
List<int[]> finish = solution(5, A);
}
public static List<int[]> solution(int N, int[] A)
{
int[] result = new int[N];
int maximum = 0;
int resetlimit = 0;
int iter = 0;
List<int[]> collected_result = new List<int[]>;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
{
throw new InvalidOperationException();
}
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetlimit)
{
result[A[K] - 1] = resetlimit + 1;
}
else
{
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
resetlimit = maximum;
result = Enumerable.Repeat(maximum, result.Length).ToArray<int>();
}
collected_result.Add(result);
}
// for (int i = 0; i < result.Length; i++)
//result[i] = Math.max(resetLimit, result[i]);
return collected_result;
}
}
}
This doesn't work, the collected_result ends up like:
(0,0,1,2,0)
(0,0,1,2,0)
(0,0,1,2,0)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
I know it's the line collected_result.Add(result); adding the reference each time to every instance of result in the List<>. Bother. I've tried adding "new" which is a compiler error. Finally in desperation I just added everything to a very long string. Can someone help me figure out how to properly load an object to pass back to main?
Easiest way to go:
Get a copy of your array before adding it to list:
collected_result.Add(result.ToArray());
Here is a Python solution:
def solution(A, N):
lenA = len(A)
k = 0
max_counter_value = 0
counters = [0 for x in range(0, N)]
for k in range(0, lenA):
if A[k] >= 1 and A[k] <= N:
counters[A[k] - 1] += 1
max_counter_value = max(counters)
if A[k] == N + 1:
counters = [max_counter_value for x in range(0, N)]
print counters
A = [3, 4, 4, 6, 1, 4, 4]
N = 5
solution(A, N)

How to find minimum number of steps to sort an integer array

I have an integer array int[] number = { 3,4,2,5,1};
The minimum number of steps to sort it should be 2. But I am getting 4.
static void Main(string[] args)
{
int[] number = { 3,4,2,5,1};
int result = get_order(number);
Console.ReadKey();
}
public static int get_order(int[] input1)
{
input1 = input1.OrderByDescending(o => o).ToArray();
bool flag = true;
int temp;
int numLength = input1.Length;
int passes = 0;
for (int i = 1; (i <= (numLength - 1)) && flag; i++)
{
flag = false;
for (int j = 0; j < (numLength - 1); j++)
{
if (input1[j + 1] > input1[j])
{
temp = input1[j];
input1[j] = input1[j + 1];
input1[j + 1] = temp;
flag = true;
}
}
passes++;
}
return passes+1;
}
What is the problem and what changes i need to do in my code?
Edit
implement #Patashu, algorithm,
public static int get_order(int[] input1)
{
var sorterArray = input1.OrderByDescending(o => o).ToArray();
var unsortedArray = input1;
int temp1;
int swap = 0;
int arrayLength = sorterArray.Length;
for (int i = 0; i < arrayLength; i++)
{
if (sorterArray[i] != unsortedArray[i])
{
temp1 = unsortedArray[i];
unsortedArray[i] = sorterArray[i];
for (int j = i + 1; j < arrayLength; j++)
{
if (unsortedArray[j] == sorterArray[i])
{
unsortedArray[j] = temp1;
swap++;
break;
}
}
}
}
return swap;
}
The problem with your algorithm is that it only attempts swapping adjacent elements.
3,4,2,5,1 is best sorted by swapping 3 with 5, which is an unadjacent swap, and then 2 with 3.
So, I suggest that you will find a better algorithm by doing the following:
1) First, sort the array into descending order using the built in sorting function of C#.
2) Now, you can use this sorted array as a comparison - iterate through the array from left to right. Every time you see an element in the unsorted array that is != to the element in the same space in the sorted array, look deeper into the unsorted array for the value the sorted array has there, and do one swap.
e.g.
3,4,2,5,1
Sort using Sort -> 5,4,3,2,1 is our sorted array
3 is != 5 - look in unsorted array for 5 - found it, swap them.
Unsorted is now 5,4,2,3,1
4 == 4
2 is != 3 - look in unsorted array for 3 - found it, swap them.
Unsorted is now 5,4,3,2,1
2 == 2
1 == 1
We're at the end of the unsorted array and we did two swaps.
EDIT: In your algorithm implementation, it looks almost right except
instead of
unsortedArray[j] = sorterArray[i];
unsortedArray[i] = temp1;
you had it backwards, you want
unsortedArray[j] = temp1;
unsortedArray[i] = sorterArray[i];
Since you're asking why you're getting 4 steps, and not how to calculate the passes, the correct way to do this is to simply step through your code. In your case the code is simple enough to step through on a piece of paper, in the debugger, or with added debug statements.
Original: 3, 4, 2, 5, 1
Pass: 1: 4, 3, 5, 2, 1
Pass: 2: 4, 5, 3, 2, 1
Pass: 3: 5, 4, 3, 2, 1
Pass: 4: 5, 4, 3, 2, 1
Basically what you see is that each iteration you sort one number into the correct position. At the end of pass one 2 is in the correct position. Then 3, 4, 5.
Ah! But this is only 3 passes you say. But you're actually incrementing passes regardless of flag, which shows you that you actually did one extra step where the array is sorted (in reverse order) but you didn't know this so you had to go through and double check (this was pass 4).
To improve performance, you do not need to start checking the array from the beginning.
Better than the last equal element.
static int MinimumSwaps(int[] arr)
{
int result = 0;
int temp;
int counter = 0;
for (int i = 0; i < arr.Length; ++i)
{
if (arr[i] - 1 == i)
{
//once all sorted then
if(counter==arr.Length)break;
counter++;
continue;
}
temp = arr[arr[i]-1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
result++;//swapped
i = counter ;//needs to start from the last equal element
}
return result;
}
At the start:
{ 3,4,2,5,1}; // passes = 0
Round 1 reuslt:
{ 4,3,2,5,1};
{ 4,3,5,2,1}; // passes = 1
Round 2 reuslt:
{ 4,5,3,2,1}; // passes = 2
Round 3 reuslt:
{ 5,4,3,2,1}; // passes = 3 and flag is set to true
Round 4 reuslt:
{ 5,4,3,2,1}; // same result and passes is incremented to be 4
You fail to mention that the array is supposed to be sorted in descending order, which is usually not the default expected behavior (at least in "C" / C++). To turn:
3, 4, 2, 5, 1
into:
1, 2, 3, 4, 5
one indeed needs 4 (non-adjacent) swaps. However, to turn it into:
5, 4, 3, 2, 1
only two swaps suffice. The following algorithm finds the number of swaps in O(m) of swap operations where m is number of swaps, which is always strictly less than the number of items in the array, n (alternately the complexity is O(m + n) of loop iterations):
int n = 5;
size_t P[] = {3, 4, 2, 5, 1};
for(int i = 0; i < n; ++ i)
-- P[i];
// need zero-based indices (yours are 1-based)
for(int i = 0; i < n; ++ i)
P[i] = 4 - P[i];
// reverse order?
size_t count = 0;
for(int i = 0; i < n; ++ i) {
for(; P[i] != i; ++ count) // could be permuted multiple times
std::swap(P[P[i]], P[i]); // look where the number at hand should be
}
// count number of permutations
This indeed finds two swaps. Note that the permutation is destroyed in the process.
The test case for this algorithm can be found here (tested with Visual Studio 2008).
Here is the solution for your question :)
static int MinimumSwaps(int[] arr)
{
int result = 0;
int temp;
int counter = 0;
for (int i = 0; i < arr.Length; ++i)
{
if (arr[i] - 1 == i)
{
//once all sorted then
if(counter==arr.Length)break;
counter++;
continue;
}
temp = arr[arr[i]-1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
result++;//swapped
i = 0;//needs to start from the beginning after every swap
counter = 0;//clearing the sorted array counter
}
return result;
}

Categories

Resources