Related
This question already has an answer here:
What is an "index out of range" exception, and how do I fix it? [duplicate]
(1 answer)
Closed 9 months ago.
how to find the max sequence order number before missing element.
input - 123678 output -3
public static void Main()
{
List<int> nums = new List<int>(){1,2,3,6,7,8};
int count = nums.Count;
for(int i=0;i<count;i++){
if((nums[i+1]-nums[i])>1){
Console.WriteLine("Missed Element after digit :" [i]);
}
}
}
fiddle https://dotnetfiddle.net/Hkd0rx
error
Index was out of range. Must be non-negative and less than the size of
the collection.
You need to skip the last number because there's nothing to compare it to after it. So in your for loop change the condition to loop while i<count-1 is true.
You also have an error in your WriteLine. Right now it will pick the character from the string Missed Element after digit : at a specific index. To properly concatenate strings you could use + or string interpolation.
List<int> nums = new List<int>() { 1, 2, 3, 6, 7, 8 };
int count = nums.Count;
for (int i = 0; i < count - 1; i++)
{
var current = nums[i];
var next = nums[i + 1];
if ((next - current) > 1)
{
Console.WriteLine("Missing Element(s) between : " + current + " and " + next);
}
}
Several issues are here:
nums[i+1] can be out ouf range when i = 0 .. nums.Count - 1.
When item is found you should break looping
If all items (no missing item) in required order, you should return the last one.
Code
List<int> nums = new List<int>(){
1, 2, 3, 6, 7, 8
};
// Add sorting if there's no guarantee that num has been sorted
// nums.Sort();
// In case we have no missing item we return the last one
int result = nums[nums.Count - 1];
// Note "nums.Count - 1" instead of "nums.Count"
for (int i = 0; i < nums.Count - 1; ++i)
if (nums[i + 1] - nums[i] > 1) {
result = nums[i];
break; // Note break
}
Console.WriteLine($"Missed Element is after number : {result}");
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.
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)
This question already has answers here:
Deleting A Specified Element In An Array Using Random Class
(4 answers)
Closed 9 years ago.
int oldLength = numbers.Length;
int[] arrTmp = numbers;
numbers = new int[oldLength - 1];
Array.Copy(arrTmp, numbers, Token);
Array.Copy(arrTmp, r+1, numbers, Token, oldLength - Token - 1);
This all i got to remove a specified element from a value type array but it doesn't work.
I got 4 elements of value type array. I have stored 4 different numbers in it.
array[0] = 2;
array[1] = 4;
array[2] = 6;
array[3] = 8;
i got a random class to randomly pick a number if it is 2 has to be removed from my array in an ascending sequential order each element should be inspected and eliminated.
You would do much easier using the List class
List<int> l = new List<int>();
l.Add(2);
l.Add(4);
...
l.Remove(2);
int oldLength = numbers.Length;
int[] arrTmp = new int[oldLength - 1];
for(int i = 0, j = 0; i < oldLength || j < arrTmp.Length; i++)
{
if(numbers[i] == Token)
continue;
arrTmp[j++] = numbers[i];
}
using linq:
var newArray = numbers.Where(n=> n!= Token).ToArray();
This would be the general approach:
int oldLength = numbers.Length;
int[] arrTmp = numbers;
numbers = new int[oldLength - 1];
Array.Copy(arrTmp, numbers, r);
Array.Copy(arrTmp, r + 1, numbers, r, oldLength - r - 1);
Note the use of r everywhere. Here r would be the index of the element to omit.
If you really need to use plain arrays and copy their contents using Array.Copy (which is not a common way of handling things in .NET), then start by using a pen and write down correct indices and lengths of the array parts you are trying to copy.
Starting to code the solution before you know how to solve it won't get you far.
So, start with an example array and a random index:
// starting array
int[] array = { 0, 1, 2, 3, 4, 5, 6, 7 };
// index to remove
int indexToRemove = new Random().Next(array.Length);
Now, presume that indexToRemove is 3 and try to do it by hand:
Part 1: { 0, 1, 2 } (start = 0, length = 3)
Part 2: { 4, 5, 6, 7 } (start = 4, length = 4)
From this concrete example, you can try to infer the general formula for offset and length of these two array parts:
Part 1: start = 0, length = (indexToRemove - 1)
Part 2: start = (indexToRemove + 1), length = (array.Length - indexToRemove - 1)
The code itself is then trivial:
var len = array.Length;
var newArray = new int[len - 1];
Array.Copy(array, 0, newArray, 0, indexToRemove - 1);
Array.Copy(array, indexToRemove + 1, newArray, indexToRemove, len - indexToRemove - 1);
Additionally, the Array.Copy can be used to copy a part of an array over itself, which means you can just move the second part of the array back by one position, and then resize the initial array using Array.Resize:
// do not create a new array, but simply "move" the 2nd part to left
Array.Copy(array, indexToRemove + 1, array, indexToRemove, len - indexToRemove - 1);
// finally, resize the original array
Array.Resize(ref array, array.Length - 1);
Of course, if you simply used a List<int>, then you would simply use the List<T>.RemoveAt method to remove the item:
var list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int indexToRemove = new Random().Next(list.Count);
list.RemoveAt(indexToRemove);
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;
}