Related
Lists say I have a list List<int> {1,2,3,4,5}
Rotate means:
=> {2,3,4,5,1} => {3,4,5,1,2} => {4,5,1,2,3}
Maybe rotate is not the best word for this, but hope you understand what I means
My question, whats the easiest way (in short code, c# 4 Linq ready), and will not be hit by performance (reasonable performance)
Thanks.
List<T>
The simplest way (for a List<T>) is to use:
int first = list[0];
list.RemoveAt(0);
list.Add(first);
Performance is nasty though - O(n).
Array
This is basically equivalent to the List<T> version, but more manual:
int first = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = first;
LinkedList<T>
If you could use a LinkedList<T> instead, that would be much simpler:
int first = linkedList.First;
linkedList.RemoveFirst();
linkedList.AddLast(first);
This is O(1) as each operation is constant time.
Queue<T>
cadrell0's solution of using a queue is a single statement, as Dequeue removes the element and returns it:
queue.Enqueue(queue.Dequeue());
While I can't find any documentation of the performance characteristic of this, I'd expect Queue<T> to be implemented using an array and an index as the "virtual starting point" - in which case this is another O(1) solution.
Note that in all of these cases you'd want to check for the list being empty first. (You could deem that to be an error, or a no-op.)
You could implement it as a queue. Dequeue and Enqueue the same value.
**I wasn't sure about performance in converting a List to a Queue, but people upvoted my comment, so I'm posting this as an answer.
I use this one:
public static List<T> Rotate<T>(this List<T> list, int offset)
{
return list.Skip(offset).Concat(list.Take(offset)).ToList();
}
It seems like some answerers have treated this as a chance to explore data structures. While those answers are informative and useful, they are not very Linq'ish.
The Linq'ish approach is: You get an extension method which returns a lazy IEnumerable that knows how to build what you want. This method doesn't modify the source and should only allocate a copy of the source if necessary.
public static IEnumerable<IEnumerable<T>> Rotate<T>(this List<T> source)
{
for(int i = 0; i < source.Count; i++)
{
yield return source.TakeFrom(i).Concat(source.TakeUntil(i));
}
}
//similar to list.Skip(i-1), but using list's indexer access to reduce iterations
public static IEnumerable<T> TakeFrom<T>(this List<T> source, int index)
{
for(int i = index; i < source.Count; i++)
{
yield return source[i];
}
}
//similar to list.Take(i), but using list's indexer access to reduce iterations
public static IEnumerable<T> TakeUntil<T>(this List<T> source, int index)
{
for(int i = 0; i < index; i++)
{
yield return source[i];
}
}
Used as:
List<int> myList = new List<int>(){1, 2, 3, 4, 5};
foreach(IEnumerable<int> rotation in myList.Rotate())
{
//do something with that rotation
}
How about this:
var output = input.Skip(rot)
.Take(input.Count - rot)
.Concat(input.Take(rot))
.ToList();
Where rot is the number of spots to rotate - which must be less than the number of elements in the input list.
As #cadrell0 answer shows if this is all you do with your list, you should use a queue instead of a list.
My solution maybe too basic (I wouldn't like to say it's lame...) and not LINQ'ish.
However, it has a pretty good performance.
int max = 5; //the fixed size of your array.
int[] inArray = new int[5] {0,0,0,0,0}; //initial values only.
void putValueToArray(int thisData)
{
//let's do the magic here...
Array.Copy(inArray, 1, inArray, 0, max-1);
inArray[max-1] = thisData;
}
Try
List<int> nums = new List<int> {1,2,3,4,5};
var newNums = nums.Skip(1).Take(nums.Count() - 1).ToList();
newNums.Add(nums[0]);
Although, I like Jon Skeet's answer better.
My solution for Arrays:
public static void ArrayRotate(Array data, int index)
{
if (index > data.Length)
throw new ArgumentException("Invalid index");
else if (index == data.Length || index == 0)
return;
var copy = (Array)data.Clone();
int part1Length = data.Length - index;
//Part1
Array.Copy(copy, 0, data, index, part1Length);
//Part2
Array.Copy(copy, part1Length, data, 0, index);
}
I've used the following extensions for this:
static class Extensions
{
public static IEnumerable<T> RotateLeft<T>(this IEnumerable<T> e, int n) =>
n >= 0 ? e.Skip(n).Concat(e.Take(n)) : e.RotateRight(-n);
public static IEnumerable<T> RotateRight<T>(this IEnumerable<T> e, int n) =>
e.Reverse().RotateLeft(n).Reverse();
}
They're certainly easy (OP title request), and they've got reasonable performance (OP write-up request). Here's a little demo I ran in LINQPad 5 on an above-average-powered laptop:
void Main()
{
const int n = 1000000;
const int r = n / 10;
var a = Enumerable.Range(0, n);
var t = Stopwatch.StartNew();
Console.WriteLine(a.RotateLeft(r).ToArray().First());
Console.WriteLine(a.RotateLeft(-r).ToArray().First());
Console.WriteLine(a.RotateRight(r).ToArray().First());
Console.WriteLine(a.RotateRight(-r).ToArray().First());
Console.WriteLine(t.ElapsedMilliseconds); // e.g. 236
}
You can use below code for left Rotation.
List<int> backUpArray = array.ToList();
for (int i = 0; i < array.Length; i++)
{
int newLocation = (i + (array.Length - rotationNumber)) % n;
array[newLocation] = backUpArray[i];
}
You can play nice in .net framework.
I understand that what you want to do is more up to be an iteration behavior than a new collection type; so I would suggest you to try this extension method based on IEnumerable, which will work with Collections, Lists and so on...
class Program
{
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7 };
IEnumerable<int> circularNumbers = numbers.AsCircular();
IEnumerable<int> firstFourNumbers = circularNumbers
.Take(4); // 1 2 3 4
IEnumerable<int> nextSevenNumbersfromfourth = circularNumbers
.Skip(4).Take(7); // 4 5 6 7 1 2 3
}
}
public static class CircularEnumerable
{
public static IEnumerable<T> AsCircular<T>(this IEnumerable<T> source)
{
if (source == null)
yield break; // be a gentleman
IEnumerator<T> enumerator = source.GetEnumerator();
iterateAllAndBackToStart:
while (enumerator.MoveNext())
yield return enumerator.Current;
enumerator.Reset();
if(!enumerator.MoveNext())
yield break;
else
yield return enumerator.Current;
goto iterateAllAndBackToStart;
}
}
Reasonable performance
Flexible
If you want go further, make a CircularList and hold the same enumerator to skip the Skip() when rotating like in your sample.
below is my approach. Thank you
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
public static int[] RightShiftRotation(int[] a, int times) {
int[] demo = new int[a.Length];
int d = times,i=0;
while(d>0) {
demo[d-1] = a[a.Length - 1 - i]; d = d - 1; i = i + 1;
}
for(int j=a.Length-1-times;j>=0;j--) { demo[j + times] = a[j]; }
return demo;
}
Using Linq,
List<int> temp = new List<int>();
public int[] solution(int[] array, int range)
{
int tempLength = array.Length - range;
temp = array.Skip(tempLength).ToList();
temp.AddRange(array.Take(array.Length - range).ToList());
return temp.ToArray();
}
If you're working with a string you can do this quite efficiently using ReadOnlySpans:
ReadOnlySpan<char> apiKeySchema = "12345";
const int apiKeyLength = 5;
for (int i = 0; i < apiKeyLength; i++)
{
ReadOnlySpan<char> left = apiKeySchema.Slice(start: i, length: apiKeyLength - i);
ReadOnlySpan<char> right = apiKeySchema.Slice(start: 0, length: i);
Console.WriteLine(string.Concat(left, right));
}
Output:
12345
23451
34512
45123
51234
I was asked to reverse a character array with minimal memory usage.
char[] charArray = new char[]{'C','o','w','b','o','y'};
Method:
static void Reverse(ref char[] s)
{
for (int i=0; i < (s.Length-i); i++)
{
char leftMost = s[i];
char rightMost = s[s.Length - i - 1];
s[i] = rightMost;
s[s.Length - i - 1] = leftMost;
}
}
How about using modular arithmetic :
public void UsingModularArithmetic()
{
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int k = Convert.ToInt32(tokens_n[1]);
int[] a = new int[n];
for(int i = 0; i < n; i++)
{
int newLocation = (i + (n - k)) % n;
a[newLocation] = Convert.ToInt32(Console.ReadLine());
}
foreach (int i in a)
Console.Write("{0} ", i);
}
So basically adding the values to the array when I am reading from console.
I started learning algorithms and I am trying to implement Quicksort in C#.
This is my code:
class QuickSortDemo
{
public void Swap(ref int InputA, ref int InputB)
{
InputA = InputA + InputB;
InputB = InputA - InputB;
InputA = InputA - InputB;
}
public int Partition(int[] InputArray, int Low, int High)
{
int Pivot = InputArray[Low];
int LoopVariable1 = Low - 1;
int LoopVariable2 = High + 1;
while (true)
{
while (InputArray[--LoopVariable2] > Pivot) ;
while (InputArray[++LoopVariable1] < Pivot) ;
if (LoopVariable1 < LoopVariable2)
{
Swap(ref InputArray[LoopVariable1], ref InputArray[LoopVariable2]);
for (int LoopVariable = Low; LoopVariable <= High; LoopVariable++)
{
Console.Write(InputArray[LoopVariable] + " ");
}
Console.WriteLine();
}
else
{
for (int LoopVariable = Low; LoopVariable <= High; LoopVariable++)
{
Console.Write(InputArray[LoopVariable] + " ");
}
Console.WriteLine();
return LoopVariable2;
}
}
}
public void QuickSort(int[] InputArray,int Low, int High)
{
if (Low < High)
{
int Mid = Partition(InputArray, Low, High);
QuickSort(InputArray, Low, Mid);
QuickSort(InputArray, Mid + 1, High);
}
}
public static void Main()
{
int[] InputArray = { 10, 5, 6, 8, 23, 19, 12, 17 };
QuickSortDemo Demo = new QuickSortDemo();
for (int LoopVariable = 0; LoopVariable < InputArray.Length; LoopVariable++)
{
Console.Write(InputArray[LoopVariable]+" ");
}
Console.WriteLine();
Demo.QuickSort(InputArray, 0, InputArray.Length - 1);
for (int LoopVariable = 0; LoopVariable < InputArray.Length; LoopVariable++)
{
Console.Write(InputArray[LoopVariable] + " ");
}
Console.WriteLine();
}
}
For some reason I can't get this to work when I take the rightmost element in the array as pivot. I don't know what I am doing wrong. It would be really helpful if someone could explain me why this doesn't work when I take my rightmost element as the pivot. From what I learned, this should work for any input and any pivot element. Correct me if I am wrong.
Thank you.
I'm still not entirely sure I understand the question. But I was able to reproduce a problem (infinite recursion) when I change the line of code in the Partition() method from int pivot = inputArray[low]; to int pivot = inputArray[high];, and doing so seems consistent with your narrative:
I can't get this to work when I take the rightmost element in the array as pivot.
If I've understood the question correctly, then the basic problem is that when you change where you get the pivot, you also need to take this into account when returning the new mid-point. Currently, you return loopVariable2, which is correct when picking the pivot from the lower end of the array. But if you switch to picking the pivot from the upper end of the array, you need to return loopVariable2 - 1.
Another problem is that as you are scanning, you unconditionally increment or decrement the respective "loop variable", regardless of whether the current index is already at an element in the wrong partition. You need to check the current element position first, and only adjust the index if that element is in the correct partition.
Here is a correct version of the Partition() method where the pivot is selected using high instead of low:
public int Partition(int[] inputArray, int low, int high)
{
int pivot = inputArray[high];
int loopVariable1 = low;
int loopVariable2 = high;
while (true)
{
while (inputArray[loopVariable2] > pivot) loopVariable2--;
while (inputArray[loopVariable1] < pivot) loopVariable1++;
if (loopVariable1 < loopVariable2)
{
Swap(ref inputArray[loopVariable1], ref inputArray[loopVariable2]);
for (int loopVariable = low; loopVariable <= high; loopVariable++)
{
Console.Write(inputArray[loopVariable] + " ");
}
Console.WriteLine();
}
else
{
for (int loopVariable = low; loopVariable <= high; loopVariable++)
{
Console.Write(inputArray[loopVariable] + " ");
}
Console.WriteLine();
return loopVariable2 - 1;
}
}
}
In either case, note that the effect is to ensure that regardless of the pivot value selected, you always partition the array in such a way to ensure that a new pivot is always selected with each level of recursion, preventing the infinite loop.
By the way, and for what it's worth, I would not implement Swap() as you have. It's an interesting gimmick to do a no-temp-variable swap, but there is no practical benefit to doing so, while it does incur a significant code maintenance and comprehension cost. In addition, it will only work with integral numeric types; what if you want to extend your sort implementation to handle other types? E.g. ones that implement IComparable or where you allow the caller to provide an IComparer implementation?
IMHO a better Swap() method looks like this:
public void Swap<T>(ref T inputA, ref T inputB)
{
T temp = inputA;
inputA = inputB;
inputB = temp;
}
quick sort:
static public int Partition(int [] numbers, int left, int right)
{
int pivot = numbers[left];
while (true)
{
while (numbers[left] < pivot)
left++;
while (numbers[right] > pivot)
right--;
if (left < right)
{
int temp = numbers[right];
numbers[right] = numbers[left];
numbers[left] = temp;
}
else
{
return right;
}
}
}
static public void QuickSort_Recursive(int [] arr, int left, int right)
{
// For Recusrion
if(left < right)
{
int pivot = Partition(arr, left, right);
if(pivot > 1)
QuickSort_Recursive(arr, left, pivot - 1);
if(pivot + 1 < right)
QuickSort_Recursive(arr, pivot + 1, right);
}
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am applying the QuickSort algorithm from book introduction to Algorithm i wrote the code,but the output is not sorted correctly
Following is the algorithm
Quicksort(A, p, r)
{
if (p < r)
{
q = Partition(A, p, r)
Quicksort(A, p, q-1)
Quicksort(A, q+1, r)
}
}
Partition(A, p, r)
{
pivot = A[r]
i = p - 1
for j = p to r – 1
{
do if A[j] <= pivot
then
{
i = i + 1
exchange A[i] A[j]
}
}
exchange A[i+1] A[r]
return i+1
}
and here is my code
class Threads<T>
{
static bool IsLessThan(T x, T y)
{
if (((IComparable)(x)).CompareTo(y)<=0)
{
return true;
}
else {
return false;
}
}
public int Partition(T[] myarray, int low, int high)
{
T x = myarray[high];
T y;
int i = low - 1;
int j;
for (j = low; j < high - 1; j++)
{
//**************Added Text after edit,I forgot to put this
if (IsLessThan(myarray[j], x))
{
i++;
y = myarray[i];
myarray[i] = myarray[j];
myarray[j] = y;
}
}
y = myarray[i+1];
myarray[i+1] = myarray[high];
myarray[high] = y;
return i + 1;
}
public void QuickSort(T[] myarray, int low, int high)
{
if (low < high)
{
// int q = Partition(myarray,highh, low);
int q = Partition(myarray,low, high);
QuickSort(myarray, low, q - 1);
QuickSort(myarray, q + 1, high );
}
}
}
Following code shows, how the quicksort method is used
private void button1_Click(object sender, EventArgs e)
{
int[] myarray ={9,8,7,6,5,4,3,2};
textBox1.Text = "";
Threads<int> t1 = new Threads<int>();
t1.QuickSort(myarray, 0, myarray.Length-1);
for(int i=0;i<myarray.Length;i++)
textBox1.Text=textBox1.Text+" , "+myarray[i];
}
I get the Following output when i execute the program
8 , 7 , 6 , 5 , 4 , 3 , 9 , 2
Answer
value of i must be one less than j and low at start in the Partition function
I forgot to Swap myarray[i+1] and myarray[high] outside the loops in Partition Function.
Now the code is working accurately fine for strings ,int ,char etc
Try this:
public int Partition(T []myarray, int low, int high)
{
T x = myarray[high];
int i=low;
int j=high;
while(i< j)
{
while(i<j&& IsLessThan(myarray[i], x))
i++;
myarray[j]=myarray[i];
while(i<j&& IsLessThan(x,myarray[j]))
j--;
myarray[i]=myarray[j];
}
myarray[i] = myarray[high];
return i ;
}
Try some changes and debug your code
I tried following
private static int Partition(int[] input, int left, int right)
{
int pivot = input[right];
int temp;
int i = left;
for (int j = left; j < right; j++)
{
if (input[j] <= pivot)
{
temp = input[j];
input[j] = input[i];
input[i] = temp;
i++;
}
}
input[right] = input[i];
input[i] = pivot;
return i;
}
if Pivot element is middle element
private static List<int> QuickSort(List<int> a, int left, int right)
{
int i = left;
int j = right;
double pivotValue = ((left + right) / 2);
int x = a[Convert.ToInt32(pivotValue)];
int w = 0;
while (i <= j)
{
while (a[i] < x)
{
i++;
}
while (x < a[j])
{
j--;
}
if (i <= j)
{
w = a[i];
a[i++] = a[j];
a[j--] = w;
}
}
if (left < j)
{
QuickSort(a, left, j);
}
if (i < right)
{
QuickSort(a, i, right);
}
return a;
}
First this part looked plain wrong, but even after changing the sort doesn't work
int q = Partition(myarray, high, low);
Low and high should be changed
int q = Partition(myarray, low, high);
I think this question is less about an algorithm, and more about the methods of debugging one. So I used a Quicksort algorithm I found online and tried to implement it in C#. I had problems of my own, but debugged it fairly quickly. The code below has some useful techniques to help with debugging. (The algorithm came from http://rosettacode.org/wiki/Sorting_algorithms/Quicksort.)
Here are my general comments when comparing your code:
It was confusing having an array of ints to test with when dealing with integer indices as well, so I changed my array to strings.
I used a lot of Console.WriteLine so I could trace the steps the algorithm was taking. That's what quickly helped me find that low/high issue.
I didn't not use a variable named i as anything but a for loop index. That's just confusing as all heck to use it as anything else -- don't do that!
Since every QuickSort algortithm had multiple swaps I created a Swap function. Even if you only do it once in your code, it clutters up the purpose of the Partition method to have such a trival pattern in there. To put this another way, why did it make sense for you to make IsLessThan a method but not Swap?
Speaking about IsLessThan, technically you actually wrote a method for IsLessThanOrEqual. Don't name things incorrectly, because if somebody uses that and assumes it is just for Less Then, they'll have a hard time when they have unpredictable results. IsLSE would be understandable by most.
Your for loop is the only place you use the variable j so why declare it outside of the for statement? Just adds an extra line and variable in a scope you don't need it.
Here's my QuickSort. It appears to work:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
string[] myarray = { "g", "b", "e", "f", "a", "d", "c"};
QuickSort<string> t1 = new QuickSort<string>();
t1.Sort(myarray, 0, myarray.Length - 1);
}
}
public class QuickSort<T>
{
static int Compare (T x, T y)
{
return ((IComparable)(x)).CompareTo(y);
}
private void Swap(T[] myarray, int i, int j)
{
// swapping indices just for writeline purposes
if (i > j)
{
int t = i;
i = j;
j = t;
}
Console.WriteLine("Swap: {0}:{1} with {2}:{3}",
i, myarray[i], j, myarray[j]);
T temp = myarray[i];
myarray[i] = myarray[j];
myarray[j] = temp;
Console.WriteLine("Result: {0}", String.Join(",", myarray));
}
private int Partition(T[] myarray, int low, int high, int pivotIndex)
{
T pivotVal = myarray[pivotIndex];
Swap(myarray, pivotIndex, high);
int currentLow = low;
while (low <= high) {
while (Compare(myarray[low], pivotVal) < 0) {
low++;
}
while (Compare(myarray[high], pivotVal) > 0) {
high--;
}
if (low <= high) {
Swap(myarray, low, high);
low++;
high--;
}
}
return low;
}
public void Sort(T[] myarray, int low, int high)
{
if (low < high)
{
Console.WriteLine(("Start: {0}", String.Join(",", myarray));
int pivotIndex = (low + high) / 2;
Console.WriteLine("QuickSort: P: {0}, L: {1}, H: {2}",
pivotIndex, low, high);
pivotIndex = Partition(myarray, low, high, pivotIndex);
Sort(myarray, low, pivotIndex - 1);
Sort(myarray, pivotIndex + 1, high);
}
}
}
Lists say I have a list List<int> {1,2,3,4,5}
Rotate means:
=> {2,3,4,5,1} => {3,4,5,1,2} => {4,5,1,2,3}
Maybe rotate is not the best word for this, but hope you understand what I means
My question, whats the easiest way (in short code, c# 4 Linq ready), and will not be hit by performance (reasonable performance)
Thanks.
List<T>
The simplest way (for a List<T>) is to use:
int first = list[0];
list.RemoveAt(0);
list.Add(first);
Performance is nasty though - O(n).
Array
This is basically equivalent to the List<T> version, but more manual:
int first = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = first;
LinkedList<T>
If you could use a LinkedList<T> instead, that would be much simpler:
int first = linkedList.First;
linkedList.RemoveFirst();
linkedList.AddLast(first);
This is O(1) as each operation is constant time.
Queue<T>
cadrell0's solution of using a queue is a single statement, as Dequeue removes the element and returns it:
queue.Enqueue(queue.Dequeue());
While I can't find any documentation of the performance characteristic of this, I'd expect Queue<T> to be implemented using an array and an index as the "virtual starting point" - in which case this is another O(1) solution.
Note that in all of these cases you'd want to check for the list being empty first. (You could deem that to be an error, or a no-op.)
You could implement it as a queue. Dequeue and Enqueue the same value.
**I wasn't sure about performance in converting a List to a Queue, but people upvoted my comment, so I'm posting this as an answer.
I use this one:
public static List<T> Rotate<T>(this List<T> list, int offset)
{
return list.Skip(offset).Concat(list.Take(offset)).ToList();
}
It seems like some answerers have treated this as a chance to explore data structures. While those answers are informative and useful, they are not very Linq'ish.
The Linq'ish approach is: You get an extension method which returns a lazy IEnumerable that knows how to build what you want. This method doesn't modify the source and should only allocate a copy of the source if necessary.
public static IEnumerable<IEnumerable<T>> Rotate<T>(this List<T> source)
{
for(int i = 0; i < source.Count; i++)
{
yield return source.TakeFrom(i).Concat(source.TakeUntil(i));
}
}
//similar to list.Skip(i-1), but using list's indexer access to reduce iterations
public static IEnumerable<T> TakeFrom<T>(this List<T> source, int index)
{
for(int i = index; i < source.Count; i++)
{
yield return source[i];
}
}
//similar to list.Take(i), but using list's indexer access to reduce iterations
public static IEnumerable<T> TakeUntil<T>(this List<T> source, int index)
{
for(int i = 0; i < index; i++)
{
yield return source[i];
}
}
Used as:
List<int> myList = new List<int>(){1, 2, 3, 4, 5};
foreach(IEnumerable<int> rotation in myList.Rotate())
{
//do something with that rotation
}
How about this:
var output = input.Skip(rot)
.Take(input.Count - rot)
.Concat(input.Take(rot))
.ToList();
Where rot is the number of spots to rotate - which must be less than the number of elements in the input list.
As #cadrell0 answer shows if this is all you do with your list, you should use a queue instead of a list.
My solution maybe too basic (I wouldn't like to say it's lame...) and not LINQ'ish.
However, it has a pretty good performance.
int max = 5; //the fixed size of your array.
int[] inArray = new int[5] {0,0,0,0,0}; //initial values only.
void putValueToArray(int thisData)
{
//let's do the magic here...
Array.Copy(inArray, 1, inArray, 0, max-1);
inArray[max-1] = thisData;
}
Try
List<int> nums = new List<int> {1,2,3,4,5};
var newNums = nums.Skip(1).Take(nums.Count() - 1).ToList();
newNums.Add(nums[0]);
Although, I like Jon Skeet's answer better.
My solution for Arrays:
public static void ArrayRotate(Array data, int index)
{
if (index > data.Length)
throw new ArgumentException("Invalid index");
else if (index == data.Length || index == 0)
return;
var copy = (Array)data.Clone();
int part1Length = data.Length - index;
//Part1
Array.Copy(copy, 0, data, index, part1Length);
//Part2
Array.Copy(copy, part1Length, data, 0, index);
}
I've used the following extensions for this:
static class Extensions
{
public static IEnumerable<T> RotateLeft<T>(this IEnumerable<T> e, int n) =>
n >= 0 ? e.Skip(n).Concat(e.Take(n)) : e.RotateRight(-n);
public static IEnumerable<T> RotateRight<T>(this IEnumerable<T> e, int n) =>
e.Reverse().RotateLeft(n).Reverse();
}
They're certainly easy (OP title request), and they've got reasonable performance (OP write-up request). Here's a little demo I ran in LINQPad 5 on an above-average-powered laptop:
void Main()
{
const int n = 1000000;
const int r = n / 10;
var a = Enumerable.Range(0, n);
var t = Stopwatch.StartNew();
Console.WriteLine(a.RotateLeft(r).ToArray().First());
Console.WriteLine(a.RotateLeft(-r).ToArray().First());
Console.WriteLine(a.RotateRight(r).ToArray().First());
Console.WriteLine(a.RotateRight(-r).ToArray().First());
Console.WriteLine(t.ElapsedMilliseconds); // e.g. 236
}
You can use below code for left Rotation.
List<int> backUpArray = array.ToList();
for (int i = 0; i < array.Length; i++)
{
int newLocation = (i + (array.Length - rotationNumber)) % n;
array[newLocation] = backUpArray[i];
}
You can play nice in .net framework.
I understand that what you want to do is more up to be an iteration behavior than a new collection type; so I would suggest you to try this extension method based on IEnumerable, which will work with Collections, Lists and so on...
class Program
{
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7 };
IEnumerable<int> circularNumbers = numbers.AsCircular();
IEnumerable<int> firstFourNumbers = circularNumbers
.Take(4); // 1 2 3 4
IEnumerable<int> nextSevenNumbersfromfourth = circularNumbers
.Skip(4).Take(7); // 4 5 6 7 1 2 3
}
}
public static class CircularEnumerable
{
public static IEnumerable<T> AsCircular<T>(this IEnumerable<T> source)
{
if (source == null)
yield break; // be a gentleman
IEnumerator<T> enumerator = source.GetEnumerator();
iterateAllAndBackToStart:
while (enumerator.MoveNext())
yield return enumerator.Current;
enumerator.Reset();
if(!enumerator.MoveNext())
yield break;
else
yield return enumerator.Current;
goto iterateAllAndBackToStart;
}
}
Reasonable performance
Flexible
If you want go further, make a CircularList and hold the same enumerator to skip the Skip() when rotating like in your sample.
below is my approach. Thank you
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
public static int[] RightShiftRotation(int[] a, int times) {
int[] demo = new int[a.Length];
int d = times,i=0;
while(d>0) {
demo[d-1] = a[a.Length - 1 - i]; d = d - 1; i = i + 1;
}
for(int j=a.Length-1-times;j>=0;j--) { demo[j + times] = a[j]; }
return demo;
}
Using Linq,
List<int> temp = new List<int>();
public int[] solution(int[] array, int range)
{
int tempLength = array.Length - range;
temp = array.Skip(tempLength).ToList();
temp.AddRange(array.Take(array.Length - range).ToList());
return temp.ToArray();
}
If you're working with a string you can do this quite efficiently using ReadOnlySpans:
ReadOnlySpan<char> apiKeySchema = "12345";
const int apiKeyLength = 5;
for (int i = 0; i < apiKeyLength; i++)
{
ReadOnlySpan<char> left = apiKeySchema.Slice(start: i, length: apiKeyLength - i);
ReadOnlySpan<char> right = apiKeySchema.Slice(start: 0, length: i);
Console.WriteLine(string.Concat(left, right));
}
Output:
12345
23451
34512
45123
51234
I was asked to reverse a character array with minimal memory usage.
char[] charArray = new char[]{'C','o','w','b','o','y'};
Method:
static void Reverse(ref char[] s)
{
for (int i=0; i < (s.Length-i); i++)
{
char leftMost = s[i];
char rightMost = s[s.Length - i - 1];
s[i] = rightMost;
s[s.Length - i - 1] = leftMost;
}
}
How about using modular arithmetic :
public void UsingModularArithmetic()
{
string[] tokens_n = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(tokens_n[0]);
int k = Convert.ToInt32(tokens_n[1]);
int[] a = new int[n];
for(int i = 0; i < n; i++)
{
int newLocation = (i + (n - k)) % n;
a[newLocation] = Convert.ToInt32(Console.ReadLine());
}
foreach (int i in a)
Console.Write("{0} ", i);
}
So basically adding the values to the array when I am reading from console.
The method should work like Math.Max(), but take 3 or more int parameters.
You could use Enumerable.Max:
new [] { 1, 2, 3 }.Max();
Well, you can just call it twice:
int max3 = Math.Max(x, Math.Max(y, z));
If you find yourself doing this a lot, you could always write your own helper method... I would be happy enough seeing this in my code base once, but not regularly.
(Note that this is likely to be more efficient than Andrew's LINQ-based answer - but obviously the more elements you have the more appealing the LINQ approach is.)
EDIT: A "best of both worlds" approach might be to have a custom set of methods either way:
public static class MoreMath
{
// This method only exists for consistency, so you can *always* call
// MoreMath.Max instead of alternating between MoreMath.Max and Math.Max
// depending on your argument count.
public static int Max(int x, int y)
{
return Math.Max(x, y);
}
public static int Max(int x, int y, int z)
{
// Or inline it as x < y ? (y < z ? z : y) : (x < z ? z : x);
// Time it before micro-optimizing though!
return Math.Max(x, Math.Max(y, z));
}
public static int Max(int w, int x, int y, int z)
{
return Math.Max(w, Math.Max(x, Math.Max(y, z)));
}
public static int Max(params int[] values)
{
return Enumerable.Max(values);
}
}
That way you can write MoreMath.Max(1, 2, 3) or MoreMath.Max(1, 2, 3, 4) without the overhead of array creation, but still write MoreMath.Max(1, 2, 3, 4, 5, 6) for nice readable and consistent code when you don't mind the overhead.
I personally find that more readable than the explicit array creation of the LINQ approach.
Linq has a Max function.
If you have an IEnumerable<int> you can call this directly, but if you require these in separate parameters you could create a function like this:
using System.Linq;
...
static int Max(params int[] numbers)
{
return numbers.Max();
}
Then you could call it like this: max(1, 6, 2), it allows for an arbitrary number of parameters.
As generic
public static T Min<T>(params T[] values) {
return values.Min();
}
public static T Max<T>(params T[] values) {
return values.Max();
}
off topic but here is the formula for middle value.. just in case someone is looking for it
Math.Min(Math.Min(Math.Max(x,y), Math.Max(y,z)), Math.Max(x,z));
Let's assume that You have a List<int> intList = new List<int>{1,2,3} if You want to get a max value You could do
int maxValue = intList.Max();
Maximum element value in priceValues[] is maxPriceValues :
double[] priceValues = new double[3];
priceValues [0] = 1;
priceValues [1] = 2;
priceValues [2] = 3;
double maxPriceValues = priceValues.Max();
If, for whatever reason (e.g. Space Engineers API), System.array has no definition for Max nor do you have access to Enumerable, a solution for Max of n values is:
public int Max(int[] values) {
if(values.Length < 1) {
return 0;
}
if(values.Length < 2) {
return values[0];
}
if(values.Length < 3) {
return Math.Max(values[0], values[1]);
}
int runningMax = values[0];
for(int i=1; i<values.Length - 1; i++) {
runningMax = Math.Max(runningMax, values[i]);
}
return runningMax;
}
You could try this code:
private float GetBrightestColor(float r, float g, float b) {
if (r > g && r > b) {
return r;
} else if (g > r && g > b) {
return g;
} else if (b > r && b > g) {
return b;
}
}
This function takes an array of integers. (I completely understand #Jon Skeet's complaint about sending arrays.)
It's probably a bit overkill.
public static int GetMax(int[] array) // must be a array of ints
{
int current_greatest_value = array[0]; // initializes it
for (int i = 1; i <= array.Length; i++)
{
// compare current number against next number
if (i+1 <= array.Length-1) // prevent "index outside bounds of array" error below with array[i+1]
{
// array[i+1] exists
if (array[i] < array[i+1] || array[i] <= current_greatest_value)
{
// current val is less than next, and less than the current greatest val, so go to next iteration
continue;
}
} else
{
// array[i+1] doesn't exist, we are at the last element
if (array[i] > current_greatest_value)
{
// current iteration val is greater than current_greatest_value
current_greatest_value = array[i];
}
break; // next for loop i index will be invalid
}
// if it gets here, current val is greater than next, so for now assign that value to greatest_value
current_greatest_value = array[i];
}
return current_greatest_value;
}
Then call the function :
int highest_val = GetMax (new[] { 1,6,2,72727275,2323});
// highest_val = 72727275
You can use if and else if method for three values but it would be much easier if you call call twice Math.Max method like this
Console.WriteLine("Largest of three: " + Math.Max(num1, Math.Max(num2, num3)));
Console.WriteLine("Lowest of three: " + Math.Min(num1, Math.Min(num2, num3)));
If you don't want to repeatedly calling the Max function, can do like this
new List<int>() { A, B, C, D, X, Y, Z }.Max()
in case you need sorting as well:
var side = new double[] {5,3,4}
Array.Sort(side);
//side[2] is a maximum
as an another variant:
T[] GetMax<T>(int number, List<T> source, T minVal)
{
T[] results = new T[number];
for (int i = 0; i < number; i++)
{
results[i] = minVal;
}
var curMin = minVal;
foreach (var e in source)
{
int resComp = Comparer.DefaultInvariant.Compare(curMin, e);
if (resComp < 0)
{
int minIndex = Array.IndexOf(results, curMin);
results[minIndex] = e;
curMin = results.Min();
}
}
return results;
}
var source = new int[] { 5, 5, 1, 2, 4, 3 }.ToList();
var result = GetMax(3, source, int.MinValue);