I have a set of numbers in the form of { -1, 0, +1 } which I have to iterate over using two loops, much like you would when using a 2D array.
The whole set then becomes every combination of the numbers above:
{ -1, -1 } -> { +1, +1 }, which is 9 in total.
However, the set { 0, 0 } I have to skip. Normally I would just check with an if statement, but using this inside two nested loops will make it check for this condition on every run.
Is there an efficient way to somehow do this?
UPDATE: I feel this deserves a little more detail, because there might be a completely different solution this problem than what I want to do above.
It is basicly to check adjacent cells within an array. So { 0, 0 } is cell we are checking, but I wish to check every cell adjacent to it, not including the main cell.
Imagine we had a 2D array int[,] array = new int[,] { ... };
If we then access the array at any index approximately in the middle of it (not close to any edge index; like the bottom/top row or bottom/top column), our conceptual bird's eye view of the array would look like this:
[-1, -1] [-1, 0] [-1, +1]
[0, -1] [0, 0] [0, +1]
[+1, -1] [+1, 0] [+1, +1]
[0,0] is our current element. We can access every adjacent element/cell using the above numbers for [row,column].
A typical loop to do this would look like this:
for (int i = row-1; i <= row+1; ++i) {
for (int j = col-1; j <= col+1; ++j) {
if (i == row && j == col) continue;
...
}
}
Can we avoid the if statement?
After your edit, it seems you don't need loops at all and your desired result has 8 well defined elements.
So you coud simply create a little method that gives you all adjacent cells to your main cell:
Point[] GetAdjacentPoints(Point p)
{
return new[]{
new Point { X = p.X - 1, Y = p.Y - 1 },
new Point { X = p.X, Y = p.Y - 1 },
new Point { X = p.X + 1, Y = p.Y - 1 },
new Point { X = p.X - 1, Y = p.Y },
// leave out p itself
new Point { X = p.X + 1, Y = p.Y },
new Point { X = p.X - 1, Y = p.Y + 1},
new Point { X = p.X, Y = p.Y + 1},
new Point { X = p.X + 1, Y = p.Y + 1}
};
}
(I assume Point to be something like struct Point {public int X {get;set;} public int Y {get;set;}} or any other type to hold two integers).
You can use this method like this:
foreach(Point adjacent in GetAdjacentPoints(new Point {X = 0, Y = 0})
Console.WriteLine($"X: {adjacent.X} Y: {adjacent.Y}");
Output:
X: -1 Y: -1
X: 0 Y: -1
X: 1 Y: -1
X: -1 Y: 0
X: 1 Y: 0
X: -1 Y: 1
X: 0 Y: 1
X: 1 Y: 1
Just compute every single pair and then remove the one pair you want to exclude from your final set. [well implemented] Sets are specifically designed for efficient removal (more efficient than linear anyway, O(1) for hash based sets, O(log(n)) for tree based sets), so that will be faster than checking every single value in the set, which is what you would be doing by having the check in your loop.
I suggest you measure it first and see if this is really a problem, because depending on the type of collection you're using, the Add operation may be more costly than the if statement (in my case below, it consists of creating a new list and then adding that list to another list).
For example, using a List<int> to hold the original set, and a List<List<int>> to hold the combinations, I find that using the if statement is faster than not using it (and if we don't use it then we still need to iterate over the pairs to find the ones we want to remove).
Below is the test I ran, using loops with the if and without the if, with 2001 items in the set (from -1000 to 1000), which creates a total of 4004000 sets. I ran the tests in a loop 100 times and displayed the average time in an attempt to get the most accurate result:
private static void Main()
{
var items = Enumerable.Range(-1000, 2001).ToList();
var combinations = new List<List<int>>();
var withIfCount = new List<long>();
var withoutIfCount = new List<long>();
var sw = new Stopwatch();
// Both test are run 100 times
for (int count = 0; count < 100; count++)
{
sw.Restart();
for (int outer = 0; outer < items.Count; outer++)
{
for (int inner = 0; inner < items.Count; inner++)
{
if (outer == 0 && inner == 0) continue;
combinations.Add(new List<int> {outer, inner});
}
}
sw.Stop();
withIfCount.Add(sw.ElapsedMilliseconds);
combinations.Clear();
sw.Restart();
for (int outer = 0; outer < items.Count; outer++)
{
for (int inner = 0; inner < items.Count; inner++)
{
combinations.Add(new List<int> {outer, inner});
}
}
sw.Stop();
withoutIfCount.Add(sw.ElapsedMilliseconds);
combinations.Clear();
}
// Display averages
Console.WriteLine("Average time with 'if': " + withIfCount.Average());
Console.WriteLine("Average time without 'if': " + withoutIfCount.Average());
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output
Related
So I've implemented a BFS algorithm and I can successfully get the amount of steps it took in order to get from A -> B where A is the top left most coordinate, and B is the bottom left most coordinate.
In my Grid Binary Matrix I have 2 different values.
0 which is "Traversable".
1 which is "Non Traversable"
And in my Visited grid I also change values that I've visited to 2. I was going to try to use the 2 to show the path I took by looking up the coordinate of each value that was 2 but that would only show me everything that I've visited and not the shortest path.
Take this grid for instance
int[][] grid = new[]
{
new int[] { 0, 0, 0, 0},
new int[] { 1, 1, 0, 0},
new int[] { 1, 0, 0, 0},
new int[] { 1, 1, 0, 0}
};
There are two paths which can be built which are considered the shortest
Either way, the result is 5 which my implementation prints out.
I want to print out the actual path it found, for instance, if the algorithm were to take the path shows in the first image, it would print out 0,0 - 0,1 - 1,2 - 2,2 - 3,3.
I'm thinking that I need to keep track of the parent node every time I visit a node, in order to know where I came from, but I'm not sure how I would do that.
Here's my implementation
int[][] dirs = new[]
{
new[] { 0, 1 }, //Bottom
new[] { 1, 1 }, //Bottom right
new[] { 1, 0 }, //Right
new[] { 1, -1 }, //Top right
new[] { 0, -1 }, //Top
new[] { -1, -1 }, //Top left
new[] { -1, 0 }, //Left
new[] { -1, 1 } //Bottom left
};
public int BinaryMatrix(int[][] grid)
{
/* Length of the rows */
var rowLength = grid.Length;
/* The length of each col */
var colLength = grid[0].Length;
/* Can't find a path */
if (grid[0][0] == 1 || grid[rowLength - 1][colLength - 1] == 1)
return -1;
var Queue = new Queue<int[]>(); /* Coordinates */
/* Make a copy of the grid on order to update and perform checks without manipulating the original one. */
int[][] visited = new int[rowLength][];
for (int i = 0; i < visited.Length; i++)
visited[i] = new int[colLength];
Queue.Enqueue(new[] { 0, 0 });
visited[0][0] = 2;
int steps = 1;
while (Queue.Count != 0)
{
int levelSize = Queue.Count;
for (int r = 0; r < levelSize; r++)
{
int[] coord = Queue.Dequeue();
var cy = coord[0]; /* Y */
var cx = coord[1]; /* X */
/* If what we just popped has the same coordinates as the destination */
if (cy == rowLength - 1 && cx == colLength - 1)
{
/* Traceback */
return steps;
}
for (int i = 0; i < dirs.Length; i++)
{
int neighborY = dirs[i][0] + cy;
int neighborX = dirs[i][1] + cx;
/* Bounds check */
if (neighborX >= 0 && neighborX < colLength && neighborY >= 0 && neighborY < rowLength)
{
/* Visited check */
if (visited[neighborY][neighborX] == 0 && grid[neighborY][neighborX] == 0)
{
Queue.Enqueue(new[] { neighborY, neighborX });
visited[neighborY][neighborX] = 2;
}
}
}
}
/* Increment once we're done traversing through a level */
steps++;
}
return -1;
}
I would just use the "visited"-array to keep track of the source node. You could for example store visited[neighborY][neighborX] = i + 2 to keep track of the direction, and then traverse the tree in reverse to build a list of nodes.
Note that I would really recommend creating a Vector2i (i.e. a pair of int) data type to manage coordinates instead of arrays, that should give shorter and easier to understand code. I would also consider using multidimensional arrays, i.e. int[,] instead of jagged, int[][].
Another approach would be to use a Queue<(Vector2i Coordinate, Vector2i[] Path)> to store the paths explicitly. That would require more memory, but for small data sets the memory usage should be irrelevant.
I have been trying for days to find a solution for this problem using c#. I was able to sort them by length but I cannot figure out the solution to sort the array by from their left-most to their right-most.
The hint they gave is to define a class Sequence to hold a sequence of elements. We will implement IComparable<Sequence> to compare sequences by length in decreasing order (and by elements in decreasing order when the length is the same). Later we will use our TreeMultiSet class. Inside we will keep the first 10 sub-sequences of S, i.e. multi-set of the lucky sub-sequences of P, kept in decreasing order by length (and in decreasing order of their content when the length is the same). When we have 10 sub-sequences inside the multi-set and we add 11th sequence, it would take its correct place in the order, because of the IComparable<Sequence> defined. After that we can delete the 11th subsequence, because it is not amongst the first 10
Here is the problem:
We are given a sequence P containing L integers L (1 < L < 50,000) and a number N. We call a “lucky sub-sequence within P” every subsequence of integers from P with a sum equal to N. Imagine we have a sequence S, holding all the lucky sub-sequences of P, kept in decreasing order by their length. When the length is the same, the sequences are ordered in decreasing order by their elements: from the leftmost to the rightmost. Write a program to return the first 10 elements of S
Example: We are given N = 5 and the sequence P = {1, 1, 2, 1, -1, 2, 3, -1, 1, 2, 3, 5, 1, -1, 2, 3}. The sequence S consists of the following 13 sub-sequences of P:
[1, -1, 2, 3, -1, 1]
[1, 2, 1, -1, 2]
[3, -1, 1, 2]
[2, 3, -1, 1]
[1, 1, 2, 1]
[1, -1, 2, 3]
[1, -1, 2, 3]
[-1, 1, 2, 3]
[5, 1, -1]
[2, 3]
[2, 3]
[2, 3]
[5]
My solution:
Actually, when reading the hint I was not able to understand the idea so I came up with another way.
class Find
{
//Function to manually create an array with N elements
public static int[] ArrCreate(int n, int[] Arr)
{
for (int i = 0; i < n; i++)
{
Arr[i] = Convert.ToInt32(Console.ReadLine());
}
return Arr;
}
//Create a Dictionary class type to hold sub-array with sum of sub-array equal to given number k
public static Dictionary<int, ArrayList> SubSeqEqual2N()
{
Console.WriteLine("Input k: ");
int k = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Input n element to create an Array: ");
int n = Convert.ToInt32(Console.ReadLine());
int[] Arr = new int[n];
int[] newArr = ArrCreate(n, Arr);
int keyIndex = 0;
//ArrayList arlist = new ArrayList();
Dictionary<int, ArrayList> SeqofLuckyArr = new Dictionary<int, ArrayList> { };
//Create a loop to find sub-array with the sum equal to given number K.
for (int i = 0; i < newArr.Length; i++)
{
int sum = 0;
for (int j = i; j < newArr.Length; j++)
{
sum = sum + newArr[j];
if (sum == k)
{
//When sub-array with the sum equal to given number K is found then add them into a temp Arraylist, also increment the keyIndex.
keyIndex++;
ArrayList temp = new ArrayList();
for (int ko = i; ko <= j; ko++)
{
temp.Add(newArr[ko]);
}
//DEBUG PURPOSE
/*Console.Write("{");
foreach (var hehe in temp)
{
Console.Write("{0}", string.Join(", ", hehe));
}
Console.Write("}");
Console.WriteLine("");
arlist.AddRange(temp);*/
//Then add that temp array as value into a Dictionary <key,value>type with that KeyIndex.
SeqofLuckyArr.Add(keyIndex,temp);
}
}
}
//DEBUG PURPOSE
//My method to sort the sub-array in the Dictionary by sub-array length and by key index.
foreach(KeyValuePair<int,ArrayList> kvp in SeqofLuckyArr.OrderByDescending(x => x.Value.Count).ThenBy(y => y.Key))
{
Console.Write("Key={0} ",kvp.Key);
Console.Write(",");
Console.Write("Value={ ");
foreach (var hoho in kvp.Value)
{
Console.Write("{0} ", string.Join(", ", hoho));
}
Console.WriteLine("}");
Console.WriteLine("");
arlist.AddRange(kvp.Value);
}
//DEBUG PURPOSE
return SeqofLuckyArr;
}
}
I try to find the sub-array with the sum equal to the given number K first then add them into the Dictionary as value with its key as index. Then sort -sub-array by length use OrderByDecreasing method.
The result:
Key=4 ,Value={ 1 -1 2 3 -1 1 }
Key=2 ,Value={ 1 2 1 -1 2 }
Key=1 ,Value={ 1 1 2 1 }
Key=3 ,Value={ 1 -1 2 3 }
Key=6 ,Value={ 2 3 -1 1 }
Key=7 ,Value={ 3 -1 1 2 }
Key=8 ,Value={ -1 1 2 3 }
Key=12 ,Value={ 1 -1 2 3 }
Key=11 ,Value={ 5 1 -1 }
Key=5 ,Value={ 2 3 }
Key=9 ,Value={ 2 3 }
Key=13 ,Value={ 2 3 }
Key=10 ,Value={ 5 }
But the result is not the same as the example. My problem is that I am stuck at "When the length is the same, the sequences are ordered in decreasing order by their elements: from the leftmost to the rightmost". As I thought left-most to right most is the key index of the sub-array from low to high.
Can anyone help me to find the appropriate way to order the sub-array in decreasing order by the elements? If my edition is not also appropriate to ask on SO I will delete my question.
Thank you!
It seems the problem lies solely in your ordering. The contents of the sequences are identical to the example.
First, the line you are ordering doesn't quite follow the rules specified:
foreach(KeyValuePair<int,ArrayList> kvp in SeqofLuckyArr
.OrderByDescending(x => x.Value.Count)
.ThenBy(y => y.Key))
[...] kept in decreasing order by their length. When the length is the same, the sequences are ordered in decreasing order by their elements: [...]
The first ordering seems correct (OrderByDescending(x => x.Value.Count)) by descending order of the sequences' length. The second ordering is currently ordered by the sequences' "key index" and in ascending order. This should have been in descending/decreasing (ThenByDescending) order based on the contents of the "lucky sub-sequences".
One way you can fix all this is by introducing an IComparer implementation a bit similar to the hint given. The IComparer below is able to take two sequences (int[]) as input and tell which of the two should come before the other (see the documentation for an explanation of what the return value of IComparer.Compare means):
public class IntArrayComparer : IComparer<int[]>
{
public int Compare(int[] x, int[] y)
{
// Ensure we don't get a null-ref exception further down
if (x == null || y == null)
// x should come before (-1) or after (1) y (default ascending order)
return y == null ? -1 : 1;
// If the lengths are different, the length is the first ordering priority
if (x.Length != y.Length)
// Use the built-in 'CompareTo' method for the 'int' type
return x.Length.CompareTo(y.Length);
// Lengths are the same, so we compare the contents
for (var i = 0; i < x.Length; i++)
{
var comparison = x[i].CompareTo(y[i]);
// If the elements in the two seq. are different, we return the ordering
if (comparison != 0)
return comparison;
}
return 0;
}
}
Now the previous mentioned line with your ordering becomes a little simpler (subjective opinion :)):
foreach(KeyValuePair<int,ArrayList> kvp in SeqofLuckyArr
.OrderByDescending(x => x.Value, new IntArrayComparer()))
Check out this fiddle for a test run of the ordering part.
Hint: You actually don't even need to store your subsequences in a Dictionary - a List would suffice.
Sorry for late response. After referring the Imcomparer implementation above. I was able to get the output the same as example. Here is my code for anyone facing the same issues as me.
class Find
{
public static int[] ArrCreate(int n, int[] Arr)
{
for (int i = 0; i < n; i++)
{
Arr[i] = Convert.ToInt32(Console.ReadLine());
}
return Arr;
}
public static void SubSeqEqual2N()
{
Console.WriteLine("Input k: ");
int k = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Input n element to create an Array: ");
int n = Convert.ToInt32(Console.ReadLine());
int[] Arr = new int[n];
int[] newArr = ArrCreate(n, Arr);
//int keyIndex = 0;
//ArrayList arlist = new ArrayList();
//Dictionary<int, ArrayList> SeqofLuckyArr = new Dictionary<int, ArrayList> { };
//Create a List of int array to store
List<int[]> luckyArray = new List<int[]>{ };
for (int i = 0; i < newArr.Length; i++)
{
int sum = 0;
for (int j = i; j < newArr.Length; j++)
{
sum = sum + newArr[j];
if (sum == k)
{
//keyIndex++;
ArrayList temp = new ArrayList();
for (int ko = i; ko <= j; ko++)
{
temp.Add(newArr[ko]);
}
//Convert ArrayList temp into int array for applying IComparer.Compare<Int[],Int[]>
int[] luckySubArray = temp.ToArray(typeof(int)) as int[];
luckyArray.Add(luckySubArray);
//SeqofLuckyArr.Add(keyIndex,temp);
}
}
}
var orderedSeq = luckyArray.OrderByDescending(s => s, new IntArrayComparer());
foreach(var seq in orderedSeq)
{
Console.Write("[ ");
foreach (var i in seq)
{
Console.Write("{0} ", string.Join(", ", i));
}
Console.Write(" ]");
Console.WriteLine("");
}
}
}
public class IntArrayComparer : IComparer<int[]>
{
public int Compare(int[] x, int[] y)
{
// Ensure we don't get a null-ref exception further down
if (x == null || y == null)
// x should come before (-1) or after (1) y (default ascending order)
return y == null ? -1 : 1;
// If the lengths are different, the length is the first ordering priority
if (x.Length != y.Length)
// Use the built-in 'CompareTo' method for the 'int' type
return x.Length.CompareTo(y.Length);
// Lengths are the same, so we compare the contents
for (var i = 0; i < x.Length; i++)
{
var comparison = x[i].CompareTo(y[i]);
// If the elements in the two seq. are different, we return the ordering
if (comparison != 0)
return comparison;
}
return 0;
}
}
And the output:
[ 1 -1 2 3 -1 1 ]
[ 1 2 1 -1 2 ]
[ 3 -1 1 2 ]
[ 2 3 -1 1 ]
[ 1 1 2 1 ]
[ 1 -1 2 3 ]
[ 1 -1 2 3 ]
[ -1 1 2 3 ]
[ 5 1 -1 ]
[ 2 3 ]
[ 2 3 ]
[ 2 3 ]
[ 5 ]
I wish to create a function AllCombnations(d, maxValue) which will create a d-dimensions array of all number combinations from 0 to maxValue.
For example, a hardcoded version of creating all number combinations in 3D space, from 0 to maxValue would possibly be something like:
for (int i = 0; i < maxValue; i++)
for (int j = 0; j < maxValue; j++)
for (int k = 0; k < maxValue; k++)
{
// code here
}
The issue I face is that I cannot nest n for loops, and am unsure how I would go about this. I have considered recursion, but have had no success. Any help would be greatly appreciated.
Actually, you can loop over dimensions. Please, have a look at Array class
Demo:
// [6, 6, 6] array
int rank = 3; // 3D array - 3 dimensions
int maxValue = 6; // Each dimension is of size 6
int[] lengths = Enumerable // {6, 6, 6} - lengths of the dimensions:
.Repeat(maxValue, rank) // rank times maxValue
.ToArray(); // materialized as array
//TODO: put the right type of arrays' items
// In demo, let array be of type string: "string[6, 6, 6] array"
var array = Array.CreateInstance(typeof(string), lengths);
// we can't use hardcoded set (i, j, k) of variables
// we have to address array's item via array of rank length
int[] address = new int[array.Rank];
// Single loop over all array's items (and dimensions)
do {
//TODO: put the right value here by given address:
// (i == address[0], j == address[1], k == address[2] etc.)
array.SetValue(
string.Concat(address.Select(i => (char) (i + 'A'))), // value: "AAA", "AAB" etc.
address); // address: [0,0,0], [0,0,1],
// here we compute next address
for (int i = 0; i < address.Length; ++i)
if (address[i] >= array.GetLength(i) - 1)
address[i] = 0;
else {
address[i] += 1;
break;
}
// if we get {0, 0, ..., 0} address, we've exhausted all the items
}
while (!address.All(index => index == 0));
Let's have a look at the array (20 top items):
Console.WriteLine(string.Join(Environment.NewLine, array.OfType<string>().Take(20)));
Outcome:
AAA
AAB
AAC
AAD
AAE
AAF
ABA
ABB
ABC
ABD
ABE
ABF
ACA
ACB
ACC
ACD
ACE
ACF
ADA
ADB
I know this is an old post now, but I DID create a solution to this problem.
Let me go through this issue with an example script.
class Program
{
static void Main()
{
// Print all combinations from a to b, for n dimensions
// e.g. 0000 to 2222 <- each dimension goes from 0 to 2, with 4 dimensions
// Note that each dimension can have a unique start/end point
// e.g. 1234 to 5678, so the 2nd dimensions is bound 2 <= x <= 6
int dimensions = 4;
int[] startValues = { 0, 0, 0, 0 };
int[] endValues = { 2, 2, 2, 2 };
PrintCombinations(startValues, endValues, dimensions);
Console.ReadKey();
}
/// <summary>
/// Prints all combinations of numbers given inputs
/// </summary>
/// <param name="start">Inclusive stating integers</param>
/// <param name="end">Inclusive ending integers</param>
/// <param name="dimensions">The number of dimensions to iterate</param>
private static void PrintCombinations(int[] startValues, int[] endValues, int dimensions)
{
// Create new array to loop through without disturbing the original array
int[] loopArray = (int[])startValues.Clone();
// Loop through each value
while (!Enumerable.SequenceEqual(loopArray, endValues))
{
// Write array to console
Console.WriteLine($"{string.Join(", ", loopArray)}");
// Increment array
loopArray[0]++;
// Check if a dimension is larger than it's maximum, then set to min, and add +1 to next dimension
// Do not do this for last dimension, as loop will break once the final combination is met
for (int i = 0; i < dimensions - 1; i++)
if (loopArray[i] > endValues[i])
{
loopArray[i] = startValues[i];
loopArray[i + 1]++;
}
}
// Write final array combination to console
Console.WriteLine($"{string.Join(", ", loopArray)}");
}
}
This is a simple enough example to show how exactly I wanted to expand on the idea of "multiple dimensions" represented as an array.
If you look to the bottom of PrintCombinations, you will see the following code:
for (int i = 0; i < dimensions - 1; i++)
if (loopArray[i] > endValues[i])
{
loopArray[i] = startValues[i];
loopArray[i + 1]++;
}
This is the code I come up with the loop through multiple dimensions, removing the need to hard-code loops when you have user submitted dimensions and other information (as shown in the upper example).
Basically, this code stores the VALUE of each dimension in an array.
Let us do an example of 3 dimensions, (x, y, z).
We can say the point (x, y, z) = int[] { x, y, z }
If we say x, y, and z are the upper bound of the array, we can loop through this array by subtracting the array's first dimesnsion, until it reaches zero, then remove one from the following dimension until it reaches zero, etc, all while resetting the dimension to the upper bound when doing so, or as in this example, add from zero to an upper bound, then reset to zero, and increment the following dimension.
By using further arrays for upper and lower bounds, you can essentially make nested loops between two specific ranges. In the above example, I used an upper bound of { 2, 2, 2, 2 }.
I hope I have explained this well. Thanks
I am reading samples from a serial port continously and I want to show the last 400 samples in a graph.
So when the number of received samples becomes 400 I should shift the myPointFsList to left by 1 and add the last received sample
to the end of it. My below code works successfully while the first 400 samples.
List<PointF> myPointFs = new List<PointF>();
uint sampleNumber = 0; PointF Current_PointFs;
private void UpdateVar(object sender, EventArgs e){
...
Current_PointFs = new PointF((float)(sampleNumber), (float)newSample);
if (sampleNumber < 400)
{
myPointFs .Add(Current_PointFs);
++sampleNumber;
}
else
{
myPointFs = myPointFs .ShiftLeft(1); //ShiftLeft is an Extension Method
myPointFs.Add(Current_PointFs);
}
if (myPointFs.Count >= 2)
{
Configure_Graphs();// using Graphics.DrawLines(thin_pen, myPointFs.ToArray()) to draw chart
}
}
But after that the first 400 samples recieved, I need to substract 1 from myPointFs[i].X to shift X-axis to left by 1. Maybe a way is to run a for loop.
How can I implement it? Or is there any more elegant way? Or something that it exists out-of-the-box in C#?
Edit: (To make my question more clear)
myPointFs contains something like this:
myPointFs[0] = {X = 1, Y = 21}
myPointFs[1] = {X = 2, Y = 50}
myPointFs[2] = {X = 3, Y = 56}
now I will remove the first element by shifting left by 1 and add a new sample to the end.
myPointFs[0] = {X = 2, Y = 50}
myPointFs[1] = {X = 3, Y = 56}
myPointFs[2] = {X = 4, Y = 68}
But I need finally something like this:
myPointFs[0] = {X = 1, Y = 50}
myPointFs[1] = {X = 2, Y = 56}
myPointFs[2] = {X = 3, Y = 68}
So, you want to remove the first element and decrement the X value of each remaining point. You can do that in one go:
myPointFs = myPointFs.Skip(1).Select(p => new PointF(p.X-1, p.Y)).ToList();
That is job for Queue<T>. In your case X will be index and Y will be data inserted into Queue.
Here's some code to show how that works:
static void Main(string[] args)
{
var queue = new Queue<int>(10); //Capacity of Queue is 10
Console.WriteLine("=== Writing to Queue ===");
for (int i = 0; i < 23; ++i) //22 rounds for inserting data
{
DequeueIfFull(i, queue);
Console.WriteLine("Inserting number {0} into Queue", i);
queue.Enqueue(i); //Read and remove the first item in Queue
}
FlushQueue(queue); //Last time read all values from queue
Console.ReadKey();
}
private static void DequeueIfFull(int i, Queue<int> queue)
{
var tenthItemInserted = (i != 0) && (i % 10 == 0);
if (tenthItemInserted)
{
Console.WriteLine("Dequeuing from Queue");
for (int j = 0; j < 10; ++j)
{
Console.WriteLine(" Number dequeued on position {0} is {1}", j, queue.Dequeue());
}
}
}
private static void FlushQueue(Queue<int> queue)
{
Console.WriteLine();
Console.WriteLine("=== Reading final Queue state ===");
var index = 0;
foreach (var itemInQueue in queue)
{
Console.WriteLine("At position {0} is number {1} ", index, itemInQueue);
index++;
}
}
Documentation for Queue and link to nice articles about Data Structures.
I'm looking for ideas/code (preferably C#, but other languages work too) to create Ulam's Spiral infinitely large (limited by length of time the program is running, or until stopped).
Now the numbers are all primes so the code for those is rather irrelevant. The interesting part is how to code the arrangement in the evergrowing (infinite) spiral, what kind of data structure is good to support it, and maybe ideas for output (graphics file, text file?).
How would you go about this?
Consider the lengths of each side:
1, 1, 2, 2, 3, 3, 4, 4, ...
The straightforward thing is to iterate over each side, rendering that side.
You can use LOGO style rendering primitives:
Angle = 0;
x=0; y = 0;
int number = 1;
int sideLength = 1;
StartLine();
for (int side = 1; side < maxSize; side++) {
for (int k = 0; k < sideLength; k++) {
Forward(1);
number++;
if (isPrime(number)) {
StopLine();
Ouput(number);
StartLine();
}
}
TurnLeft();
if (side % 2 == 0) sideLength++;
}
You might improve this by only iterating over primes on a side:
The following program works by directly calculating the coordinates of a number. The method NumberToPoint() performs the following mapping.
0 => (x0 , y0 )
1 => (x0 + 1, y0 )
2 => (x0 + 1, y0 - 1)
3 => (x0 , y0 - 1)
4 => (x0 - 1, y0 - 1)
5 => (x0 - 1, y0 )
6 => ...
The rest is a very simple prime number test and a small console application.
In order to save an image I would consider two solutions. If you can create a buffer for the whole image, you can just use the program below to fill the buffer.
If the buffer would be to large, I would create a method PointToNumber() and invert the calculation - the method takes two coordinates and returns the number at this point. With this method you can iterate from top to bottom and left to right and calculate the number at this point, check if it is prime, and output the pixel as you go without a buffer. But for both solutions the image size should be be known before you start, because adding pixels at the top and left is quite expensive (but of cause possible).
Questions
Any good ideas for converting the coefficient lookup in NumberToPoint() into rock solid math without using modulo, integer division, and sign a thousand times?
Any good ideas to shorten or speed up the prime number test?
Code
using System;
using System.Drawing;
using System.Linq;
using System.Threading;
namespace UlamsSpiral
{
public static class Program
{
public static void Main()
{
Int32 width = 60;
Int32 height = 60;
Console.SetWindowSize(Math.Min(width, 120), Math.Min(height, 60));
Console.SetBufferSize(width, height);
Console.CursorVisible = false;
Int32 limit = (Int32)Math.Pow(Math.Min(width, height) - 2, 2);
for (Int32 n = 1; n <= limit; n++)
{
Point point = NumberToPoint(n - 1, width / 2 - 1, height / 2);
Console.ForegroundColor = n.IsPrime() ? ConsoleColor.DarkBlue : ConsoleColor.DarkGray;
Console.SetCursorPosition(point.X, point.Y);
Console.Write('\u25A0');
Console.SetCursorPosition(0, 0);
Console.Write(n);
Thread.Sleep(10);
}
Console.ReadLine();
}
private static Point NumberToPoint(Int32 n, Int32 x0, Int32 y0)
{
Int32[,] c = { { -1, 0, 0, -1, 1, 0 }, { -1, 1, 1, 1, 0, 0 }, { 1, 0, 1, 1, -1, -1 }, { 1, -1, 0, -1, 0, -1 } };
Int32 square = (Int32)Math.Floor(Math.Sqrt(n / 4));
Int32 index;
Int32 side = (Int32)Math.DivRem(n - 4 * square * square, 2 * square + 1, out index);
Int32 x = c[side, 0] * square + c[side, 1] * index + c[side, 2];
Int32 y = c[side, 3] * square + c[side, 4] * index + c[side, 5];
return new Point(x + x0, y + y0);
}
private static Boolean IsPrime(this Int32 n)
{
if (n < 3) return (n == 2);
return Enumerable.Range(2, (Int32)Math.Sqrt(n)).All(m => n % m != 0);
}
}
}
One possible way to do it is to create a linear array or a List to store the numbers and use a formula to determine when the direction needs to change.
As for output, I liked the example on wikipedia of drawing a black pixel for a prime and a white pixel for all other numbers.
Why not have a "generator" process/thread that creates the numbers and a "reader/display" process/thread that displays them, then you can separate the creation from the display and then the program will only really be limited by how much data the "reader/display" consumes. Since i would assume the "generator" needs a fairly constant sized set of data to work with.