C# locate value in a array and move it to right - c#

My task is to find a element in the array that is the same as given value, and then take it to right while maintaining the order of other elements. An example (Test Case):
{1, 2, 0, 1, 0, 1, 0, 3, 0, 1} for value = 0 => {1, 2, 1, 1, 3, 1, 0, 0, 0, 0}
While my code could do that above example, what it could not do is a very specific case: if the element in array equals value and the next element also equals value it will not shift the element. Again a example:
{ 1, int.MinValue, int.MinValue, int.MaxValue, int.MinValue, -1, -3, -9, 1 }, value = int.MinValue
Expected result: { 1, int.MaxValue, -1, -3, -9, 1, int.MinValue, int.MinValue, int.MinValue }
Result with my code: { 1, int.MinValue ,int.MaxValue, -1, -3, -9, 1, int.MinValue, int.MinValue }
I thought shifting is the one solution, is it? I am having a lot of problems with it, I also tried Array.Copy but there were problems the result was always out of range.
How can I make it so that it will shifts/rotates correctly in all cases?
Code:
static void Main(string[] args)
{
int[] source = new int[] { 1, int.MinValue, int.MinValue, int.MaxValue, int.MinValue, -1, -3, -9, 1 };
int value = int.MinValue;
for (int i = 0; i < source.Length; i++)
{
if (source[i] == value)
{
LeftShiftArray(source, i);
}
}
for (int i = 0; i < source.Length; i++)
{
Console.WriteLine(source[i]);
}
}
public static void LeftShiftArray(int[] source, int i)
{
var temp1 = source[i];
for (var j = i; j < source.Length - 1; j++)
{
source[j] = source[j + 1];
}
source[source.Length - 1] = temp1;
}
Now this

I have a simple approach to solve this problem. Run a loop, You keep on counting the numbers which are not equal to your number. And keep assigning to arr[count]. Then increment the count. And then finally you will be left to assign all the remaining numbers with the given number.
static void MoveToEnd(int []arr, int n)
{
int count = 0;
    for (int i = 0; i < arr.Length; i++)
        if (arr[i] != n)
         arr[count++] = arr[i];
    while (count < arr.Length)
        arr[count++] = n;
}
Please note I have typed this answer from phone, so please avoid typing mistakes.

This is a classic off by one error. Think about it like this:
Let's say you are moving all 0s to the back (value = 0). When you find a zero at some position, let's say source[2], you turn your array from this:
1 1 0 0 1 1
source[2] ^
To this:
1 1 0 1 1 0
source[2] ^
Now that you've shifted the array, the next step in your code is to increase i by 1. That means the next comparison you make will be with source[3]. In the above array, that looks like this:
1 1 0 1 1 0
source[3] ^
Do you see the problem? Let me know if not and I can explain further.
PS. There are a couple of issues with the other code that was posted that will probably stop you from getting full points if you were to turn it in for an assignment :)

Related

Move Negative Numbers to the left, first come fist list

