how to find a max element of highest sequence number [duplicate] - c#

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

Related

Is it okay to exit a loop when an exception is thrown?

I solved a task on Hackerrank.com, where the problem was like this:
You have an Array. This Array contains numbers.
Now you enter two numbers:
The first one describes a sum
The second one describes the amount of indexes (sequence length) you add together
In the end you get the amount of sequences whose sum is your defined number
For example:
Your array is [ 1, 2, 3, 4], your sum is 3 and your sequence length is 2.
Now you take the first two indexes and output the sum: [1, 2] = 3.
This is equal to your sum, so now you have found one sequence.
The next sequence is [ 2, 3 ] = 5. This is not equal to 3, so your sequence counter stays 1.
The last sequence is [3, 4] = 7. This is also not equal to 3 and in the end, you found one sequence.
I wrote this code for that:
static int GetSequences(List<int> s, int d, int m)
{
//m = segment-length
//d = sum
int count = 0;
int j = 0;
int k = 0;
do
{
try
{
List<int> temp = new List<int>();
for (int i = 0; i < m; i++)
{
temp.Add(s[i + k]);
}
if (temp.Sum() == d)
{
count++;
}
j++;
k++;
}
catch (ArgumentOutOfRangeException)
{
break;
}
} while (true);
return count;
}
As I didn't know how often I have to count
(For example a 6-Length-Array with a sequence-length of 3 has 4 sequences (1,2,3 | 2,3,4 | 3,4,5 | 4,5,6)),
I am stopping the while loop when the index is out of range. but I'm not sure if this solution is okay. Not just with program speed, but also with code cleanliness. Is this code acceptable, or is it better to use a for loop, which loops for example exactly 4 times for a 6-length array with 3-Length sequences?
It's not recommended, no. Exceptions should be reserved for stuff that isn't supposed to happen, not flow control or validation.
What you want is to use conditional logic (if statements) and the break keyword.
Also, codereview.stackexchange.com is better suited for these kinds of questions.
It would be better to fix your code so that it doesn't routinely throw exceptions:
You sum each of these segments:
0 1 2 3 start = 0
| | summing indexes: 0, 1
+--+
0 1 2 3 start = 1
| | summing indexes: 1, 2
+--+
0 1 2 3 start = 2
| | summing indexes: 2, 3
+--+
The bracket starts at the index start, and has a size of m. The length of s is given by s.Count. Therefore we want to keep going until start + m == s.Count.
(I always find it's useful to draw these things out, and put sample numbers in, in order to make sure you've got the maths right. In the sample above, you can see that we stop when start (2) + m (2) == the array size (4))
static int GetSequences(List<int> s, int d, int m)
{
//m = segment-length
//d = sum
int count = 0;
for (int start = 0; start + m <= s.Count; start++)
{
List<int> temp = new List<int>();
for (int i = 0; i < m; i++)
{
temp.Add(s[start + i]);
}
if (temp.Sum() == d)
{
count++;
}
}
return count;
}
However, you can improve your code a bit:
Use meaningful variable names
Don't create a new temporary list each time, just to sum it
Check your inputs
static int GetSequences(List<int> numbers, int targetSum, int segmentLength)
{
if (numbers == null)
throw new ArgumentNullException(nameof(numbers));
if (segmentLength > numbers.Count)
throw new ArgumentException("segmentLength must be <= numbers.Count");
int count = 0;
for (int start = 0; start + segmentLength <= numbers.Count; start++)
{
int sum = 0;
for (int i = 0; i < segmentLength; i++)
{
sum += numbers[start + i];
}
if (sum == targetSum)
{
count++;
}
}
}
Usually except for switch/case there is often no real reason to use break.
Also an exception MUST be as the name says exceptional, so it MUST NOT be a part of your logic.
As said Jeppe you can use the methods and attributes the framework provides you to do as you like.
Here s.Count seems to be the way to go.
int[] arr = new[] { 1, 2, 1, 2 };
// Sum and len are given by the task.
// 'last' is the last index where we should stop iterating.
int sum = 3, len = 2, last = arr.Length - len;
// One of the overloads of Where accepts index, i.e. the position of element.
// 1) We check that we don't go after our stop-index (last).
// 2) Avoid exception by using '&&'.
// 3) We use C# 8 Range (..) to get the slice of the numbers we need:
// we start from the current position (index) till then index,
// calculated as current index + length given by the task.
// 4) Sum all the numbers in the slice (Sum()) and compare it with the target sum,
// given by the task (== sum).
// 5) The count of all matches (Count()) is the sought amount of sequences.
int count = arr.Where((z, index) => index <= last && arr[index..(index+len)].Sum() == sum).Count();

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.

Removing n elements before and after the given number

can you tell me how to remove n elements before and after the given number in array of integers? For example we have 1 2 2 4 2 2 2 9 and have to remove 2 elements before and after number "4". So it will left 1429. I tried to came up with something, but... nothing.
var sequenceOfNums = Console.ReadLine().Split(' ').Select(int.Parse).ToList();
var specials = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
int bombNum = specialBombNum[0];
int power = specialBombNum[1];
for (int i = 0; i < sequenceOfNums.Count; i++) {
sequenceOfNums.RemoveRange(bombNum, sequenceOfNums.IndexOf(bombNum + power));
sequenceOfNums.Remove(bombNum);
}
This should work:
var sequenceOfNums = new List<int> {1, 2, 2, 4, 2, 2, 2, 9};
int bombNum = 4;
int power = 2;
//Get the index of the special number
int locationOfSpecialNumber = sequenceOfNums.IndexOf(bombNum);
//Starting from (index of special number - [power]), remove [power] elements
sequenceOfNums.RemoveRange(locationOfSpecialNumber - power, power);
//Starting from (index of special number + 1), remove [power] elements.
//We subtract [power] from the starting index to account for the
//[power] elements we removed in the previous statement
sequenceOfNums.RemoveRange(locationOfSpecialNumber + 1 - power, power);

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

Printing out 3 elements in array per line

I have an array with x number of elements and want to print out three elements per line (with a for-loop).
Example:
123 343 3434
342 3455 13355
3444 534 2455
I guess i could use %, but I just can't figure out how to do it.
For loop is more suitable:
var array = Enumerable.Range(0, 11).ToArray();
for (int i = 0; i < array.Length; i++)
{
Console.Write("{0,-5}", array[i]);
if (i % 3 == 2)
Console.WriteLine();
}
Outputs:
0 1 2
3 4 5
6 7 8
9 10
Loop through the array 3 at a time and use String.Format().
This should do it...
for (int i = 0; i < array.Length; i += 3)
Console.WriteLine(String.Format("{0,6} {1,6} {2,6}", array[i], array[i + 1], array[i + 2]));
But if the number of items in the array is not divisable by 3, you'll have to add some logic to make sure you don't go out of bounds on the final loop.
You perhaps need to fix the format spacing...
for(int i=0;i<array.Length;i++)
{
Console.Write(array[i] + " ");
if((i+1)%3==0)
Console.WriteLine();
}
Long... but with comments:
List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int count = list.Count;
int numGroups = list.Count / 3 + ((list.Count % 3 == 0) ? 0 : 1); // A partially-filled group is still a group!
for (int i = 0; i < numGroups; i++)
{
int counterBase = i * 3;
string s = list[counterBase].ToString(); // if this a partially filled group, the first element must be here...
if (counterBase + 1 < count) // but the second...
s += list[counterBase + 1].ToString(", 0");
if (counterBase + 2 < count) // and third elements may not.
s += list[counterBase + 2].ToString(", 0");
Console.WriteLine(s);
}

Categories

Resources