SOLVED: I figured it out myself. I can't select my answer for 2 days. Thank you everyone!
I have this weird bug. Sometimes my list is 0, when I can't see why. Every time I stepped through the debugger, it worked. It's making me crazy. Please help! This is travelling salesperson branch and bound, by the way.
public static BSSFPair generateBSSF(ref City[] Cities, int numberOfTrials)
{
int n = Cities.Length;
//Declare variable for updating.
double minCostOfBSSF = double.PositiveInfinity;
List<int> minRandomCityOrder = new List<int>();
//Try many random paths, and keep track of the minimum-cost path. Then select the minimum-cost path as the BSSF.
for (int iteration = 0; iteration < numberOfTrials; iteration++)
{
//Choose a random path.
List<int> randomCityOrder = new List<int>(generateRandomOrderInts(n)); //a list of ints of cities. Each city int only occurs once.
//Determine cost of route using the TSPSolution class.
System.Collections.ArrayList cities = new System.Collections.ArrayList(); //a list of City objects
foreach (int i in randomCityOrder)
{
cities.Add(Cities[i]);
}
ProblemAndSolver.TSPSolution bssf = new ProblemAndSolver.TSPSolution(cities);
double costOfBSSF = bssf.costOfRoute();
//Update the minimums.
if (costOfBSSF < minCostOfBSSF)
{
minCostOfBSSF = costOfBSSF;
minRandomCityOrder = new List<int>(randomCityOrder);
}
}
//return the path and the cost of the BSSF.
//<---- This is where the method with the bug was called.
return new BSSFPair(minCostOfBSSF, convertCityListToEdges(minRandomCityOrder)); //<---- THIS IS WHERE THE METHOD WITH THE BUG WAS CALLED.
}
This method is where the error happens:
/// <summary>
/// Converts a list of cities (WITHOUT THE LAST CITY BEING A DUPLICATE OF THE FIRST CITY) to a list of edges
/// (WITH THE LAST EDGE GOING BACK TO THE START OF THE FIRST EDGE because it wraps around so you can easily draw it).
/// </summary>
/// <param name="minRandomCityOrder"></param>
/// <returns></returns>
public static List<Edge> convertCityListToEdges(List<int> minRandomCityOrder)
{
if(minRandomCityOrder.Count < 2)
{
//Right here->
throw new NotImplementedException(); //<------- RIGHT HERE. minRandomCityOrder count is 0. How did that happen?
}
int n = minRandomCityOrder.Count;
//Convert the BSSF path to a list of edges.
List<Edge> newBssfPath = new List<Edge>();
int prev = minRandomCityOrder[0];
for (int i = 1; i < n; i++)
{
newBssfPath.Add(new Edge(prev, minRandomCityOrder[i]));
prev = minRandomCityOrder[i];
}
//Add edge from end to start.
newBssfPath.Add(new Edge(minRandomCityOrder[n - 1], minRandomCityOrder[0]));
return newBssfPath;
}
Utility function called by the code below. I've tested this myself, and it never returns an empty list.
/// <summary>
/// Generate a list of ints in the range [0, (maximum-1)] (Inclusive) in a random order. Each int occurs only once in the list.
/// </summary>
/// <param name="maximum"> "maximum" is the upper bound, and is not included in the list.</param>
/// <returns>the random-ordered list.</returns>
private static List<int> generateRandomOrderInts(int maximum)
{
if (maximum < 1)
{
throw new NotImplementedException();
}
Random random = new Random();
List<int> intsToAdd = new List<int>();
List<int> randomOrderList = new List<int>();
for (int i = 0; i < maximum; i++)
{
intsToAdd.Add(i);
}
while (intsToAdd.Count > 0)
{
//Returns a random int between 0 and n-1, inclusive.
int randomInt = random.Next(intsToAdd.Count);
randomOrderList.Add(intsToAdd[randomInt]);
intsToAdd.RemoveAt(randomInt);
}
return randomOrderList;
}
I found out what was wrong. In this method:
public static BSSFPair generateBSSF(ref City[] Cities, int numberOfTrials)
{
int n = Cities.Length;
//Declare variable for updating.
double minCostOfBSSF = double.PositiveInfinity;
List<int> minRandomCityOrder = new List<int>();//<--------------here
...
It starts as empty. The problem is that this assumes that the minimum (which is initialized to infinity) will be updated, and then the minRandomCityOrder will get a new list initialized to it. But, if I randomly pick paths that have a cost of infinity, then it will never be updated.
So, this is what fixed my code:
public static BSSFPair generateBSSF(ref City[] Cities, int numberOfTrials)
{
int n = Cities.Length;
//Declare variable for updating.
double minCostOfBSSF = double.PositiveInfinity;
List<int> minRandomCityOrder = new List<int>(generateRandomOrderInts(n)); //<---fixed
...
Now, if it doesn't update the best solution so far, it won't break the code and will just have a garbage path to calculate.
I guess this condition is true and your list gets resetted:
//Update the minimums.
if (costOfBSSF < minCostOfBSSF)
{
minCostOfBSSF = costOfBSSF;
minRandomCityOrder = new List<int>(randomCityOrder);
}
it does not mean that you are initializing the list with randomCityOrder-number of items but that the list has this initial capacity. If you want to have that number of items you might try:
minRandomCityOrder = Enumerable.Range(0, randomCityOrder).ToList();
...but I don't know if it makes sense in your algorithm. I'm just showing what's possible.
Related
Hi guys im trying to learn permutation and recurtion. And im looking for a way how can i use bought at the same time.
MAIN:
namespace Recursive_Permutation
{
class Program
{
static void Main(string[] args)
{
int[] array = new int[5] { 0, 0, 0, 0, 0 };
CalPermutations CP = new CalPermutations();
CP.Run(array, array.Length-1);
}
}
}
Here is my Simple code:
namespace Recursive_Permutation
{
public class CalPermutations
{
public int Run(int[] array,int indexer)
{
if (indexer > array.Length)
{
return 1;
}
else
{
for (int i = 0; i <= array.Length; i++)
{
array[indexer] = i;
Display(array);
}
Run(array, indexer-1);
}
return indexer;
}
public void Display(int[] array)
{
foreach (int num in array)
{
Console.Write(num);
}
Console.WriteLine();
}
}
}
And here is the Output of the program:
Question:
it might be simple to other but im kind of confuse now in how can i manipulate it that it still count the first digit (position [0]) 1 to 5 and go next position and (position 1) and add 1 and go back to [0] and start count again till it reaches 5.
i hope that my explanation is understandable.. thx.
I put together this simpler example of using recursion and permutation. It uses strings internally, but produces the same result.
Its for proof of concept only, since nobody will us recursion for this simple stuff in a professional environment. Recursion can have a big memory impact, but makes describing some problems in a simple way possible.
If I had to choose between iterative and recursive solutions, I would take the iterative one most of the time.
// Main entrance
public void DoStuff()
{
// define variations
List<string> possibilities = new List<string>() { "0", "1", "2", "3", "4", "5" };
// resultlist, will be filled later
List<string> permutations = new List<string>();
// how many values will be taken from the possibilities
int digits = 5;
//do the work
Permute(permutations, possibilities, digits, "");
// display the work
foreach (var item in permutations)
{
Console.WriteLine(item);
}
}
/// <summary>
/// generates a List of permuted strings
/// </summary>
/// <param name="permutations">resultlist</param>
/// <param name="possibilities">possible values of the digit</param>
/// <param name="digitsLeft">how many digits shall be appended</param>
/// <param name="current">the current value of the unfinished result</param>
private void Permute(List<string> permutations, List<string> possibilities, int digitsLeft, string current)
{
// uncomment to see how it works in detail
//Console.WriteLine("step:"+current);
// most important: define Stop conditions for the recursion
// safety stop
if (digitsLeft < 0)
{// end of digits :), normally we never end up here
return;
}
// normal stop
if (digitsLeft == 0)
{// normal endpoint, add the found permutation to the resultlist
permutations.Add(current);
return;
}
// now prepare the recursion, try each possibility
foreach (var item in possibilities)
{
// digitsLeft need to be decreased, since we add a concrete digit to the current value (current+item)
// important: (current + item) generates a new string in memory, the old values won't be touched, permutations possibilities are references, so no memory impact here
Permute(permutations, possibilities, digitsLeft - 1, current + item);
}
}
Update: added comments on each method as per comment.
public class Program
{
public static void Main(string[] args)
{
int[] array = new int[] { 0, 0, 0, 0, 0};
CalPermutations CP = new CalPermutations();
CP.Run(array, 0);
}
}
public class CalPermutations
{
// Prints all the permutations of array, starting at the specified index.
public void Run(int[] array, int indexer)
{
if (indexer < 0 || indexer >= array.Length)
return;
// Keep [0, indexer] combination constant, change combination on right i.e. (indexer, Array.length).
Run(array, indexer+1);
// All the elements on right have finished, increment current element.
array[indexer]++;
// Check if current combination is STILL valid.
if(array[indexer] <= array.Length)
{
// since current combination is still valid, display it, and execute the process again on the new combination.
Display(array);
Run(array, indexer);
}
else
{
// Since current element is out of range, reset it.
array[indexer] = 1;
}
}
// Prints all the elements in array.
public void Display(int[] array)
{
foreach (int num in array)
Console.Write(num);
Console.WriteLine();
}
}
I'm making a basic Deal or No Deal game, in doing so I have to pick 10 finalists from an array, at random, without repeats.
I have my structure and arrays set out like this
public struct People
{
public string firstname;
public string lastname;
public int age;
}
class Program
{
public static People[] People1 = new People[40];
public static People[] Finalists1 = new People[10];
public static People[] Finalist1 = new People[1];
And my finalists method set out like this
Random rand = new Random();
for (int i = 0; i < Finalists1.Length; i++)
{
num = rand.Next(0, People1.Length);
Finalists1[i].lastname = People1[num].lastname;
Finalists1[i].firstname = People1[num].firstname;
Finalists1[i].age = People1[num].age;
}
How can I eliminate duplicate entries, while maintaining 10 people in the array?
Since initial array doesn't contain duplicates, you can sort it in random order and pick up 10 top items:
Finalists1 = People1
.OrderByDescending(item => 1) // if people have some points, bonuses etc.
.ThenBy(item => Guid.NewGuid()) // shuffle among peers
.Take(10) // Take top 10
.ToArray(); // materialize as an array
If people are selected to the final are not completely random (e.g. contestant can earn points, bonuses etc.) change .OrderByDescending(item => 1), e.g.
.OrderByDescending(item => item.Bonuses)
If you don't want to use Linq, you can just draw Peoples from urn without returning:
private static Random random = new Random();
...
List<People> urn = new List<People>(People1);
for (int i = 0; i < Finalists1.Length; ++i) {
int index = random.Next(0, urn.Count);
Finalists1[i] = urn[index];
urn.RemoveAt(index);
}
You can hold a list or hash set of numbers you have already drawn. Then just roll the dice again to get another random number.
Random rand = new Random();
HashSet<int> drawnNumbers = new HashSet<int>();
for (int i = 0; i < Finalists1.Length; i++)
{
do
{
num = rand.Next(0, People1.Length);
}
while (drawnNumbers.Contains(num));
Finalists1[i] = People1[num];
}
You can change the type of Finalists1 to a HashSet, that does not allow duplicates.
Then change your loop to
while(Finalists1.Length < 10)
{
// random pick from array People1 (you don't need to create a new one)
num = rand.Next(0, People1.Length);
var toAdd = People1[num];
// add to hash-set. Object won't be added, if already existing in the set
Finalists1.Add(toAdd);
}
You probably need to override the Equals method of class People, if you really need to create a new object to add to the hash-set.
You can group people array and select distinct that way.
If you use List you can remove person from the list
`var peopleArray = new People[40];
var peopleCollection = peopleArray.GroupBy(p => new { p.age, p.firstname, p.lastname }).Select(grp => grp.FirstOrDefault()).ToList();
var finalists = new People[10];
var rand = new Random();
for (var i = 0; i < finalists.Length; i++)
{
var index = rand.Next(0, peopleCollection.Count);
var person = peopleCollection[index];
finalists[i].lastname = person.lastname;
finalists[i].firstname = person.firstname;
finalists[i].age = person.age;
peopleCollection.Remove(person);
}
shuffle and take the first 10, for example
People1.Shuffle();
Finalists1= People1.Take(10).ToArray();
you can find shuffle code from StackOverflow or search for "Fisher-Yates shuffle C#" Below methods are taken from This SO Post. Read the answers for more information on why GUID is not used etc..
public static class ThreadSafeRandom
{
[ThreadStatic] private static Random Local;
public static Random ThisThreadsRandom
{
get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
}
}
static class MyExtensions
{
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
Swap each selected element in People1 to with the end of the array, and decrement an end-of-array index so that you're only selecting from what's left on the next iteration.
People tempPerson = new People;
int lastElem = People1.length - 1;
for (int i = 0; i < Finalists1.Length; i++)
{
num = rand.Next(0, lastElem + 1);
Finalists1[i] = People1[num];
//swap last entry in People1 with People1[num]
tempPerson = People1[num];
People1[num] = People1[lastElem];
People1[lastElem] = tempPerson;
lastElem--;
}
Sorry if there's a syntax error, I'm mostly using Java and C# these days.
BTW You don't have to set the fields individually since each array stores objects of type Person.
Situation:
I'm new to c# and currently learning the ropes whilst also polishing up on my data structures, I decided to make a class that'd perform multiple functions to a linear array, since It was suggested to me that I should start with linear arrays then work on a circular one.
The methods my class currently provides are:
adding an item to the front-most position of the array,
adding an item to the back-most position of the array,
removing the first item in the array,
removing the last item in the array, //todo
clearing the current array list of it's values,
displaying the array list contents to the user.
Problem:
I'm having difficulty constructing a method that removes the last item of the array, I've looked online and the pre-writen methods seem complex and I can't get my head around them due to my in-experience. I realize it must be easy for others to write a method like this, but I'm truly stumped.
I'd like to learn how to write a method that removes the last value in the array, in the most simpliest to understand way. Here is my current code for my LinearArrayList class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace arraydatastructuresactual
{
public class LinearArrayList
{
private int count; //how many numbers currently stored
private int[] values; //array to hold values entered into list
//constructors
/// <summary>
/// //creates a linear array that can hold max values
/// </summary>
/// <param name="max"></param>
public LinearArrayList(int max)
{
count = 0;
values = new int[max]; //makes the linear array as big as the max value
}
/// <summary>
/// //default constructor sets capacity to 10
/// </summary>
public LinearArrayList()
{
count = 0;
values = new int[10];
}
/// <summary>
/// returns true if list is empty
/// otherwise turns false
/// </summary>
/// <returns>true if empty otherwise false</returns>
public bool isEmpty()
{
return (count == 0);
}
/// <summary>
/// returns true if list is full
/// otherwise turns false
/// </summary>
/// <returns>true if full otherwise false</returns>
public bool isFull()
{
return (values.Length <= count);
}
/// <summary>
/// if not full adds value to the end of list
/// throws exception if list is fulll
/// </summary>
/// <param name="value">value to add to end of list</param>
public void addLast(int value) //adds an item to the last position in the array.
{
if (isFull())
{
throw new Exception("List Full");
}
else
{
values[count++] = value;
}
}
public void addFirst(int value) //Adds an item to the first position in the array.
{
if (isFull())
{
throw new Exception("List Full");
}
else
{
for (int i = count; i > 0; i--)
{
values[i] = values[i--];
}
values[0] = value;
count++;
}
}
public int removeFirst() //removes the first item from the array
{
if (isEmpty())
throw new Exception("List is Empty");
int value = values[0];
count--;
for (int i = 0; i < count; i++)
{
values[i] = values[i + 1];
}
return value;
}
public int removeLast() //todo //removes the last item from the array
{
if (isEmpty())
throw new Exception("List is Empty");
int value = values[0];
count--;
for (int i = count; i < count; i++)
{
values[i] = values[i + 1];
}
return value;
}
public void displayUI()//displays contents of list
{
}
public void destroy() //Empties The List
{
}
}
}
If someone could share their experience on how I'd go about achieving this, then many thanks, I tried to repurpose my removeFirst method but I messed up, tried to do this a few times and I'm completely stumped now.
You just need to write
public int removeLast()
{
if (isEmpty())
throw new Exception("List is Empty");
count--;
return values[count];
}
this will return the last item in the values array WITHOUT changing its size but decrementing the variable that keeps track of the item actually inserted in the array.
Notice that I don't try to change the value in the location pointed by the count variable. It is still there until you overwrite it adding another value
So you could still write this
// Creates an array with space for 10 ints
LinearArrayList la = new LinearArrayList();
la.addLast(34);
la.addLast(23);
la.addLast(56);
la.addLast(467);
la.addLast(43);
la.addLast(666);
la.addLast(7989);
la.addLast(82);
la.addLast(569);
la.addLast(100);
int value = la.removeLast();
// This will work because you still have a slot free in the 10 ints array
la.addLast(1110);
// While this will fail because the array has now all slots filled
la.addLast(9435);
An alternative to Sybren's answer:
int lastValue = values[values.Length - 1];
int[] newValues = new int[values.Length - 1];
Array.Copy(values, newValues, newValues.Length);
values = newValues;
return lastValue;
or
int lastValue = values[values.Length - 1];
Array.Resize(values, values.Length - 1);
return lastValue;
If you don't want to use any existing methods of Array class, you can also:
int lastValue = values[values.Length - 1];
int[] newValues = new int[values.Length - 1];
for (int i = 0; i < newValues.Length; i++)
{
newValues[i] = values[i];
}
values = newValues;
return lastValue;
Edit
Forget this, do what #Steve said.
Here's a way to do it. You're converting your array to a list, getting the last element from the list, removing the last element from the list, and convert it back to an array.
var numbersList = values.ToList();
var last = numbersList.Last();
numbersList.Remove(last);
values = numbersList.ToArray();
return last;
I'm working on a roulette wheel class, it should function more or less like a regular roulette wheel where certain numbers can take up a larger portion of the roulette wheel and thus have a higher probability of being chosen.
So far it has passed the more basic unit tests, that is, programatically it works, I can create a roulette wheel and fill it with a bunch of generic values and it will do just that.
However when it comes to my probability testing, I decided to try it out as a 6-sided die, after 10,000,000 trials it should generate an average die roll of about 3,5 unfortunately it doesn't even come close to that the average after 10,000,000 trials is about 2,9 so I am guessing there is a weakness in my number selection somewhere? I have posted unit tests and actual code below:
public class RouletteNumber<T>
{
public readonly T Number;
public readonly int Size;
public RouletteNumber(T number, int size)
{
this.Number = number;
this.Size = size;
}
public static RouletteNumber<T>[] CreateRange(Tuple<T, int>[] entries)
{
var rouletteNumbers = new RouletteNumber<T>[entries.Length];
for (int i = 0; i < entries.Length; i++)
{
rouletteNumbers[i] = new RouletteNumber<T>(entries[i].Item1, entries[i].Item2);
}
return rouletteNumbers;
}
}
public class RouletteWheel<T>
{
private int size;
private RouletteNumber<T>[] numbers;
private Random rng;
public RouletteWheel(params RouletteNumber<T>[] rouletteNumbers)
{
size = rouletteNumbers.Length;
numbers = rouletteNumbers;
rng = new Random();
//Check if the roulette number sizes match the size of the wheel
if (numbers.Sum(n => n.Size) != size)
{
throw new Exception("The roulette number sections are larger or smaller than the size of the wheel!");
}
}
public T Spin()
{
// Keep spinning until we've returned a number
while (true)
{
foreach (var entry in numbers)
{
if (entry.Size > rng.Next(size))
{
return entry.Number;
}
}
}
}
}
[TestMethod]
public void DiceRouletteWheelTest()
{
double expected = 3.50;
var entries = new Tuple<int, int>[]
{
Tuple.Create(1, 1),
Tuple.Create(2, 1),
Tuple.Create(3, 1),
Tuple.Create(4, 1),
Tuple.Create(5, 1),
Tuple.Create(6, 1)
};
var rouletteWheel = new RouletteWheel<int>(RouletteNumber<int>.CreateRange(entries));
var results = new List<int>();
for (int i = 0; i < 10000000; i++)
{
results.Add(rouletteWheel.Spin());
}
double actual = results.Average();
Assert.AreEqual(expected, actual);
}
}
When you call Random.Next(n) it generates a random number between 0 and n-1, not between 0 and n.
Did you account for that?
In fact for a 6-sided die, you would want to call Random.Next(1, 7)
Maybe i'm not understanding it correctly but I'm guessing the problem lies here :
while (true)
{
foreach (var entry in numbers)
{
if (entry.Size > rng.Next(size))
{
return entry.Number;
}
}
}
You're calculating the rng.Next each time you do the if check.
So the first number has a 1 in 6 chance of being taken. Number 2(the next entry in numbers) then has a 2 in 6 chance of being taken(a new number is rendered between 1 and 6). But since you always start from the first you will eventually have more lower numbers.
I also don't see the need for the while(true) in a normal random generator.
I'm guessing this could would work and look like your current code :
var rndValue = rng.Next(size);
foreach (var entry in numbers)
{
if (entry.Size > rndValue)
{
return entry.Number;
}
}
Well, first of all, I am not sure whether my title in this question delivered what I want to ask or not. I just do not sure how to describe my problem in one sentence, hopefully the title would not cause any misleading.
If I have a list. Inside the list contain 100 data : list<100>
If I put this list inside a 1 second timer tick and do like this:
myList.RemoveRange(0, 2);
This mean, every 1 second, the data length inside the list will be -2;
This mean, every 1 second, it will be <98> , <96> , <94> .... <0>
Now my problem is...I still have a list, but the list will contain an array: list<array[100]>
Now, what I want is, every 1 second, the data length inside the array inside the list will be -2. But I am not sure know how to do this...
what I want is, every 1 second <array[98]> , <array[96]> , <array[96]> ... <array[0]>
And so, if the list contain <array0[100] , array1[100], array2[100]>
if i put this list inside a loop, every 1 second, it should be
array0[98] , array0[96] ... array0[0]
array1[98] , array1[96] ... array1[0]
array2[98] , array2[96] ... array2[0]
Update:
List<int[]> myList = new List<int[]>();
object myLock = new object();
Random rand = new Random();
public Form1()
{
timer1second.Start();
}
private void SomeMethod()
{
int[] myData = new int [100]
for (int i = 0; i < 100; i++)
{
//generate some random number to store inside myData[]
myData[i] = rand.Next(1 , 10);
}
lock (myLock)
{
myList.Add(myData); //mean List[0] = myData[100]
}
}
private void timer1second_Tick(object sender, EventArgs e)
{
lock (myLock)
{
//do something here in myList to get the myData[100 - 2]
//so that every 1 second tick, the data length inside the MyData will be -2
}
}
Convert the Array item into a List.
Then remove the range from the List
Convert it back to an Array.
Insert it back into the List
Here is a sample:
int currentIndex = 0;
var myList = new List<int[]>();
var intArray = new int[100];
myList.Add(intArray);
// Convert to List.
var newIntArrayList = myList[currentIndex].ToList();
// Remove the ranges
// Index would be based on you logic
newIntArrayList.RemoveRange(0, 2);
//Replace the list with the new arry
myList[currentIndex] = newIntArrayList.ToArray();
Update : Array.Resize should also help.
int currentIndex = 0;
int arrayLength = 100;
var myList = new List<int[]>();
var intArray = new int[100];
myList.Add(intArray);
// Get the array
var array = myList[currentIndex];
// Resize
Array.Resize(ref array, arrayLength-2);
//Replace the list with the update array
myList[currentIndex] = array;
List<int> myList = new List<int>();
for (int i = 1; i < 101; i++)
{
myList.Add(i);
}
for (int i = 100; i > 0; i--)
{
System.Threading.Threading.Sleep(1000);
myList.RemoveAt(i);
i -= 1;
myList.RemoveAt(i);
}
Resizing lists and arrays is an expensive operation. Would you consider a custom data structure for your needs with convinient interface and optimized underlying structure? So every tick you will only increment and integer value representing offset:
class Data
{
const int Step = 2;
List<int[]> data;
List<int> cursors;
public Data()
{
data = new List<int[]>();
}
public void AddArray(int[] array)
{
data.Add(array);
cursors.Add(array.Length);
// or cursors.Add(0), depending on your needs
}
public void Tick()
{
for (int i = 0; i < cursors.Count; i++)
{
cursors[i] -= Step;
// or cursors[i] += Step, depending on your needs
}
}
public IEnumerable<int> GetValuesAtIndex(int index)
{
for (int i = 0, i < data[index].Length; i++)
{
if (i > cursors[index]) // or i < cursors[index]
{
yield return data[index][i];
}
}
}
}