Move an element from an array - c#

How can I move an element from an index, for example to the front. Let's say this example : moving the second index to the front, and the rest of the elements remain the same. As I am working with algorithms I can't implement things like lists that I found most efficient I guess.
Example : 1 2 3 4
Output : 3 1 2 4
I assigned the value from the index to a temporary variable so far. But I do not know how to shift the elements, I'm guessing implementing somehow a for loop.

You have to change how you iterate based on whether your desired index is before or after the elements original index and handle those cases individually.
public static void MoveToIndex(int[] array, int from, int to)
{
if (array.Length < 2) return;
if (from == to) return;
if (from < 0 || array.Length <= from) throw new ArgumentException(nameof(from));
if (to < 0 || array.Length <= to) throw new ArgumentException(nameof(to));
var startIndex = Math.Min(from, to);
var endIndex = Math.Max(from, to);
var swappedValue = array[startIndex];
if (to < from)
{
array[startIndex] = array[endIndex];
}
for (var i = startIndex + 1; i <= endIndex; i++)
{
var current = array[i];
if (to < from)
{
array[i] = swappedValue;
swappedValue = current;
}
else
{
array[i - 1] = i == endIndex ? swappedValue : current;
}
}
}

Related

Having trouble understanding a solution to this c# algorithm

I was doing a LeetCode exercise for c# and made my own solution for the following prompt:
"Given a binary array nums, return the maximum number of consecutive 1's in the array."
"Input: nums = [1,1,0,1,1,1]
Output: 3
Explanation: The first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3."
My solution had a hardcoded array value, and i found a solution online that worked and ran fine. However, im having a really hard time understanding what the isStart and isEnd bools do. The code is below:
public class Solution {
public int FindMaxConsecutiveOnes(int[] nums)
{
if(nums == null || nums.Length == 0)
{
return 0;
}
var start = 0;
var length = nums.Length;
var maxLength = 0;
for(int i = 0; i < length; i++)
{
var current = nums[i];
bool isStart = current == 1 && (i == 0 || nums[i - 1] == 0);
bool isEnd = current == 1 && (i == length - 1 || nums[i + 1] == 0);
if (isStart)
{
start = i;
}
if(isEnd)
{
var currentOnes = i - start + 1;
maxLength = currentOnes > maxLength ? currentOnes : maxLength;
}
}
return maxLength;
}
I assume isStart and isEnd determine if we are at the Start or End of the array? I dont really understand what the operators do either. Any help could be appreciated. Thanks :)

C# how to check if adjacent values are greater or smaller in an array and allocate points based on values?

I am trying to figure out how to assign points based on adjacent number values in an array. By default, each number is worth one point, and it increases in value if the adjacent numbers are lower than the current number.
For values at the start and the end of the array, the adjacent values are the end and start, so for numbers[0] adjacent values are numbers[5] && numbers[1] and for numbers[5] the values would be numbers[4] && numbers[0]. Consider it going in a circle.
As an example of numbers let's say we have int[] numbers = new int[] { 5, 6, 4, 2, 5, 6 }; after point allocation the output should be something like 1 3 2 1 2 3.
The issue I'm facing is that I don't know how to write the code in such a way that I don't get an error. And I would like to avoid using a lot of if nested functions. Managed to get it working like that but it looks horrible, so scrapped that and figured there must be a better way of doing this but I seem to be stuck...
static int[] AssignPoints (int[] numbers) {
int[] points = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++) {
points[i]++; //allocating initial point
???
}
return points;
}
static int[] AssignPoints (int[] numbers) {
int[] points = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++)
{
int prevIndex = (i-1 < 0 ? numbers.Length -1 : i-1);
int nextIndex = (i+1 >= numbers.Length ? 0 : i + 1);
if (numbers[i] > numbers[prevIndex])
points[i]++;
if (numbers[i] > numbers[nextIndex])
points[i]++;
}
return points;
}
A very explicit example:
static int[] AssignPoints (int[] numbers) {
int[] points = new int[numbers.Length];
for (int i = 0; i < numbers.Length; i++) {
var leftIndex = i == 0 ? numbers.Length - 1 : i - 1;
var rightIndex = i == numbers.Length - 1 ? 0 : i + 1;
points[i] = 1
+ (numbers[i] > numbers[leftIndex] ? 1 : 0)
+ (numbers[i] > numbers[rightIndex] ? 1 : 0);
}
return points;
}
static List<int> AssignPoints(List<int> numbers)
{
List<int> points =new List<int>(numbers.Capacity);
int i = 0, point;
foreach (int item in numbers)
{
point = 1;
if(i != 0)
if (numbers[i - 1] < numbers[i]) point++;
if(i != numbers.Capacity -1)
if (numbers[i + 1] < numbers[i]) point++;
i++;
points.Add(point);
}
return points;
}

Get n (part of) objects from a list of objects, starting from n index

