I have a problem. It's a bit difficult to explain, but I am going to try. I have a few buttons, which I want to give a sequence. I created a dictionary with the buttons and the SequenceNum. Now when I am in the sequence select screen, I can click a button and give it a number. Now I have this code for getting the next highest number:
foreach (KeyValuePair<string, SelectedHexagonRegistryObject> row in SelectedHexagonRegistry.ToList())
{
if (row.Value.SequenceNum >= NextSequenceNum)
{
NextSequenceNum = row.Value.SequenceNum + 1;
}
}
Now SequenceNum does always get the next highest number, but there is a problem with this. When I gave for example 6 buttons a sequence number and I click 3 again, it gets reset. That is supposed to happen, but when I want to swap numbers for example, I also click the button with the SequenceNum 4. There are 2 buttons with no sequence numbers. If I click one of the 2 buttons that don't have sequence number. The next number is 7. But the problem is that there is a gap, because the numbers 3 and 4 are reset, so I want to be the next number the lowest number of the gap. How can I create something like that?
Example:
I have 6 buttons, which I want to give a sequence number.
When I click the first button it will get SequenceNum 1
Then when I click the rest it will get the highest given number + 1.
At the end I have 6 buttons with all a sequence number from 1 to 6.
When I click for example the button with SequenceNum=4 again, I can unset the SequenceNum to 0 (equals null).
Now when I click that same button another timen, I want it to get the number of the gap that I created, so SequenceNum 4.
Now the problem is that it gets number 7, because it takes the highest + 1.
I need code to fill the gaps and I can't seem to figure out how I can make that!
Something like this should work, unless I am mistaken:
static int GetNextSequenceNo(Dictionary<string, SelectedHexagonRegistryObject> registry)
{
// order the values ascending
var vals = registry.Values.OrderBy(s => s.SequenceNum).ToList();
// find the first value where .SequenceNum is different from (idx + 1)
var firstGap = vals.TakeWhile((s, idx) => s.SequenceNum == idx + 1).Count();
// take the sequenceNum from the previous item and increment
if (firstGap > 0)
return vals[firstGap - 1].SequenceNum + 1;
else
return 1;
}
In general, if you have a list of integers and you want to find the next lowest available number, you can sort them (if they aren't already sorted) and then walk the list one item at a time, comparing the current item to the next item. As soon as you find one where the next item is greater than the current item by more than 1, you have found a gap and can return currentItem + 1.
If you get to the end of the list, then you just return the next number. For example:
private static int GetNextAvailableNumber(IReadOnlyCollection<int> numberSequence)
{
// If the list is null or empty, return the first number (this uses 1, modify as needed)
if (numberSequence == null || !numberSequence.Any()) return 1;
var orderedNumbers = numberSequence.OrderBy(n => n).ToList();
for (var i = 0; i < orderedNumbers.Count - 1; i++)
{
var thisNumber = orderedNumbers[i];
var nextNumber = orderedNumbers[i + 1];
if (nextNumber - thisNumber > 1) return thisNumber + 1;
}
return orderedNumbers.Last() + 1;
}
Related
I've got a priority queue created and working that enters items in order and removes them in order. Even if two numbers have the same priority, it removes the one that was entered first.
If there are three numbers that have the same priority, it does not remove the first one. How would I go about doing this, or should it do this?
Dequeue function:
public void deQueue(Animal item)
{
item = items.elements[0];
items.elements[0] = items.elements[numItems - 1];
numItems--;
items.ReheapDown(0, numItems - 1);
}
ReheapDown Function:
public void ReheapDown(int root, int bottom)
{
int maxchild, rightchild, leftchild;
leftchild = root * 2 + 1;
rightchild = root * 2 + 2;
if (leftchild <= bottom)
{
if (leftchild == bottom)
maxchild = leftchild;
else
{
if (elements[leftchild].priority <= elements[rightchild].priority)
maxchild = rightchild;
else
maxchild = leftchild;
}
if (elements[root].priority < elements[maxchild].priority)
{
Swap(elements, root, maxchild);
ReheapDown(maxchild, bottom);
}
}
}
In this line
if (elements[leftchild].priority <= elements[rightchild].priority)
you swap elements if they're equal. So let's say you enter the numbers [2, 2, 1, 3], in that order. Let's call the second 2, "2*", to differentiate it from the first one. The resulting heap is:
1
/ \
2 2*
/
3
Now, you remove 1. So then you replace the 1 with 3:
3
/ \
2 2*
In your ReheapDown method, the parent has two children, and you're selecting the smallest child. When you compare the two 2's, you have this code:
if (elements[leftchild].priority <= elements[rightchild].priority)
maxchild = rightchild;
else
maxchild = leftchild;
Since 2 == 2, it sets maxchild = rightchild, so the new root becomes 2*--the second 2 that was entered. Your heap now looks like this:
2*
/ \
2 3
And the next thing to be removed will be 2*.
You might think, then, that if you change that <= to <, it'll solve your problem. But it won't.
When you consider all the different ways that the heap can mutate, it's impossible to guarantee that equal items will be removed in the same order that they were inserted, unless you supply additional information. Consider what happens if you enter items in the order [1, 3, 2, 2*]. The resulting heap is:
1
/ \
2* 2
/
3
If you remove 1, you end up with:
3
/ \
2* 2
In this case, the <= would help you out. But in the previous case, it wouldn't.
The only way to guarantee removal order of equal items is to add a second condition on your comparison--basically, you have to make those equal items unequal. You either need to add a date stamp or sequential number to the key so that you can identify the insertion order.
I have an array like following:
{1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5}
I want to find duplicates within each 10 elements from one to another.
I need a code that can tell me that 5 was duplicated 3 times within 10 elements (there are at most only 1 element between 5s (4). It should igore last 5 as it is too far away. Only three 5s are within 10 elements).
I don't want code to return 1, because there are 13 element in between both 1s.
I have a code that can count duplicates but how to change it so it can count duplicates withing 10 elements?
var dict = new Dictionary<string, int>();
foreach (var count in combined2)
{
if (dict.ContainsKey(count))
dict[count]++;
else
dict[count] = 1;
}
foreach (var val in dict)
{
MessageBox.Show(val.Key + " occurred " + val.Value + " times");
}
I'm only concerned with duplicates that occur the most. If some number get duplicated twice but another gets duplicated 3 times. I would only like to know about number that got duplicated 3 times (withing 10 items). Thank you
Make a dictionary max defaulting to 0
Make a dictionary seen defaulting to 0
Count count from 0 up to N, where N is number of elements.
after N >= 10, decrement seen[array[count - 10]]
Increment seen[array[count]]
If that number is higher than max[array[count]], update it
Repeat
Return the key of the highest value in max.
This way, seen always has the accurate count in the 10-element window, and max will have the maximum number of appearances of each element in a 10-element window.
This code finds the first item with the higher number of occurrences inside the "numbers" array (within n = 10 elements):
int n = 10;
int[] numbers = new int[] {1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5};
int mostDuplicatedNumber = 0, numberOfMaxOccurrences = 0;
for(int count = 0; count < numbers.Length - n; count++)
{
var groupOfNumbers = numbers.Skip(count).Take(n).GroupBy(i => i).OrderByDescending(i => i.Count());
if(numberOfMaxOccurrences < groupOfNumbers.First().Count())
{
numberOfMaxOccurrences = groupOfNumbers.First().Count();
mostDuplicatedNumber = groupOfNumbers.First().Key;
}
}
Console.WriteLine("Most duplicated number is " + mostDuplicatedNumber + " with " + numberOfMaxOccurrences + " occurrences");
Try out this way. I have not tested using IDE just wrote while travelling. Let me know if you encounter any error. What it does simply take first 10 elements and finds number of occurrence i.e. repetition but then ( you would like to display most repeated number in that case you have to hold those repeated numbers in another array and swap the elements to get most repeated and least repeated one as you asking in your question I have not implemented this part ) .
.................
int[] inputArray= {1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5} // total input elements
int[] mostAndLeastOccuranceArray=new int[10] ;
int skip=0;
int limit=10;
int[] resultArray=new int[10];
for (int i = skip; i < inputArray.Length; i++)
{
if(i<limit)
{
resultArray[i]=inputArray[i];
skip=skip+1;
}else
{
findOccurance(resultArray); // call in every 10 elements array subset
resultArray=new int[10]; // re-initialize the array
limit=limit+10; // increase the limit for next iteration remember loop has not finished yet
}
}
public void findOccurance(int[] resultArray)
{
var dict = new Dictionary < int,int > ();
foreach(var value in resultArray)
{
if (dict.ContainsKey(value)) dict[value]++;
else dict[value] = 1;
}
foreach(var pair in dict)
{
mostAndLeastOccuranceArray[pair.Key]=pair.Value; // store the repeated value
Console.WriteLine("Value {0} occurred {1} times", pair.Key, pair.Value);
}
// call the method to find most and least occurance elements within each array subsets
findMostAndLeastOccuranceElements(mostAndLeastOccuranceArray)
// re-initialize
mostAndLeastOccuranceArray=new int[10] ;
}
public void findMostAndLeastOccuranceElements(int[] mostAndLeastOccuranceArray)
{
// now find most and least repeated elements within each 10 elements block
}
A simpler solution would be to use LINQ. Here I wrote a simple method to count the number of time a value is repeated.
public int CountRepetitions(List<int> myLists,int maxValues,int number)
{
if (myLists.Count > maxValues)
return myLists.Take(maxValues).Count(v => v == number);
else return 0;
}
everyone. I've this small task to do:
There are two sequences of numbers:
A[0], A[1], ... , A[n].
B[0], B[1], ... , B[m].
Do the following operations with the sequence A:
Remove the items whose indices are divisible by B[0].
In the items remained, remove those whose indices are divisible by B[1].
Repeat this process up to B[m].
Output the items finally remained.
Input is like this: (where -1 is delimiter for two sequences A and B)
1 2 4 3 6 5 -1 2 -1
Here goes my code (explanation done via comments):
List<int> result = new List<int>(); // list for sequence A
List<int> values = new List<int>(); // list for holding value to remove
var input = Console.ReadLine().Split().Select(int.Parse).ToArray();
var len = Array.IndexOf(input, -1); // getting index of the first -1 (delimiter)
result = input.ToList(); // converting input array to List
result.RemoveRange(len, input.Length - len); // and deleting everything beyond first delimiter (including it)
for (var i = len + 1; i < input.Length - 1; i++) // for the number of elements in the sequence B
{
for (var j = 0; j < result.Count; j++) // going through all elmnts in sequence A
{
if (j % input[i] == 0) // if index is divisible by B[i]
{
values.Add(result[j]); // adding associated value to List<int> values
}
}
foreach (var value in values) // after all elements in sequence A have been looked upon, now deleting those who apply to criteria
{
result.Remove(value);
}
}
But the problem is that I'm only passing 5/11 tests cases. The 25% is 'Wrong result' and the rest 25% - 'Timed out'. I understand that my code is probably very badly written, but I really can't get to understand how to improve it.
So, if someone more experienced could explain (clarify) next points to me it would be very cool:
1. Am I doing parsing from the console input right? I feel like it could be done in a more elegant/efficient way.
2. Is my logic of getting value which apply to criteria and then storing them for later deleting is efficient in terms of performance? Or is there any other way to do it?
3. Why is this code not passing all test-cases or how would you change it in order to pass all of them?
I'm writing the answer once again, since I have misunderstood the problem completely. So undoubtly the problem in your code is a removal of elements. Let's try to avoid that. Let's try to make a new array C, where you can store all the correct numbers that should be left in the A array after each removal. So if index id is not divisible by B[i], you should add A[id] to the array C. Then, after checking all the indices with the B[i] value, you should replace the array A with the array C and do the same for B[i + 1]. Repeat until you reach the end of the array B.
The algorithm:
1. For each value in B:
2. For each id from 1 to length(A):
3. If id % value != 0, add A[id] to C
4. A = C
5. Return A.
EDIT: Be sure to make a new array C for each iteration of the 1. loop (or clear C after replacing A with it)
In this article Test Run K-Means++ he use C# code and Roulette Wheel Selection to get next Centroid
there is a code that implement Roulette Wheel Selection
while (sanity < data.Length * 2)
{
cumulative += dSquared[ii] / sum;
if (cumulative >= p && used.Contains(ii) == false)
{
newMean = ii; // the chosen index
used.Add(newMean); // don't pick again
break; // WHY BREAK ?? THERE IS ANOTHER BIGGER CUMULATIVE VALUES
}
++ii; // next candidate
if (ii >= dSquared.Length)
ii = 0; // past the end
++sanity;
}
but why break when meet first true condition in here :
if (cumulative >= p && used.Contains(ii) == false)
why not looping until index 19 ???
N : 20 item
Random value = 0,817325359590969
I compare the result from the code with Excel : Result if not stop at index 16
can anyone explain to me the answer of this question ?
Because you want a weighted random sampling.
Otherwise, you would always choose the last value.
i started learning C# and programming a few months ago and have some problems. The idea here is we create a 2 dimensional array (the number of rows / columns are added by the user), the numbers need to be between 1 and 10.
Then when the array is created the number sequence ( 3-5-7-9-11 etc) is started in the first and finishes in the last column. The rest of the numbers in the columns are added via keyboard by the user starting with the first row (ignoring column 1 and the last column cause we have that added).
The questions are :
What will be the best way to check if the numbers of rows/columns are between 1 and 10? (I was thinking of IF-else but isn't there a better way ?)
How will i make it so that the number sequence 3-5-7 etc is started in the first and finishes in the last column?
Yeah i feel lost.
Where i am at the moment :
Console.WriteLine("Add row value of 1-10");
string s1
s1 = Console.ReadLine();
int k = int.Parse(s1);
Console.WriteLine("Add column value of 1-10");
string s2;
s2 = Console.ReadLine();
int p = int.Parse(s2);
int[,] M = new int[k, p];
Example : we added k(row) & p(coulmn) value of 4.So the array should look like :
3 x x 11
5 x x 13
7 x x 15
9 x x 17
Then the X's should be added again manually without overwriting the existing numbers .The value of the numbers doesnt matter.
So... If I get it right you want to ask user the "length and width" of dynamical 2d array?
To check if entered number is between 1 and 10 there's only 1 method:
int [,] M;
if (k >= 1 && k <= 10 && p >= 1 && p <= 10)
{
M = new int[k,p];
}
And better is to do int.TryParse() for case if user enters characters there instead of numbers, or else you can easily get an Exception.
Filling with numbers:
int num = 3;
for (int i = 0; i < k; ++i)
{
M[i,0] = num;
num+=2;
}
for (int i = 0; i < k; ++i)
{
M[i,p] = num;
num+=2;
}
This adds numbers in 1st and last column in each row. After that to fill other cells manually you check every cell thet it is not in firs or last column.
I hope I understood you correctly. Provided code may be simplified, but provided in such way for better understanding.
if(k>0 && k<11 && p>0 && p<11)
{
int i;
int M[,] = new int[k,p];
for (i=0;i<k;i++)
{
M[i,0]=i*2+3;
M[i,p-1]=(i+k)*2+3;
}
}