Related
How can I quickly shift all the items in an array one to the left, padding the end with null?
For example, [0,1,2,3,4,5,6] would become [1,2,3,4,5,6,null]
Edit: I said quickly but I guess I meant efficiently. I need to do this without creating a List or some other data structure. This is something I need to do several hundred thousand times in as short amount of time as possible.
Here's my test harness...
var source = Enumerable.Range(1, 100).Cast<int?>().ToArray();
var destination = new int?[source.Length];
var s = new Stopwatch();
s.Start();
for (int i = 0; i < 1000000;i++)
{
Array.Copy(source, 1, destination, 0, source.Length - 1);
}
s.Stop();
Console.WriteLine(s.Elapsed);
Here are the performance results for 1 million iterations of each solution (8 Core Intel Xeon E5450 # 3.00GHz)
100 elements 10000 elements
For Loop 0.390s 31.839s
Array.Copy() 0.177s 12.496s
Aaron 1 3.789s 84.082s
Array.ConstrainedCopy() 0.197s 17.658s
Make the choice for yourself :)
The quickest way to do this is to use Array.Copy, which in the final implementation uses a bulk memory transfer operation (similar to memcpy):
var oldArray = new int?[] { 1, 2, 3, 4, 5, 6 };
var newArray = new int?[oldArray.Length];
Array.Copy(oldArray, 1, newArray, 0, oldArray.Length - 1);
// newArray is now { 2, 3, 4, 5, 6, null }
Edited: according to the documentation:
If sourceArray and destinationArray overlap, this method behaves as if the original values of sourceArray were preserved in a temporary location before destinationArray is overwritten.
So if you don't want to allocate a new array, you can pass in the original array for both source and destination--although I imagine the tradeoff will be a somewhat slower performance since the values go through a temporary holding position.
I suppose, as in any investigation of this kind, you should do some quick benchmarking.
Here is my solution, similar to Task's in that it is a simple Array wrapper and that it takes O(1) time to shift the array to the left.
public class ShiftyArray<T>
{
private readonly T[] array;
private int front;
public ShiftyArray(T[] array)
{
this.array = array;
front = 0;
}
public void ShiftLeft()
{
array[front++] = default(T);
if(front > array.Length - 1)
{
front = 0;
}
}
public void ShiftLeft(int count)
{
for(int i = 0; i < count; i++)
{
ShiftLeft();
}
}
public T this[int index]
{
get
{
if(index > array.Length - 1)
{
throw new IndexOutOfRangeException();
}
return array[(front + index) % array.Length];
}
}
public int Length { get { return array.Length; } }
}
Running it through Jason Punyon's test code...
int?[] intData = Enumerable.Range(1, 100).Cast<int?>().ToArray();
ShiftyArray<int?> array = new ShiftyArray<int?>(intData);
Stopwatch watch = new Stopwatch();
watch.Start();
for(int i = 0; i < 1000000; i++)
{
array.ShiftLeft();
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
Takes ~29ms, regardless of the array size.
Use the Array.Copy() method as in
int?[] myArray = new int?[]{0,1,2,3,4};
Array.Copy(myArray, 1, myArray, 0, myArray.Length - 1);
myArray[myArray.Length - 1] = null
The Array.Copy is probably the way, Microsoft wanted us to copy array elements...
Couldn't you use a System.Collections.Generic.Queue instead of an array ?
I feel like you need to perform actions on your value the discard it, thus using a queue seems to be more appropriate :
// dummy initialization
System.Collections.Generic.Queue<int> queue = new Queue<int>();
for (int i = 0; i < 7; ++i ) { queue.Enqueue(i); }// add each element at the end of the container
// working thread
if (queue.Count > 0)
doSomething(queue.Dequeue());// removes the last element of the container and calls doSomething on it
For any pour soul finding this thread and about to implement one of the highly rated answers. All of them are trash, I'm not sure why that is. Maybe Dested asked for a new array implementation at first or something that has now been removed from the question. Well if you simply want to shift the array and don't need a new one, see an answer like tdaines's answer. And read up on things like the Circular Buffer / Ring Buffer : http://en.wikipedia.org/wiki/Circular_buffer. No moving of the actual data is necessary. The performance of shifting an array should not be tied to the size of the array.
If it absolutely has to be in an array, then I would recommend the most obvious code possible.
for (int index = startIndex; index + 1 < values.Length; index++)
values[index] = values[index + 1];
values[values.Length - 1] = null;
This gives the optimizer the most opportunities to find the best way on whatever target platform the program is installed on.
EDIT:
I just borrowed Jason Punyon's test code, and I'm afraid he's right. Array.Copy wins!
var source = Enumerable.Range(1, 100).Cast<int?>().ToArray();
int indexToRemove = 4;
var s = new Stopwatch();
s.Start();
for (int i = 0; i < 1000000; i++)
{
Array.Copy(source, indexToRemove + 1, source, indexToRemove, source.Length - indexToRemove - 1);
//for (int index = indexToRemove; index + 1 < source.Length; index++)
// source[index] = source[index + 1];
}
s.Stop();
Console.WriteLine(s.Elapsed);
Array.Copy takes between 103 and 150 ms on my machine.
for loop takes between 269 and 338 ms on my machine.
Can't you
allocate the array with an extra 1000 elements
have an integer variable int base = 0
instead of accessing a[i] access a[base+i]
to do your shift, just say base++
Then after you've done this 1000 times, copy it down and start over.
That way, you only do the copy once per 1000 shifts.
Old joke:
Q: How many IBM 360s does it take to shift a register by 1 bit?
A: 33. 32 to hold the bits in place, and 1 to move the register. (or some such...)
You can use the same array as source and destination for fast in-place copy:
static void Main(string[] args)
{
int[] array = {0, 1, 2, 3, 4, 5, 6, 7};
Array.ConstrainedCopy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = 0;
}
You might do it like this:
var items = new int?[] { 0, 1, 2, 3, 4, 5, 6 }; // Your array
var itemList = new List<int?>(items); // Put the items in a List<>
itemList.RemoveAt(1); // Remove the item at index 1
itemList.Add(null); // Add a null to the end of the list
items = itemList.ToArray(); // Turn the list back into an array
Of course, it would be more efficient to get rid of the array entirely and just use a List<>. You could then forget the first line and last line and do it like this:
var itemList = new List<int?> { 0, 1, 2, 3, 4, 5, 6 };
itemList.RemoveAt(1); // Remove the item at index 1
itemList.Add(null); // Add a null to the end of the list
The best and most efficient method I believe is using Buffer.BlockCopy function.
You will set both source and destination to your array, the offset of the source is 1. Depending on your array type (I assume it is int), 1 int = 4 bytes, so you must pass in 4 as the second parameter of this function. Note that the offset is byte offset.
So it looks like this:
int bytes2copy = yourArray.length - 4;
Buffer.BlockCopy(yourArray, 4, yourArray, 0, bytes2copy);
yourArray[yourArray.length-1] = null;
Try this! using Linq. No need of second Array.
var i_array = new int?[] {0, 1, 2, 3, 4, 5, 6 };
i_array = i_array.Select((v, k) => new { v = v, k = k }).
Where(i => i.k > 0).Select(i => i.v).ToArray();
Array.Resize(ref i_array, i_array.Length + 1);
Output:
[0,1,2,3,4,5,6] would become [1,2,3,4,5,6,null]
If you own the memory you could consider using Unsafe Code and good old fashioned pointers.
Make yourself a memory stream and lock it down or use Marshal.AllocHGlobal
Construct all your arrays in it with a little bit of padding at the beginning and end.
increment or decrement all of the array pointers at once. You'll still need to loop back and set your nulls.
If you need to selectively increment or decrement the arrays you would have to add padding between them.
Arrays are incredibly low level data structures, if you treat them in a low level way you can get huge performance out of them.
A baytrail doing this could outperform Jason's with all its copying 8 Core Intel Xeon E5450 # 3.00GHz
Not tested this code, but it should shifts all the values to right by one. Note that the last three lines of code is all you require to efficiently shift the array.
public class Shift : MonoBehaviour {
//Initialize Array
public int[] queue;
void Start () {
//Create Array Rows
queue = new int[5];
//Set Values to 1,2,3,4,5
for (int i=0; i<5;i++)
{
queue[i] = i + 1;
}
//Get the integer at the first index
int prev = queue[0];
//Copy the array to the new array.
System.Array.Copy(queue, 1, queue, 0, queue.Length - 1);
//Set the last shifted value to the previously first value.
queue[queue.Length - 1] = prev;
Implementation with Extension methods passing shifting direction as Enum.
"for" statements and indexers only (don't use Array.Copy method).
using System;
namespace ShiftArrayElements
{
public static class EnumShifter
{
public static int[] Shift(int[] source, Direction[] directions)
{
for (var i = 0; i < directions.Length; i++)
{
var direction = directions[i];
if (direction == Direction.Left)
{
source.LeftShift();
}
else if (direction == Direction.Right)
{
source.RightShift();
}
else
{
throw new InvalidOperationException("Direction is invalid");
}
}
return source;
}
public static void LeftShift(this int[] source)
{
var lastIndex = source?.Length - 1 ?? 0;
var temp = source[0];
for (int j = 0; j + 1 < source.Length; j++)
{
source[j] = source[j + 1];
}
source[lastIndex] = temp;
}
public static void RightShift(this int[] source)
{
var lastIndex = source?.Length - 1 ?? 0;
var temp = source[lastIndex];
for (int j = lastIndex; j > 0; j--)
{
source[j] = source[j - 1];
}
source[0] = temp;
}
}
}
Array copying is an O(n) operation and creates a new array.
While array copying can certainly be done quickly and efficiently, the problem you've stated can actually be solved in an entirely different way without (as you've requested) creating a new array/data structure and only creating one small wrapping object instance per array:
using System;
using System.Text;
public class ArrayReindexer
{
private Array reindexed;
private int location, offset;
public ArrayReindexer( Array source )
{
reindexed = source;
}
public object this[int index]
{
get
{
if (offset > 0 && index >= location)
{
int adjustedIndex = index + offset;
return adjustedIndex >= reindexed.Length ? "null" : reindexed.GetValue( adjustedIndex );
}
return reindexed.GetValue( index );
}
}
public void Reindex( int position, int shiftAmount )
{
location = position;
offset = shiftAmount;
}
public override string ToString()
{
StringBuilder output = new StringBuilder( "[ " );
for (int i = 0; i < reindexed.Length; ++i)
{
output.Append( this[i] );
if (i == reindexed.Length - 1)
{
output.Append( " ]" );
}
else
{
output.Append( ", " );
}
}
return output.ToString();
}
}
By wrapping and controlling access to the array in this manner, we can now demonstrate how the problem was solved with an O(1) method call...
ArrayReindexer original = new ArrayReindexer( SourceArray );
Console.WriteLine( " Base array: {0}", original.ToString() );
ArrayReindexer reindexed = new ArrayReindexer( SourceArray );
reindexed.Reindex( 1, 1 );
Console.WriteLine( "Shifted array: {0}", reindexed.ToString() );
Will produce the output:
Base array: [ 0, 1, 2, 3, 4, 5, 6 ]
Shifted array: [ 0, 2, 3, 4, 5, 6, null ]
I'm willing to bet that there will be a reason that such a solution won't work for you, but I believe this does match your initial stated requirements. 8 )
It's often helpful to think about all the different kinds of solutions to a problem before implementing a specific one, and perhaps that might be the most important thing that this example can demonstrate.
Hope this helps!
Incorrect and slightly amusing answer (thanks, i'll be here all night !)
int?[] test = new int?[] {0,1,2,3,4,5,6 };
int?[] t = new int?[test.Length];
t = test.Skip(1).ToArray();
t[t.Length - 1] = null;
In the spirit of still using Skip (dont ask me, i know worst usage of LINQ extension methods ever), the only way I thought of rewriting it would be
int?[] test = new int?[] { 0, 1, 2, 3, 4, 5, 6 };
int?[] t = new int?[test.Length];
Array.Copy(test.Skip(1).ToArray(), t, t.Length - 1);
But it's in NO WAY faster than the other options.
I know this is an old question but coming from Google there was no simple example so thanks to this is the easiest way to reorder a list, and you don't have to supply the type it will work it out at runtime,
private static List<T> reorderList<T>(List<T> list){
List<T> newList = new List<T>();
list.ForEach(delegate(T item)
{
newList.Add(item);
});
return newList;
}
using System;
using System.Threading;
namespace ShiftMatrix
{
class Program
{
static void Main(string[] args)
{
MatrixOperation objMatrixOperation = new MatrixOperation();
//Create a matrix
int[,] mat = new int[,]
{
{1, 2},
{3,4 },
{5, 6},
{7,8},
{8,9},
};
int type = 2;
int counter = 0;
if (type == 1)
{
counter = mat.GetLength(0);
}
else
{
counter = mat.GetLength(1);
}
while (true)
{
for (int i = 0; i < counter; i++)
{
ShowMatrix(objMatrixOperation.ShiftMatrix(mat, i, type));
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
}
public static void ShowMatrix(int[,] matrix)
{
int rows = matrix.GetLength(0);
int columns = matrix.GetLength(1);
for (int k = 0; k < rows; k++)
{
for (int l = 0; l < columns; l++)
{
Console.Write(matrix[k, l] + " ");
}
Console.WriteLine();
}
}
}
class MatrixOperation
{
public int[,] ShiftMatrix(int[,] origanalMatrix, int shift, int type)
{
int rows = origanalMatrix.GetLength(0);
int cols = origanalMatrix.GetLength(1);
int[,] _tmpMatrix = new int[rows, cols];
if (type == 2)
{
for (int x1 = 0; x1 < rows; x1++)
{
int y2 = 0;
for (int y1 = shift; y2 < cols - shift; y1++, y2++)
{
_tmpMatrix[x1, y2] = origanalMatrix[x1, y1];
}
y2--;
for (int y1 = 0; y1 < shift; y1++, y2++)
{
_tmpMatrix[x1, y2] = origanalMatrix[x1, y1];
}
}
}
else
{
int x2 = 0;
for (int x1 = shift; x2 < rows - shift; x1++, x2++)
{
for (int y1 = 0; y1 < cols; y1++)
{
_tmpMatrix[x2, y1] = origanalMatrix[x1, y1];
}
}
x2--;
for (int x1 = 0; x1 < shift; x1++, x2++)
{
for (int y1 = 0; y1 < cols; y1++)
{
_tmpMatrix[x2, y1] = origanalMatrix[x1, y1];
}
}
}
return _tmpMatrix;
}
}
}
See C# code below to remove space from string. That shift character in array. Performance is O(n). No other array is used. So no extra memory either.
static void Main(string[] args)
{
string strIn = System.Console.ReadLine();
char[] chraryIn = strIn.ToCharArray();
int iShift = 0;
char chrTemp;
for (int i = 0; i < chraryIn.Length; ++i)
{
if (i > 0)
{
chrTemp = chraryIn[i];
chraryIn[i - iShift] = chrTemp;
chraryIn[i] = chraryIn[i - iShift];
}
if (chraryIn[i] == ' ') iShift++;
if (i >= chraryIn.Length - 1 - iShift) chraryIn[i] = ' ';
}
System.Console.WriteLine(new string(chraryIn));
System.Console.Read();
}
a is array of ints & d is number of times array has to shift left.
static int[] rotLeft(int[] a, int d)
{
var innerLoop = a.Length - 1;
for(var loop=0; loop < d; loop++)
{
var res = a[innerLoop];
for (var i= innerLoop; i>=0; i--)
{
var tempI = i-1;
if (tempI < 0)
{
tempI = innerLoop;
}
var yolo = a[tempI];
a[tempI] = res;
res = yolo;
}
}
return a;
}
Simple way to do it when you need to resize the same array.
var nLength = args.Length - 1;
Array.Copy(args, 1, args, 0, nLength);
Array.Resize(ref args, nLength);
Okay, I know that this code is crude, and all around a messy, but I am no programmer, so bear with me. I have this code that lists a bunch of numbers, but I want it to not list any circular copies of the numbers.
For example, if the number 111262 is on my list, I don't want 112621, 126211, 262111, 621112, or 211126 to be listed.
Sorry, that number cannot be on the list.
For a true example, if the number 111252 is on my list, I don't want 112521, 125211, 252111, 521112, or 211125 to be listed.
Any help is appreciated!
namespace Toric_Classes
{
class Program
{
static void Main(string[] args)
{
int number_of_perms=0;
bool badsubsum1;
bool badsubsum2;
int subsum1 = 0;
int subsum2 = 0;
int sum = 0;
int class_length=6;
int[] toric_class=new int[class_length];
// The nested for loops scroll through every possible number of length class_length, where each digit can have a value of 1,2,..., or class_length-1
// Each number is looked at as an array, and is not stored anywhere, only printed if it satisfies certain conditions
for(int i1=1; i1<class_length; i1++)
{
toric_class[0] = i1;
for (int i2 = 1; i2 < class_length; i2++)
{
toric_class[1] = i2;
for (int i3 = 1; i3 < class_length; i3++)
{
toric_class[2] = i3;
for (int i4 = 1; i4 < class_length; i4++)
{
toric_class[3] = i4;
for (int i5 = 1; i5 < class_length; i5++)
{
toric_class[4] = i5;
for (int i6 = 1; i6 < class_length; i6++)
{
badsubsum1 = false;
badsubsum2 = false;
toric_class[5] = i6;
// Find the value of the sum of the digits of our array.
// We only want numbers that have a total digit sum being a multiple of class_length
for (int k = 0; k < class_length; k++)
{
sum += toric_class[k];
}
// The follwong two nested loops find the value of every contiguous subsum of our number, but not the total subsum.
// We *do not* want any subsum to be a multiple of class_length.
// That is, if our number is, say, 121342, we want to find 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
// The following checks 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 1+3, 1+3+4, and 3+4
for (int i = 0; i < class_length - 1; i++)
{
for (int j = i + 1; j < class_length - 1; j++)
{
for (int k = i; k < j; k++)
{
subsum1 += toric_class[k];
}
if (subsum1 % class_length == 0)
{
badsubsum1 = true;
break;
}
subsum1 = 0;
}
}
// The following checks 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
for (int i = 1; i < class_length; i++)
{
for (int j = i + 1; j < class_length; j++)
{
for (int k = i; k < j; k++)
{
subsum2 += toric_class[k];
}
if (subsum2 % class_length == 0)
{
badsubsum2 = true;
break;
}
subsum2 = 0;
}
}
// We only want numbers that satisfies the following conditions
if (sum % class_length == 0 && badsubsum1 == false && badsubsum2 == false)
{
foreach (var item in toric_class)
{
Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
number_of_perms++;
}
sum = 0;
subsum1 = 0;
subsum2 = 0;
}
}
}
}
}
}
Console.WriteLine("Number of Permuatations: "+number_of_perms);
Console.Read();
}
}
}
EDIT
To clarify, I am creating a list of all numbers with length n that satisfy certain conditions. Consider the number d1d2...dn, where each di is a digit of our number. Each di may have value 1,2,...,n. Our number is in the list if it satisfies the following
The sum of all the digits is a multiple of n, that is,
d1+d2+...+dn = 0 mod n
Every contiguous subsum of the digits is not a multiple of n, aside from the total sum, that is, if i !=1 and j != n, then
di+d(i+1)+...+dj != 0 mod n
I should mention again that a "number" does not strictly use the numbers 0-9 in its digits. It may take any value between 1 and n. In my code, I am using the case where n=6.
The code works by creating an array of length class_length (in the code above, I use class_length=6). We first have 6 nested for loops that simply assign values to the array toric_class. The first for assigns toric_class[0], the second for assigns toric_class[1], and so on. In the first go around, we are generating the array 111111, then 111112, up to 111115, then 111121, etc. So essentially, we are looking at all heximal numbers that do not include 0. Once we reach our sixth value in our array, we check the array toric_class and check its values to ensure that it satisfies the above conditions. If it does, we simply print the array in a line, and move on.
Here is my easy and inefficient way that should work with minimal changes to your code. It requires shared string list var strList = new List<string>(); to store the used numbers. Then this part:
foreach (var item in toric_class)
{
Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
number_of_perms++;
becomes something like this:
string strItem = " " + string.Join(" ", toric_class) + " "; // Example: int[] {1, 12, 123} becomes " 1 12 123 "
if (!strList.Any(str => str.Contains(strItem))) // Example: if " 1 12 123 1 12 123 " contains " 1 12 123 "
{
Console.WriteLine(strItem);
strItem += strItem.Substring(1); // double the string, but keep only one space between them
strList.Add(strItem);
}
number_of_perms++; // not sure if this should be in the if statement
The idea is that for example the string " 1 1 1 2 5 2 1 1 1 2 5 2 " contains all circular copies of the numbers {1, 1, 1, 2, 5, 2}. I used string as a lazy way to check if array contains sub-array, but you can use similar approach to store copy of the used numbers in a list of arrays new List<int[]>() and check if any of the arrays in the list is circular copy of the current array, or even better HashSet<int[]>() approach similar to #slavanap's answer.
The first version of my answer was the easiest, but it works only with array of single digit items.
List is almost the same as array (new List<string>() instead of new string[]), but makes it much easier and efficient to add items to it. For example {1,2}.Add(3) becomes {1,2,3}.
str => str.Contains(strItem) is shortcut for a function that accepts parameter str and returns the result of str.Contains(strItem). That "function" is then passed to the .Any LINQ extension, so
strList.Any(str => str.Contains(strItem))
is shortcut for something like this:
foreach(string str in strList)
{
if (str.Contains(strItem))
{
return true;
}
}
return false;
The following method:
private static List<int> GetCircularEquivalents(int value)
{
var circularList = new List<int>();
var valueString = value.ToString();
var length = valueString.Length - 1;
for (var i = 0; i < length; i++)
{
valueString = valueString.Substring(1, length) + valueString.Substring(0, 1);
circularList.Add(int.Parse(valueString));
}
return circularList;
}
will return a list of the circular numbers derived from the input value. Using your example, this method can be called like this:
var circularList = GetCircularEquivalents(111262);
var dirtyList = new List<int> { 1, 112621, 2, 126211, 3, 262111, 4, 621112, 5, 211126, 6 };
var cleanList = dirtyList.Except(circularList).ToList();
which would result in a cleanList made up of the numbers 1 through 6, i.e. the dirtyList with all the circular numbers derived from 111262 removed.
That's where OOP really benefits. Comments inlined.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3 {
struct MyInt : IEquatable<MyInt> {
private int _value;
public MyInt(int value) {
_value = value;
}
// make it look like int
static public implicit operator MyInt(int value) {
return new MyInt(value);
}
public static explicit operator int(MyInt instance) {
return instance._value;
}
// main difference in these 3 methods
private int GetDigitsNum() {
int temp, res;
for (res = 0, temp = Math.Abs(_value); temp > 0; ++res, temp /= 10);
return res;
}
public bool Equals(MyInt other) {
int digits = other.GetDigitsNum();
if (digits != this.GetDigitsNum())
return false;
int temp = other._value;
// prepare mul used in shifts
int mul = 1;
for (int i = 0; i < digits - 1; ++i)
mul *= 10;
// compare
for (int i = 0; i < digits; ++i) {
if (temp == _value)
return true;
// ROR
int t = temp % 10;
temp = temp / 10 + t * mul;
}
return false;
}
public override int GetHashCode() {
// hash code must be equal for "equal" items,
// that's why use a sum of digits.
int sum = 0;
for (int temp = _value; temp > 0; temp /= 10)
sum += temp % 10;
return sum;
}
// be consistent
public override bool Equals(object obj) {
return (obj is MyInt) ? Equals((MyInt)obj) : false;
}
public override string ToString() {
return _value.ToString();
}
}
class Program {
static void Main(string[] args) {
List<MyInt> list = new List<MyInt> { 112621, 126211, 262111, 621112, 211126 };
// make a set of unique items from list
HashSet<MyInt> set = new HashSet<MyInt>(list);
// print that set
foreach(int item in set)
Console.WriteLine(item);
}
}
}
Output:
112621
This Console-application is a bit strange but kinda funny, if it works. First, I'm clocking the time it takes to fill a LinkedList with 4.000.000 elements, with random numbers. Then I'm searching for 100 random elements in that LinkedList. And between this I'm writing out the time it took to fill and find the elements.
After that I'm trying to do the same thing again, but with an Array. First filling it, then looking for 100 random elements. And then I'm sorting the array, to see the difference between looking for 100 random elements in a unsorted vs sorted array. And then typing the time again.
The problem is, after I've filled the LinkedList, and found the elements in the LinkedList, I'm starting to fill the Array with a loop. And I get a infinite loop. I really don't know what's wrong ATM.
I suggest, if you want to help, that you copy the code I'm pasting into this question, so you understand how it should look for all the parts of the program.
Code:
public static bool sokning(int[] a, int b)
{
bool sant = false;
Random rand = new Random();
Stopwatch watchFindArray = new Stopwatch();
Console.Write("Letar efter tal: ");
watchFindArray.Start();
int myint = 0;
for (int iii = 0; iii < a.Length; iii++)
{
b = rand.Next();
Console.Write("#");
myint = Array.BinarySearch(a, b);
if (myint < 0)
{
sant = false;
}
else
{
sant = true;
}
}
watchFindArray.Stop();
if (sant == true)
{
Console.WriteLine("\nFann alla element efter " + watchFindArray.Elapsed.TotalSeconds + " sekunder.");
return true;
}
else
{
return false;
}
}
public static void körMetod()
{
const int MAX = 40000000;
int[] array = new int[MAX];
int hittamig2 = 0;
Random rand2 = new Random();
Stopwatch watchArray = new Stopwatch();
Console.WriteLine("\nStartar Array...");
watchArray.Start();
Console.Write("Position: ");
for (int ii = 0; ii < MAX; ii++)
{
array[ii] = rand2.Next();
if (array.Length % 1000000 == 0)
{
Console.Write("#");
}
}
watchArray.Stop();
Console.WriteLine("\nTid: " + watchArray.Elapsed.TotalSeconds + " sekunder att fylla en array.");
Console.WriteLine("Letar efter tal: ");
bool sant = sokning(array, hittamig2);
Console.WriteLine("Sorterar arrayen.");
Array.Sort(array);
sant = sokning(array, hittamig2);
if (sant == false)
{
Console.WriteLine("\nHittade inte alla element i arrayen.");
Console.ReadLine();
}
else
{
Console.WriteLine("Klar!");
Console.ReadLine();
}
}
static void Main(string[] args)
{
Random rnd = new Random();
const int MAX = 40000000;
LinkedList<int> lankadLista = new LinkedList<int>();
Stopwatch watchLinkedList = new Stopwatch();
Console.WriteLine("Startar LinkedList...");
watchLinkedList.Start();
Console.Write("Position: ");
for (int i = 0; i < MAX; i++)
{
lankadLista.AddLast(rnd.Next());
if (lankadLista.Count() % 1000000 == 0)
{
Console.Write("#");
}
}
watchLinkedList.Stop();
Console.WriteLine("\nTid: " + watchLinkedList.Elapsed.TotalSeconds + " sekunder att fylla en LinkedList.");
Stopwatch watchFindLinkedList = new Stopwatch();
int hittaMig;
Console.Write("Letar efter tal: ");
watchFindLinkedList.Start();
for (int j = 0; j < 100; j++)
{
hittaMig = rnd.Next();
Console.Write("#");
lankadLista.Find(hittaMig);
}
watchFindLinkedList.Stop();
Console.WriteLine("\nFann alla element efter " +
watchFindLinkedList.Elapsed.TotalSeconds + " sekunder.");
Console.ReadLine();
körMetod();
}
Best Regards.
You are not in an infinite loop, the problem is that it the following code:
for (int ii = 0; ii < MAX; ii++)
{
array[ii] = rand2.Next();
if (array.Length % 1000000 == 0)
{
Console.Write("#");
}
}
The inner condition is array.Length % 1000000 == 0 which is always true because the size of array is always 40000000 as you initialized it:
const int MAX = 40000000;
int[] array = new int[MAX];
When you are doing array[ii] = rand2.Next(); you are not changing the length of the array you are just setting one of its cells with a value equals to rand2.Next();.
This causes the Console.Write("#"); to work in every iteration and also slowing your loop dramatically.
To fix this, just change:
if (array.Length % 1000000 == 0)
to:
if (ii % 1000000 == 0)
You don't want to add new item at the end of the array every time because, resizing the array reallocates the array every time which is super slow but you can do it using the Array.Resize method (no reason for you to do it)
I think you have a big problem in the routine that searches the Array. (sokning)
Where is the code that searches for only 100 elements?
It seems that your are searching a random generated number for 40 millions times. Just fixing the Console.Write("#") to write correctly at every million point is not enough. I think that the big delay that let you think to have an infinite loop is in your code that search 40 millions of random generated numbers in an array of 40 millions of numbers
Of course this is not very "responsive" (considering also that you call this method two times)
public static bool sokning(int[] a, int b)
{
bool sant = false;
Random rand = new Random();
Stopwatch watchFindArray = new Stopwatch();
Console.Write("Letar efter tal: ");
watchFindArray.Start();
int myint = 0;
// Search only 100 numbers like you do in the linked list
for (int iii = 0; iii < 100; iii++)
{
b = rand.Next();
Console.Write("#");
myint = Array.BinarySearch(a, b);
if (myint < 0)
{
sant = false;
}
else
{
sant = true;
}
}
watchFindArray.Stop();
if (sant == true)
{
Console.WriteLine("\nFann alla element efter " + watchFindArray.Elapsed.TotalSeconds + " sekunder.");
return true;
}
else
{
return false;
}
}
There are also two minor problems.
Why passing the variable b inside the sokning method? The original value is never used and when you start the loop to search a random generated number the b variable os overwritten. So I think you could remove it
The second problem is the result of this sokning method. You set the sant variable to true or false at every loop. So the latest loop wins. In other words, if the latest loop finds a match you return true or false if not. If some previous loop has a different result, it is totally lost for the callers of sokning.
Trying to build a method that will find the sum of all the values within the 2D array. I'm very new to programming and can't find a good starting point on trying to figure out how its done. Here is what I have so far (forgive me, I'm usually an english/history guy, logic isn't my forte...)
class Program
{
static void Main(string[] args)
{
int[,] myArray = new int[5,6];
FillArray(myArray);
LargestValue(myArray);
}
//Fills the array with random values 1-15
public static void FillArray(int[,] array)
{
Random rnd = new Random();
int[,] tempArray = new int[,] { };
for (int i = 0; i < tempArray.GetLength(0); i++)
{
for (int j = 0; j < tempArray.GetLength(1); j++)
{
tempArray[i, j] = rnd.Next(1, 16);
}
}
}
//finds the largest value in the array (using an IEnumerator someone
//showed me, but I'm a little fuzzy on how it works...)
public static void LargestValue(int[,] array)
{
FillArray(array);
IEnumerable<int> allValues = array.Cast<int>();
int max = allValues.Max();
Console.WriteLine("Max value: " + max);
}
//finds the sum of all values
public int SumArray(int[,] array)
{
FillArray(array);
}
}
I guess I could try to find the sum of each row or column and add them up with a for loop? Add them up and return an int? If anyone could shed any insight, it would be greatly appreciated, thanks!
Firstly, you don't need to call FillArray in the beginning of each method, you have already populated the array in the main method, you are passing a populated array to these other methods.
A loop similar to what you use to populate the array is the easiest to understand:
//finds the sum of all values
public int SumArray(int[,] array)
{
int total = 0;
// Iterate through the first dimension of the array
for (int i = 0; i < array.GetLength(0); i++)
{
// Iterate through the second dimension
for (int j = 0; j < array.GetLength(1); j++)
{
// Add the value at this location to the total
// (+= is shorthand for saying total = total + <something>)
total += array[i, j];
}
}
return total;
}
To sum an array if you know the length is easy
As a bonus code included to get the highest valeu too.
You could easily expand this to get other kinds of statistical code.
I asume below Xlength and Ylength are integers too, and known by you.
You could also replace them by a number in the code.
int total = 0;
int max=0;
int t=0; // temp valeu
For (int x=0;x<Xlength;x++)
{
for (int y=0;y<Ylength;y++)
{
t = yourArray[x,y];
total =total +t;
if(t>max){max=t;} // an if on a single line
}
}
here is a link with an MSDN sample on how to retrieve unknown array lengths.
and there is a nice site to have around when you start in c#
google ".net perls"
How can I quickly shift all the items in an array one to the left, padding the end with null?
For example, [0,1,2,3,4,5,6] would become [1,2,3,4,5,6,null]
Edit: I said quickly but I guess I meant efficiently. I need to do this without creating a List or some other data structure. This is something I need to do several hundred thousand times in as short amount of time as possible.
Here's my test harness...
var source = Enumerable.Range(1, 100).Cast<int?>().ToArray();
var destination = new int?[source.Length];
var s = new Stopwatch();
s.Start();
for (int i = 0; i < 1000000;i++)
{
Array.Copy(source, 1, destination, 0, source.Length - 1);
}
s.Stop();
Console.WriteLine(s.Elapsed);
Here are the performance results for 1 million iterations of each solution (8 Core Intel Xeon E5450 # 3.00GHz)
100 elements 10000 elements
For Loop 0.390s 31.839s
Array.Copy() 0.177s 12.496s
Aaron 1 3.789s 84.082s
Array.ConstrainedCopy() 0.197s 17.658s
Make the choice for yourself :)
The quickest way to do this is to use Array.Copy, which in the final implementation uses a bulk memory transfer operation (similar to memcpy):
var oldArray = new int?[] { 1, 2, 3, 4, 5, 6 };
var newArray = new int?[oldArray.Length];
Array.Copy(oldArray, 1, newArray, 0, oldArray.Length - 1);
// newArray is now { 2, 3, 4, 5, 6, null }
Edited: according to the documentation:
If sourceArray and destinationArray overlap, this method behaves as if the original values of sourceArray were preserved in a temporary location before destinationArray is overwritten.
So if you don't want to allocate a new array, you can pass in the original array for both source and destination--although I imagine the tradeoff will be a somewhat slower performance since the values go through a temporary holding position.
I suppose, as in any investigation of this kind, you should do some quick benchmarking.
Here is my solution, similar to Task's in that it is a simple Array wrapper and that it takes O(1) time to shift the array to the left.
public class ShiftyArray<T>
{
private readonly T[] array;
private int front;
public ShiftyArray(T[] array)
{
this.array = array;
front = 0;
}
public void ShiftLeft()
{
array[front++] = default(T);
if(front > array.Length - 1)
{
front = 0;
}
}
public void ShiftLeft(int count)
{
for(int i = 0; i < count; i++)
{
ShiftLeft();
}
}
public T this[int index]
{
get
{
if(index > array.Length - 1)
{
throw new IndexOutOfRangeException();
}
return array[(front + index) % array.Length];
}
}
public int Length { get { return array.Length; } }
}
Running it through Jason Punyon's test code...
int?[] intData = Enumerable.Range(1, 100).Cast<int?>().ToArray();
ShiftyArray<int?> array = new ShiftyArray<int?>(intData);
Stopwatch watch = new Stopwatch();
watch.Start();
for(int i = 0; i < 1000000; i++)
{
array.ShiftLeft();
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
Takes ~29ms, regardless of the array size.
Use the Array.Copy() method as in
int?[] myArray = new int?[]{0,1,2,3,4};
Array.Copy(myArray, 1, myArray, 0, myArray.Length - 1);
myArray[myArray.Length - 1] = null
The Array.Copy is probably the way, Microsoft wanted us to copy array elements...
Couldn't you use a System.Collections.Generic.Queue instead of an array ?
I feel like you need to perform actions on your value the discard it, thus using a queue seems to be more appropriate :
// dummy initialization
System.Collections.Generic.Queue<int> queue = new Queue<int>();
for (int i = 0; i < 7; ++i ) { queue.Enqueue(i); }// add each element at the end of the container
// working thread
if (queue.Count > 0)
doSomething(queue.Dequeue());// removes the last element of the container and calls doSomething on it
For any pour soul finding this thread and about to implement one of the highly rated answers. All of them are trash, I'm not sure why that is. Maybe Dested asked for a new array implementation at first or something that has now been removed from the question. Well if you simply want to shift the array and don't need a new one, see an answer like tdaines's answer. And read up on things like the Circular Buffer / Ring Buffer : http://en.wikipedia.org/wiki/Circular_buffer. No moving of the actual data is necessary. The performance of shifting an array should not be tied to the size of the array.
If it absolutely has to be in an array, then I would recommend the most obvious code possible.
for (int index = startIndex; index + 1 < values.Length; index++)
values[index] = values[index + 1];
values[values.Length - 1] = null;
This gives the optimizer the most opportunities to find the best way on whatever target platform the program is installed on.
EDIT:
I just borrowed Jason Punyon's test code, and I'm afraid he's right. Array.Copy wins!
var source = Enumerable.Range(1, 100).Cast<int?>().ToArray();
int indexToRemove = 4;
var s = new Stopwatch();
s.Start();
for (int i = 0; i < 1000000; i++)
{
Array.Copy(source, indexToRemove + 1, source, indexToRemove, source.Length - indexToRemove - 1);
//for (int index = indexToRemove; index + 1 < source.Length; index++)
// source[index] = source[index + 1];
}
s.Stop();
Console.WriteLine(s.Elapsed);
Array.Copy takes between 103 and 150 ms on my machine.
for loop takes between 269 and 338 ms on my machine.
Can't you
allocate the array with an extra 1000 elements
have an integer variable int base = 0
instead of accessing a[i] access a[base+i]
to do your shift, just say base++
Then after you've done this 1000 times, copy it down and start over.
That way, you only do the copy once per 1000 shifts.
Old joke:
Q: How many IBM 360s does it take to shift a register by 1 bit?
A: 33. 32 to hold the bits in place, and 1 to move the register. (or some such...)
You can use the same array as source and destination for fast in-place copy:
static void Main(string[] args)
{
int[] array = {0, 1, 2, 3, 4, 5, 6, 7};
Array.ConstrainedCopy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = 0;
}
You might do it like this:
var items = new int?[] { 0, 1, 2, 3, 4, 5, 6 }; // Your array
var itemList = new List<int?>(items); // Put the items in a List<>
itemList.RemoveAt(1); // Remove the item at index 1
itemList.Add(null); // Add a null to the end of the list
items = itemList.ToArray(); // Turn the list back into an array
Of course, it would be more efficient to get rid of the array entirely and just use a List<>. You could then forget the first line and last line and do it like this:
var itemList = new List<int?> { 0, 1, 2, 3, 4, 5, 6 };
itemList.RemoveAt(1); // Remove the item at index 1
itemList.Add(null); // Add a null to the end of the list
The best and most efficient method I believe is using Buffer.BlockCopy function.
You will set both source and destination to your array, the offset of the source is 1. Depending on your array type (I assume it is int), 1 int = 4 bytes, so you must pass in 4 as the second parameter of this function. Note that the offset is byte offset.
So it looks like this:
int bytes2copy = yourArray.length - 4;
Buffer.BlockCopy(yourArray, 4, yourArray, 0, bytes2copy);
yourArray[yourArray.length-1] = null;
Try this! using Linq. No need of second Array.
var i_array = new int?[] {0, 1, 2, 3, 4, 5, 6 };
i_array = i_array.Select((v, k) => new { v = v, k = k }).
Where(i => i.k > 0).Select(i => i.v).ToArray();
Array.Resize(ref i_array, i_array.Length + 1);
Output:
[0,1,2,3,4,5,6] would become [1,2,3,4,5,6,null]
If you own the memory you could consider using Unsafe Code and good old fashioned pointers.
Make yourself a memory stream and lock it down or use Marshal.AllocHGlobal
Construct all your arrays in it with a little bit of padding at the beginning and end.
increment or decrement all of the array pointers at once. You'll still need to loop back and set your nulls.
If you need to selectively increment or decrement the arrays you would have to add padding between them.
Arrays are incredibly low level data structures, if you treat them in a low level way you can get huge performance out of them.
A baytrail doing this could outperform Jason's with all its copying 8 Core Intel Xeon E5450 # 3.00GHz
Not tested this code, but it should shifts all the values to right by one. Note that the last three lines of code is all you require to efficiently shift the array.
public class Shift : MonoBehaviour {
//Initialize Array
public int[] queue;
void Start () {
//Create Array Rows
queue = new int[5];
//Set Values to 1,2,3,4,5
for (int i=0; i<5;i++)
{
queue[i] = i + 1;
}
//Get the integer at the first index
int prev = queue[0];
//Copy the array to the new array.
System.Array.Copy(queue, 1, queue, 0, queue.Length - 1);
//Set the last shifted value to the previously first value.
queue[queue.Length - 1] = prev;
Implementation with Extension methods passing shifting direction as Enum.
"for" statements and indexers only (don't use Array.Copy method).
using System;
namespace ShiftArrayElements
{
public static class EnumShifter
{
public static int[] Shift(int[] source, Direction[] directions)
{
for (var i = 0; i < directions.Length; i++)
{
var direction = directions[i];
if (direction == Direction.Left)
{
source.LeftShift();
}
else if (direction == Direction.Right)
{
source.RightShift();
}
else
{
throw new InvalidOperationException("Direction is invalid");
}
}
return source;
}
public static void LeftShift(this int[] source)
{
var lastIndex = source?.Length - 1 ?? 0;
var temp = source[0];
for (int j = 0; j + 1 < source.Length; j++)
{
source[j] = source[j + 1];
}
source[lastIndex] = temp;
}
public static void RightShift(this int[] source)
{
var lastIndex = source?.Length - 1 ?? 0;
var temp = source[lastIndex];
for (int j = lastIndex; j > 0; j--)
{
source[j] = source[j - 1];
}
source[0] = temp;
}
}
}
Array copying is an O(n) operation and creates a new array.
While array copying can certainly be done quickly and efficiently, the problem you've stated can actually be solved in an entirely different way without (as you've requested) creating a new array/data structure and only creating one small wrapping object instance per array:
using System;
using System.Text;
public class ArrayReindexer
{
private Array reindexed;
private int location, offset;
public ArrayReindexer( Array source )
{
reindexed = source;
}
public object this[int index]
{
get
{
if (offset > 0 && index >= location)
{
int adjustedIndex = index + offset;
return adjustedIndex >= reindexed.Length ? "null" : reindexed.GetValue( adjustedIndex );
}
return reindexed.GetValue( index );
}
}
public void Reindex( int position, int shiftAmount )
{
location = position;
offset = shiftAmount;
}
public override string ToString()
{
StringBuilder output = new StringBuilder( "[ " );
for (int i = 0; i < reindexed.Length; ++i)
{
output.Append( this[i] );
if (i == reindexed.Length - 1)
{
output.Append( " ]" );
}
else
{
output.Append( ", " );
}
}
return output.ToString();
}
}
By wrapping and controlling access to the array in this manner, we can now demonstrate how the problem was solved with an O(1) method call...
ArrayReindexer original = new ArrayReindexer( SourceArray );
Console.WriteLine( " Base array: {0}", original.ToString() );
ArrayReindexer reindexed = new ArrayReindexer( SourceArray );
reindexed.Reindex( 1, 1 );
Console.WriteLine( "Shifted array: {0}", reindexed.ToString() );
Will produce the output:
Base array: [ 0, 1, 2, 3, 4, 5, 6 ]
Shifted array: [ 0, 2, 3, 4, 5, 6, null ]
I'm willing to bet that there will be a reason that such a solution won't work for you, but I believe this does match your initial stated requirements. 8 )
It's often helpful to think about all the different kinds of solutions to a problem before implementing a specific one, and perhaps that might be the most important thing that this example can demonstrate.
Hope this helps!
Incorrect and slightly amusing answer (thanks, i'll be here all night !)
int?[] test = new int?[] {0,1,2,3,4,5,6 };
int?[] t = new int?[test.Length];
t = test.Skip(1).ToArray();
t[t.Length - 1] = null;
In the spirit of still using Skip (dont ask me, i know worst usage of LINQ extension methods ever), the only way I thought of rewriting it would be
int?[] test = new int?[] { 0, 1, 2, 3, 4, 5, 6 };
int?[] t = new int?[test.Length];
Array.Copy(test.Skip(1).ToArray(), t, t.Length - 1);
But it's in NO WAY faster than the other options.
I know this is an old question but coming from Google there was no simple example so thanks to this is the easiest way to reorder a list, and you don't have to supply the type it will work it out at runtime,
private static List<T> reorderList<T>(List<T> list){
List<T> newList = new List<T>();
list.ForEach(delegate(T item)
{
newList.Add(item);
});
return newList;
}
using System;
using System.Threading;
namespace ShiftMatrix
{
class Program
{
static void Main(string[] args)
{
MatrixOperation objMatrixOperation = new MatrixOperation();
//Create a matrix
int[,] mat = new int[,]
{
{1, 2},
{3,4 },
{5, 6},
{7,8},
{8,9},
};
int type = 2;
int counter = 0;
if (type == 1)
{
counter = mat.GetLength(0);
}
else
{
counter = mat.GetLength(1);
}
while (true)
{
for (int i = 0; i < counter; i++)
{
ShowMatrix(objMatrixOperation.ShiftMatrix(mat, i, type));
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
}
public static void ShowMatrix(int[,] matrix)
{
int rows = matrix.GetLength(0);
int columns = matrix.GetLength(1);
for (int k = 0; k < rows; k++)
{
for (int l = 0; l < columns; l++)
{
Console.Write(matrix[k, l] + " ");
}
Console.WriteLine();
}
}
}
class MatrixOperation
{
public int[,] ShiftMatrix(int[,] origanalMatrix, int shift, int type)
{
int rows = origanalMatrix.GetLength(0);
int cols = origanalMatrix.GetLength(1);
int[,] _tmpMatrix = new int[rows, cols];
if (type == 2)
{
for (int x1 = 0; x1 < rows; x1++)
{
int y2 = 0;
for (int y1 = shift; y2 < cols - shift; y1++, y2++)
{
_tmpMatrix[x1, y2] = origanalMatrix[x1, y1];
}
y2--;
for (int y1 = 0; y1 < shift; y1++, y2++)
{
_tmpMatrix[x1, y2] = origanalMatrix[x1, y1];
}
}
}
else
{
int x2 = 0;
for (int x1 = shift; x2 < rows - shift; x1++, x2++)
{
for (int y1 = 0; y1 < cols; y1++)
{
_tmpMatrix[x2, y1] = origanalMatrix[x1, y1];
}
}
x2--;
for (int x1 = 0; x1 < shift; x1++, x2++)
{
for (int y1 = 0; y1 < cols; y1++)
{
_tmpMatrix[x2, y1] = origanalMatrix[x1, y1];
}
}
}
return _tmpMatrix;
}
}
}
See C# code below to remove space from string. That shift character in array. Performance is O(n). No other array is used. So no extra memory either.
static void Main(string[] args)
{
string strIn = System.Console.ReadLine();
char[] chraryIn = strIn.ToCharArray();
int iShift = 0;
char chrTemp;
for (int i = 0; i < chraryIn.Length; ++i)
{
if (i > 0)
{
chrTemp = chraryIn[i];
chraryIn[i - iShift] = chrTemp;
chraryIn[i] = chraryIn[i - iShift];
}
if (chraryIn[i] == ' ') iShift++;
if (i >= chraryIn.Length - 1 - iShift) chraryIn[i] = ' ';
}
System.Console.WriteLine(new string(chraryIn));
System.Console.Read();
}
a is array of ints & d is number of times array has to shift left.
static int[] rotLeft(int[] a, int d)
{
var innerLoop = a.Length - 1;
for(var loop=0; loop < d; loop++)
{
var res = a[innerLoop];
for (var i= innerLoop; i>=0; i--)
{
var tempI = i-1;
if (tempI < 0)
{
tempI = innerLoop;
}
var yolo = a[tempI];
a[tempI] = res;
res = yolo;
}
}
return a;
}
Simple way to do it when you need to resize the same array.
var nLength = args.Length - 1;
Array.Copy(args, 1, args, 0, nLength);
Array.Resize(ref args, nLength);