I have a list of n objects. I want to grab a maximum of n items (-n previous items and n + next items), starting from the selected index. I want a method for this, in which I provide the list with certain parameters.
How can I achieve this in C#?
First example:
int selectedIndex = 5
int itemsToTake = 4 (2 previous and 2 next)
Returned list = 3-4-5-6-7
Second example:
int selectedIndex = 1
int itemsToTake = 4 (take 1 previous and 3 next, because list starts with 0)
Returned list = 0-1-2-3-4
I have already tried a combination of list.skip().take(), only that didn't go so well.
Example:
nextIndex = nextIndex - prevIndex + 1;
return List.Skip (prevIndex) .Take (nextIndex) .ToList ();
An inefficient but visually aesthetic way of doing it:
public static IEnumerable<T> Nearby<T>(this IEnumerable<T> source,
int selectedIndex, int itemsToTake)
{
var left = source.Take(selectedIndex).Reverse().Take(itemsToTake / 2).Reverse();
var middle = source.ElementAt(selectedIndex);
var right = source.Skip(selectedIndex).Skip(1).Take(itemsToTake / 2);
return left.Append(middle).Concat(right);
}
Usage example:
var source = Enumerable.Range(0, 10);
Console.WriteLine($"Result: {String.Join(", ", source.Nearby(5, 5))}");
Output:
Result: 3, 4, 5, 6, 7
Skip + Take should work fine, try this:
int firstIndex = selectedIndex - itemsToTake / 2;
firstIndex = firstIndex < 0 ? 0 : firstIndex;
return list.Skip(firstIndex).Take(itemsToTake);
First, make sure that the list contains enough elements:
if(itemsToTake + 1 > List.Count)
return List.ToList(); //copy the list
The first index you want to take is (not considering sequence borders):
var firstIndex = selectedIndex - itemsToTake / 2;
The corresponding last index would be firstIndex + n.
Then, make sure that the range is valid
if(firstIndex < 0)
firstIndex = 0;
if(firstIndex + nitemsToTake >= List.Count)
firstIndex = List.Count - 1 - itemsToTake ;
And finally do as you tried:
return List.Skip(firstIndex).Take(itemsToTake + 1).ToList();
You need to handle the special case of when selectedIndex - itemsToTake / 2 is less than 0:
public static List<T> Take<T>(this List<T> list, int selectedIndex, int itemsToTake) {
if (selectedIndex - n / 2 < 0) {
return list.Take(itemsToTake + 1).ToList();
}
return list.Skip(selectedIndex - itemsToTake / 2).Take(itemsToTake +1).ToList();
}
public static IEnumerable<T> Nearby<T>(IEnumerable<T> source, int selectedIndex, int itemsToTake)
{
itemsToTake = ((itemsToTake/2)*2)+1;
Queue<T> queue = new Queue<T>();
bool foundItem = false;
int afterItemCount = 0;
int recommendedAfterItemCount = itemsToTake/2;
foreach(var pair in source.Select((t, i) => new {t, i}))
{
T t = pair.t;
int i = pair.i;
queue.Enqueue(t);
if (itemsToTake < queue.Count) queue.Dequeue();
if (i == selectedIndex) foundItem = true;
else if (foundItem) afterItemCount += 1;
bool enoughItems = queue.Count == itemsToTake;
bool enoughAfterItems = recommendedAfterItemCount <= afterItemCount;
if (enoughItems && enoughAfterItems) break;
}
foreach(T t in queue)
{
yield return t;
}
}

How do I determine between which two array indexes a number lies