I'm trying to move negative numbers to the left.
using System;
class Class1
{
static void rearrange(int[] arr, int n)
{
int j = 0, temp;
for (int i = 0; i < n; i++)
{
if (arr[i] < 0)
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
j++;
}
}
}
static void printArray(int[] arr, int n)
{
for (int i = 0; i < n; i++)
Console.Write(arr[i] + ",");
}
//Call the Method
public static void Main()
{
int[] arr = { 1, -4, -7, 4, -2, 6, -9 };
int n = arr.Length;
rearrange(arr, n);
printArray(arr, n);
}
}
The question expects the output { -4, -7, -2, -9, 1, 4, 6 }
But my output is { -4, -7, -2, -9, 1, 6, 4 }, because the code is to switch -9 with 4.
How to adjust the code?
Wouldn't it be simpler to use LINQ?
Here is the code which does what you need using LINQ:
var list = new[]{ 1, -4, -7, 4, -2, 6, -9 };
var newList = list.Where(x => x < 0).Union(list.Where(x => x >= 0)).ToList();
Console.WriteLine(string.Join(", ", newList));
Output:
-4, -7, -2, -9, 1, 4, 6
It looks like the problem is that the code is always swapping a negative number with the number that's in the position where the negative number should go. This becomes a problem when there are a few positive numbers in a row, because the order is disturbed when a positive number in a low index is swapped with a negative number in a high index. This happens when i is 4 and -2 is swapped with 1 (so at that moment the array looks like { -4, -7, -2, 4, 1, 6, -9 }); and again when i is 6 and -9 gets swapped with 4, which leaves you with the result that prompted your question.
To resolve this, you have to swap the negative number with the number before it in an inner loop, until the number before it is also negative, so that the numbers retain their relative positioning:
static void Rearrange(int[] arr)
{
// Start at index 1 since the first item can't move left
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] < 0)
{
// Walk backwards from the current index, swapping items as we
// go, until the item in the previous index is also negative
for (int j = i; j > 0; j--)
{
// If previous item is negative, we can stop
if (arr[j - 1] < 0) break;
// Otherwise, swap this item with the previous item
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
}
Before the last iteration, the array is in this state:
{ -4, -7, -2, 4, 1, 6, -9}
You algorithm then swaps -9 and 4:
{ -4, -7, -2, -9, 1, 6, 4}
Why would you expect 6 to be the last number in the array?
If you want numbers to be ordered, C# provides an .OrderBy extension method, but that would also change the order of the negative numbers.

How does an equilibrium index of an array work?

I tried a demo test on Codility for finding the equilibrium index(es) of an array. I'm not sure if the test was to find the equilibrium indexes of an array or what. I googled around and found the following example:
The equilibrium index of a sequence is an index such that the sum of elements at lower indexes is equal to the sum of elements at higher indexes. For example, in a sequence A:
A[0]=-7 A[1]=1 A[2]=5 A[3]=2 A[4]=-4 A[5]=3 A[6]=0
3 is an equilibrium index, because:
A[0] + A[1] + A[2] = A[4] + A[5] +A[6]
6 is also an equilibrium index, because:
A[0] + A[1] + A[2] + A[3] + A[4] + A[5] = 0
Based on this information I see the test array contains 7 elements. It looks like the middle element A[3]=2 is being ignored. Is it because it is between the first 3 elements and the last 3 elements? How is the equilibrium index of 6 arrived at in this example?
Here is the method that was used to compute this:
int equi(int arr[], int n) {
if (n==0) return -1;
long long sum = 0;
int i;
for(i=0;i<n;i++) sum+=(long long) arr[i];
long long sum_left = 0;
for(i=0;i<n;i++) {
long long sum_right = sum - sum_left - (long long) arr[i];
if (sum_left == sum_right) return i;
sum_left += (long long) arr[i];
}
return -1;
}
When I took the Codility demo test I used the method (below) with the for loops initially beginning at 0. I received a "wrong answer" message for the test case of 1, 5, 2, 1, 4, 0 and that Codility was looking for a result of 11.
I modified the two for loops in my method and started the first loop at i = 1 and the second loop at i = 2 until it yielded a result of 11, which Codility was satisfied with. I basically just tweaked the method until Codility was happy (I was shooting for 11 because Codility specified that was the answer they were looking for), but I don't really know why Codility was happy or what was the significance of my tweaks -- just hit and miss:
...
int[] B = new int[] { 1, 5, 2, 1, 4, 0 };
Console.WriteLine(solution3(B));
}
public int solution3(int[] A)
{
long rsum = 0;
for (int i = 1; i < A.Count(); i++)
rsum += A[i];
long lsum = A[0];
int min = (int)Math.Abs(lsum - rsum);
for (int i = 2; i < A.Count() - 1; i++)
{
lsum += A[i];
rsum -= A[i];
int diff = (int)Math.Abs(lsum - rsum);
if (diff >= min)
min = diff;
}
return min;
}
Why did this tweak (of hit and miss) satisfy the Codility test? What is an equilibrium index actually? How is it arrived at? Note: if there are steps between step A and step E (which I would have to intuit the in between steps) what are steps B, C, and D?
What is an equilibrium index and how is it determined?
Think of your array like a board with weights of different sizes on it (negative weights can be thought of as helium balloons attached to the board). Each weight is numbered from left to right. Your task is to place a fulcrum under the board at any of the numbered positions to make the board balance. (We will treat the board itself as weightless, and assume distance of the weights from the center doesn't matter.) Whichever positions make the board balance are the equilibrium indexes. The weight at the fulcrum doesn't "count" because it's not on either side; it is in the middle.
Here is a picture of the first example:
Here, 3 is an equilibrium index, because the sum of the weights to the left of the fulcrum equal the sum of the weights to the right of the fulcrum (-7 + 5 + 1 = -1 = -4 + 3 + 0).
Here is the second example:
We see that 6 is also an equilibrium index for the same reason. All the elements to the left of the fulcrum add up to zero. As there are no elements to the right of the fulcrum, that sum is also zero.
The basic algorithm to find the equilibrium indexes is this:
Loop over the array and add up all the elements. Call this sum total.
Initialize a variable left_sum to zero.
Initialize a variable right_sum to total.
Now loop over the array a second time. For each array item:
Subtract the value of the current item from right_sum.
Compare the left_sum to the right_sum. If they are equal, then the index of the current item is an equilibrium index.
Add the value of the current item to left_sum.
And that's all there is to it. Does it make sense now?
What's going on with my algorithm?
As for why the "Codility demo test" was expecting a result of 11 for an array containing the elements { 1, 5, 2, 1, 4, 0 }, I cannot say. You never said in your question what the demo problem actually was. If the problem was to find the first equilibrium index in that array, then the answer is that there is none for that array. Stepping through the above algorithm, here are the left and right sums for each array index:
Index Left Right
----- ---- -----
0 0 12
1 1 7
2 6 5
3 8 4
4 9 0
5 13 0
As you can see, there is no index at which the left sum equals the right sum. An expected result of 11 does not even make sense anyway because there are only six elements. So if there were an equilibrium index for this array, it would have to between 0 and 5 inclusive. So I'm guessing the problem posed must have been something else. You would have to include the problem statement in your question before I could even begin to guess why your algorithm is or isn't correct.
Well, based on what I understand about an equilibrium index of an array I came up with the following algorithm which I tested on another array which has equilibrium indexes as index 3 and index 6, but I also tested this algorithm on the original array which returned a -1 (nothing to do with an 11). Here is the sample:
private void button6_Click_1(object sender, EventArgs e)
{
//int[] arr = new int[7] { -7, 1, 5, 2, -4, 3, 0 }; //--new array
int[] arr = new int[6] { 1, 5, 2, 1, 4, 0 }; //--original array
List<int> lst = new List<int>();
int p = arr.Length;
int i = 0;
int q = 0;
int t = 0;
do
{
t = equilibrium(arr, arr.Length, q);
if (lst.IndexOf(t) == -1)
lst.Add(t);
q = t;
i++;
} while (i < p);
foreach (var m in lst)
Console.WriteLine(m);
}
private int equilibrium( int[] arr, int n, int q1)
{
int i, j;
int leftsum, rightsum;
for (i = 0; i < n; ++i)
{
leftsum = 0;
rightsum = 0;
for (j = 0; j < i; j++)
leftsum += arr[j];
for (j = i + 1; j < n; j++)
rightsum += arr[j];
if (leftsum == rightsum && q1 != i)
return i;
}
return -1;
}
This algorithm makes sense to me, but when I tried it on Codility with an array of int[] arr = new int[] { 2, 2, 1, 0, 1 }; I got a "wrong Answer -- expected 3" In my test app my algorithm returned a 1 which is what it returned on Codility. Where did they come up with 3 for this array? Thus, I do not understand the equilibrium index of an array. Any suggestions appreciated.

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

Find the greatest right number from the current number in the array algorithm

My algorithm should find the greatest right number from the current number in an input array, for example, given the following int[] input:
5, 9, 6, 1, 3, 2
My algorithm will output:
9, 6, 3, 3, 2, 2
Here is my current code:
public static int[] FindGreatestRightNumber(int[] input)
{
var output = new int[input.Length];
for (var i = 0; i < input.Length; i++)
{
int maxRightNumber = (i == input.Length - 1 ? input[i] : 0);
for (var j = i+1; j < input.Length; j++)
{
var currentNumber = input[j];
if (maxRightNumber < currentNumber)
maxRightNumber = currentNumber;
}
output[i] = maxRightNumber;
}
return output;
}
I was told it could be much faster, how? any idea?
UPDATE: Please don't use LINQ in your answers, I would like to get familiar with faster ways to solve the problem using simple code, no LINQ, IEnumerable Extension Methods etc.
You can do this in a single pass from the right hand side. The trick is realizing maxRightVal(n) = max(maxRightVal(n+1), values(n+1)):
var output = new int[input.Length];
output[input.Length-1] = input[input.Length-1];
for(int i = input.Length - 2; i >= 0; i--)
output[i] = output[i+1] > input[i+1] ? output[i+1] : input[i+1];
Why not just using Enumerable.Max() method?
Returns the maximum value in a sequence of Int32 values.
int[] input = new int[] { 5, 9, 6, 1, 3, 2 };
int biggest = input.Max();
Console.WriteLine(biggest); // 9
Here is a DEMO.
Since, I see the question better now, VLad's answer looks the right one.
very simple if you want to skip some items and search the max
int[]arr = {5, 9, 6, 1, 3, 2};
int currentIndex = 2;
int currentValue = 6;
int max = arr.Skip(currentIndex).Where(f => f > currentValue).Max();
EDIT if you want to simply sort an array, then:
int[] sorted = arr.OrderByDescending();
Start from the (n-2)th elements, maintain a current max array which is initialised with nth element. Keep updating it if the current element is greater than the element in max array. Continue this until the first element is reached.
This takes the largest value to the right of each element;
int[] input = {5, 9, 6, 1, 3, 2};
int[] output = input
.Take(input.Length-1)
.Select( (x,i) => input.Skip(i+1).Max()).ToArray();

Categories

Resources