I've got some code that I've worked on that is functional but I feel I'm doing it in a very obtuse way.
I have a fixed size array of 13 elements. The array is populated from a SQL table. If given a number, I'd like to know between which two array indexes the number belongs.
For example: If my number is 500 and I have the following elements:
-500, -400, -255, -89, 77, 243, 409, 575, 741, 907, 1073, 1500, 2000
...500 would be between elements 6 and 7. (409 and 575)
I've written a fairly brute force method for doing this using IF statements, code below. I basically create a second array and I use the IF statements to check the number against the first array. Note - I'm ignoring the case where the number is greater than the the max or min array numbers. I've searched for an array method that can search between indexes to no avail. Any ideas on how I can do this more efficiently? Thank you.
int[] deviations = new int[13] { -500, -400, -255, -89, 77, 243, 409, 575, 741, 907, 1073, 1500, 2000 };
int[] arrayCheck = new int[12];
Int64 num = 500;
Console.WriteLine("The number is: {0}", num);
if ((num >= deviations[0]) && (num < deviations[1]))
{arrayCheck[0] = 1;}
else { arrayCheck[0] = 0;}
if ((num >= deviations[1]) && (num < deviations[2]))
{arrayCheck[1] = 1;}
else { arrayCheck[1] = 0;}
if ((num >= deviations[2]) && (num < deviations[3]))
{ arrayCheck[2] = 1; }
else { arrayCheck[2] = 0; }
if ((num >= deviations[3]) && (num < deviations[4]))
{ arrayCheck[3] = 1; }
else { arrayCheck[3] = 0; }
if ((num >= deviations[4]) && (num < deviations[5]))
{ arrayCheck[4] = 1; }
else { arrayCheck[4] = 0; }
if ((num >= deviations[5]) && (num < deviations[6]))
{ arrayCheck[5] = 1; }
else { arrayCheck[5] = 0; }
if ((num >= deviations[6]) && (num < deviations[7]))
{ arrayCheck[6] = 1; }
else { arrayCheck[6] = 0; }
if ((num >= deviations[7]) && (num < deviations[8]))
{ arrayCheck[7] = 1; }
else { arrayCheck[7] = 0; }
if ((num >= deviations[8]) && (num < deviations[9]))
{ arrayCheck[8] = 1; }
else { arrayCheck[8] = 0; }
if ((num >= deviations[9]) && (num < deviations[10]))
{ arrayCheck[9] = 1; }
else { arrayCheck[9] = 0; }
if ((num >= deviations[10]) && (num < deviations[11]))
{ arrayCheck[10] = 1; }
else { arrayCheck[10] = 0; }
if ((num >= deviations[11]) && (num < deviations[12]))
{ arrayCheck[11] = 1; }
else { arrayCheck[11] = 0; }
int arrayIndex = Array.IndexOf(arrayCheck, 1);
Console.WriteLine("The num is between array indexes: {0} and {1}", arrayIndex, arrayIndex + 1);
If array is sorted, Array.BinarySearch is the way to go.
int[] deviations = new int[13] { -500, -400, -255, -89, 77, 243, 409, 575, 741, 907, 1073, 1500, 2000 };
var index = Array.BinarySearch(deviations,500);
if(index >= 0)
{
//Found at index
}
else
{
int expectedindex = ~index;
//Should fall in expectedindex
}
Array.BinarySearch returns the index of the specified value in the
specified array, if value is found. If value is not found and value is
less than one or more elements in array, a negative number which is
the bitwise complement of the index of the first element that is
larger than value. If value is not found and value is greater than any
of the elements in array, a negative number which is the bitwise
complement of (the index of the last element plus 1).
So when this method returns a negative value, that means given value is not found. but the bit-wise complement of the expected index of the element is returned. Bitwise complement works by changing the bits representation of 1 to 0 and 0 to 1, We make use of ~ operator to turn the bitwise complemented number back to original.
You could use the following two LINQ statements:
var previousIndex = deviations.Select((d, idx) => new { d, idx })
.Last(x => x.d <= num).idx;
var nextIndex = deviations.Select((d, idx) => new { d, idx })
.First(x => x.d >= num).idx;
You might want to use LastOrDefault() and FirstOrDefault() if you're worried about being below the smallest number or above the largest.
Assuming your array is already sorted, can't you just loop through the array?
(Not tested code)
var foundIndex = -1;
for ( var i = 0; i < deviations.GetUpperBound(0); i++ )
{
if ( num >= deviations[i] && num < deviations[i+1] )
{
foundIndex = i;
break;
}
}

Heapsort with min-heap not working correctly

I'm trying to implement heapsort with min-heap. Input is array of positive integers and array's zero index stores the size. Can anyone spot my error? Language used here is C#. The algorithm works correctly sometimes, but with bigger arrays the root is not the smallest value in the array.
static void CreateMinHeap(int[] input)
{
input[0] = input.Length - 1;
for (int i = (input[0] / 2); i > 0; i--)
{
MinHeapify(input, i);
}
}
static void MinHeapify(int[] input, int index)
{
var left = 2 * index;
var right = 2 * index + 1;
int smallest;
if (left < input.Length && input[left] < input[index])
smallest = left;
else
smallest = index;
if (right < input.Length && input[right] < input[smallest])
smallest = right;
if (smallest != index)
{
Swap(ref input[smallest], ref input[index]);
MinHeapify(input, smallest);
}
}
static public void HeapSort(int[] input)
{
CreateMinHeap(input);
for (int i = input[0]; i > 0; i--)
{
Swap(ref input[1], ref input[i]);
input[0]--;
MinHeapify(input, 1);
}
}
static public void Swap(ref int a, ref int b)
{
var temp = a;
a = b;
b = temp;
}
Background
As far as I understand you are using your array in two partitions.
The first partition contains the heap, and the second partition (which starts empty) contains the sorted values.
During HeapSort the size of the first partition decreases, and the second increases until you have a sorted array.
Bug
The problem is that when you run MinHeapify you have not told it that the length of the heap has decreased so it is trying to heapify some of your sorted nodes.
Fix
You are keeping track of the size of the heap in entry input[0] so this should be easy to fix.
Try changing:
if (left < input.Length && input[left] < input[index])
smallest = left;
else
smallest = index;
if (right < input.Length && input[right] < input[smallest])
smallest = right;
to
if (left <= input[0] && input[left] < input[index])
smallest = left;
else
smallest = index;
if (right <= input[0] && input[right] < input[smallest])
smallest = right;

Categories

Resources