I've been trying to do the following, I have a max value and a int, I want to split that int like this:
Max = 10
Int = 45
Result = [10, 10, 10, 10, 5]
I already search a lot and I didn't find nothing like the thing I want to do, and my head hurts for thinking and trying to do it.
Thank you for any help!
You just need to repeat the max the number of times it divides into your value. Then if it does not divide evenly add the remainder.
int value = 45;
int max = 10;
var results = Enumerable.Repeat(max, value/max).ToList();
if(value % max != 0)
results.Add(value % max);
Console.WriteLine(string.Join(",", results));
I think LINQ is the nicest way to do this, but you could also have a straightforward loop approach that finds how many times the size fits into your max value, then add these numbers to a List<int>, and add the leftover(if any) to the list at the end.
var size = 10;
var max = 45;
// Find how many times the size fits and leftover
var goesInto = max / size;
var leftover = max % size;
var result = new List<int>();
// Add the sizes that fit in first
for (var i = 0; i < goesInto; i++)
{
result.Add(size);
}
// Add leftover size at the end.
if (leftover > 0)
{
result.Add(leftover);
}
That looks a lot like Pseudo code. We however will write C# code, as that was the langauge tag.
//Need a list, or have to calculate the expected lenght. List is easier.
List<int> ResultList = new List<int>();
//Make a copy to work with
int temp = value;
//Now let us math down towards 0
while(temp>0){
//All those multiples of Max are added first
if(temp >= Max){
ResultList.Add(Max);
temp -= Max;
}
//We are down to the rest, here
else{
//If the rest is not 0, you can add it too
if(temp > 0){
ResultList.Add(temp);
temp = 0;
}
}
}
Here how you do in plain code without LINQ, List, etc. This will also take care of negatives
int val = -45; // negative
int max = 10;
int count = Math.Abs(val / max);
int rem = Math.Abs(val % max);
var output = new int[count + (rem == 0 ? 0 : 1)];
for(int i = 0; i < output.Length ; i++)
{
if (i == output.Length - 1)
output[i] = rem;
else
output[i] = max;
Console.WriteLine(output[i]);
}
return output;
10
10
10
10
5
Related
I have a situation in which I must generate a random number, this number must be either zero or one
So, the code is something like this:
randomNumber = new Random().Next(0,1)
However, the business requirements state that there is just 10% probability that the generated number is zero and 90% probability that the generated number is 1
However can I include that probability in generating the random number please?
What I thought of is:
Generate array of integer that includes 10 zeros and 90 ones.
Generate a random index between 1 and 100
Take the value that corresponds to that index
But I don't know if this way is the correct way, plus, I think that C# should have something ready for it
You can implement it like that:
// Do not re-create Random! Create it once only
// The simplest implementation - not thread-save
private static Random s_Generator = new Random();
...
// you can easiliy update the margin if you want, say, 91.234%
const double margin = 90.0 / 100.0;
int result = s_Generator.NextDouble() <= margin ? 1 : 0;
to get true with a probability of 10%:
bool result = new Random().Next(1, 11) % 10 == 0;
to get true with a probability of 40%:
bool result = new Random().Next(1, 11) > 6;
First of all, you should save the reference to the random instance in order to get a proper random sequence of numbers:
Random randGen = new Random();
The second thing to know, is that the max of the random is exclusive, so to properly solve the issue you should do:
int eitherOneOrZero = randGen.Next(1, 11) % 10;
To generalize it to any variation of chances, you can do:
Random randGen = new Random();
var trueChance = 60;
int x = randGen.Next(0, 100) < trueChance ? 1 : 0;
Testing:
Random randGen = new Random();
var trueChance = 60;
var totalCount = 1000;
var trueCount = 0;
var falseCount = 0;
for (int i = 0; i < totalCount; i++)
{
int x = randGen.Next(0, 100) < trueChance ? 1 : 0;
if (x == 1)
{
trueCount++;
}
else
{
falseCount++;
}
}
Output:
True: 60.30 %
False: 39.70 %
I need ideas for a simple, lightweight way to get the max and min values of an array of doubles. The trick is I only need the max and min between two indexes in the array.
The built-in arrayOfDoubles.Max() and arrayOfDoubles.Min() will not work, because they check the entire array.
This code will be running constantly and needs to be somewhat efficient. That said, simplicity and readability are more important than speed alone.
Here's one way to get the max and min between two indexes:
double[] array = new double[8] { 3, 1, 15, 5, 11, 9, 13, 7 };
int startIndex = 3;
int endIndex = 6;
// Get max and min between these two indexes in the array
double max = GetMax(array, startIndex, endIndex);
double min = GetMin(array, startIndex, endIndex);
Console.WriteLine("Max = " + max + ", Min = " + min);
Here is the code for GetMax, and GetMin would be very similar:
private static double GetMax(double[] array, int startIndex, int endIndex)
{
double max = double.MinValue;
for (int i = startIndex; i <= endIndex; i++)
{
// Increase max with each bigger value
max = Math.Max(max, array[i]);
}
return max;
}
And the output: Max = 13, Min = 5
The Question: What other ways could I get the same result that might be simpler and wouldn't require too much overhead?
var list = array.Skip(startIndex).Take(endIndex - startIndex + 1).ToList();
var min = list.Min();
var max = list.Max();
You can also do:
var segment = new ArraySegment<double>(array, startIndex, endIndex - startIndex + 1);
var min = segment.Min();
var max = segment.Max();
It should be obvious that finding the minimum and maximum elements in an unsorted array requires an O(n) algorithm because no matter how you do it you do have to examine each element, at least once. So the only optimizations you can hope for are implementation specific and can only bring you gains in terms of the constants.
There is however a clever trick you can employ for finding both minimum and maximum in the array using only 3*[n/2] comparisons. While this is not an asymptotic improvement, it is an improvement of n/2 compared to the typical 2*n comparison that are needed in the straight forward algorithm. So, if you expect to be performing lots of the min/max computations then it may be worth considering it as an option.
The way you do it is like this:
maintain both minimum and maximum elements so far in two variables
at each iteration:
compare the next two elements between each other to determine which one is larger
compare the larger element with the maximum (and swap if necessary)
compare the smaller element with the minimum (and swap if necessary)
You will be executing n/2 iterations of that loop, and 3 comparisons for each iteration for a total of 3*[n/2] operations.
Here's an implementation:
void GetMinMax(double[] array, int start, int end, out double min, out double max)
{
min = array[start];
max = array[start];
if((end - start) % 2 == 0) // if there's an odd number of elements
start = start + 1; // skip the first one
for (int i = start + 1; i <= end; i += 2)
{
if(array[i] > array[i-1])
{
if(array[i] > max) max = array[i];
if(array[i - 1] < min) min = array[i - 1];
} else {
if(array[i - 1] > max) max = array[i - 1];
if(array[i] < min) min = array[i];
}
}
}
You can do this by scanning the array once. This is the standard min/max tracking algorithm that is asked in a bazillion interview questions, so readability shouldn't be an issue.
void GetMinMax(double[] array, int start, int end, out double min, out double max)
{
min = Double.MaxValue;
max = Double.MinValue;
// TODO: error checks for out-of-bounds, null, etc...
for (int i = start; i <= end; ++i)
{
if (array[i] > max) max = array[i];
if (array[i] < min) min = array[i];
}
}
Edit:
Using Usman Zafar's answer to simplify and remove the need for several error checks:
void GetMinMax(IList<double> list, out double min, out double max)
{
// TODO: null/empty check for list.
min = Double.MaxValue;
max = Double.MinValue;
for (int i = 0; i < list.Count; ++i)
{
if (list[i] > max) max = list[i];
if (list[i] < min) min = list[i];
}
}
Now call with any IList<double>, or in your case: new ArraySegment<double>(array, 3, 4).
using the sweet drug that is LINQ:
var res = array.Skip(startIndex).Take(1 + endIndex - startIndex );
var min = res.Min();
var max = res.Max();
This is my code:
SortedDictionary<int,int> Numbers = new SortedDictionary<int,int>();
List<int> onlyP = new List<int>(Numbers.Keys);
int Inferior = int.Parse(toks[0]);
int Superior = int.Parse(toks[1]);
int count = 0;
int inferiorindex = Array.BinarySearch(Numbers.Keys.ToArray(), Inferior);
if (inferiorindex < 0) inferiorindex = (inferiorindex * -1) - 1;
int superiorindex = Array.BinarySearch(Numbers.Keys.ToArray(), Superior);
if (superiorindex < 0) superiorindex = (superiorindex * -1) - 1;
count = Numbers[onlyP[superiorindex]] - Numbers[onlyP[inferiorindex]];
So what I'm trying to do is this: I've got a sorted dictionary with powers as keys, and a normal iteration as values. I've to print how many numbers of the keys fit within a specified range.
Example:
Some entries of the dict: [1,1],[4,2],[8,3],[9,4],[16,5],[25,6],[27,7],[32,8]
Limits: 2 and 10
Numbers within 2 - 10 : 4, 8, 9 = 3 numbers.
With BinarySearch I'm trying to quickly find the numbers I want and then substract Potencias[onlyP[superiorindex]] - Potencias[onlyP[inferiorindex]] to find how many numbers are within the range. Unfortunately it's not working for all the cases, and it sometimes gives less numbers than the actual amount. How can this be fixed? Thanks in advance.
[EDIT] Examples of the problems: If I select limits: 4 and 4... it returns 0, but the answer is 1.
limits: 1 and 10^9 (the whole range) returns 32669... But the answer is 32670.
The algorithm is ignoring powers.
Finally, having read the documentation. Notice the -1 on the upperIndex conversion and the +1 on the return value, these are important.
var numbers = new[] { 1, 4, 8, 9, 16, 25, 27, 32 };
var lowerBound = 4;
var upperBound = 17;
int lowerIndex = Array.BinarySearch(numbers, lowerBound);
if (lowerIndex < 0) lowerIndex = ~lowerIndex;
// - 1 here because we want the index of the item that is <= upper bound.
int upperIndex = Array.BinarySearch(numbers, upperBound);
if (upperIndex < 0) upperIndex = ~upperIndex - 1;
return (upperIndex - lowerIndex) + 1;
Explanation:
For the lower index we just take the complement because the BinarySearch returns the index of the first item >= lowerBound.
For the upper index we additionally minus one from the complement because we want the first item <= upperBound (not >= upperBound which is what BinarySearch returns).
It seems that you're not doing it the wright way for post processing the binary search return value :
http://msdn.microsoft.com/en-us/library/5kwds4b1.aspx
Should be :
if (inferiorindex < 0) inferiorindex = ~inferiorindex;
(untested)
Moreover, List supports a binary search, so you don't have to do the Array.BinarySearch thing, just work on onlyP.
int inferiorindex = Array.BinarySearch<int>(keys, Inferior);
if (inferiorindex < 0) {
inferiorindex = ~inferiorindex;
}
int superiorindex = Array.BinarySearch<int>(keys, Superior);
if (superiorindex < 0) {
// superiorindex is the binary complement of the next higher.
// -1 because we want the highest.
superiorindex = ~superiorindex - 1;
}
int count = superiorindex - inferiorindex + 1;
I have come up with the code below but that doesn't satisfy all cases, e.g.:
Array consisting all 0's
Array having negative values(it's bit tricky since it's about finding product as two negative ints give positive value)
public static int LargestProduct(int[] arr)
{
//returning arr[0] if it has only one element
if (arr.Length == 1) return arr[0];
int product = 1;
int maxProduct = Int32.MinValue;
for (int i = 0; i < arr.Length; i++)
{
//this block store the largest product so far when it finds 0
if (arr[i] == 0)
{
if (maxProduct < product)
{
maxProduct = product;
}
product = 1;
}
else
{
product *= arr[i];
}
}
if (maxProduct > product)
return maxProduct;
else
return product;
}
How can I incorporate the above cases/correct the code. Please suggest.
I am basing my answer on the assumption that if you have more than 1 element in the array, you would want to multiply at least 2 contiguous integers for checking the output, i.e. in array of {-1, 15}, the output that you want is -15 and not 15).
The problem that we need to solve is to look at all possible multiplication combinations and find out the max product out of them.
The total number of products in an array of n integers would be nC2 i.e. if there are 2 elements, then the total multiplication combinations would be 1, for 3, it would be 3, for 4, it would be 6 and so on.
For each number that we have in the incoming array, it has to multiply with all the multiplications that we did with the last element and keep the max product till now and if we do it for all the elements, at the end we would be left with the maximum product.
This should work for negatives and zeros.
public static long LargestProduct(int[] arr)
{
if (arr.Length == 1)
return arr[0];
int lastNumber = 1;
List<long> latestProducts = new List<long>();
long maxProduct = Int64.MinValue;
for (int i = 0; i < arr.Length; i++)
{
var item = arr[i];
var latest = lastNumber * item;
var temp = new long[latestProducts.Count];
latestProducts.CopyTo(temp);
latestProducts.Clear();
foreach (var p in temp)
{
var product = p * item;
if (product > maxProduct)
maxProduct = product;
latestProducts.Add(product);
}
if (i != 0)
{
if (latest > maxProduct)
maxProduct = latest;
latestProducts.Add(latest);
}
lastNumber = item;
}
return maxProduct;
}
If you want the maximum product to also incorporate the single element present in the array i.e. {-1, 15} should written 15, then you can compare the max product with the element of the array being processed and that should give you the max product if the single element is the max number.
This can be achieved by adding the following code inside the for loop at the end.
if (item > maxProduct)
maxProduct = item;
Your basic problem is 2 parts. Break them down and solving it becomes easier.
1) Find all contiguous subsets.
Since your source sequence can have negative values, you are not all that equipped to make any value judgments until you're found each subset, as a negative can later be "cancelled" by another. So let the first phase be to only find the subsets.
An example of how you might do this is the following code
// will contain all contiguous subsets
var sequences = new List<Tuple<bool, List<int>>>();
// build subsets
foreach (int item in source)
{
var deadCopies = new List<Tuple<bool, List<int>>>();
foreach (var record in sequences.Where(r => r.Item1 && !r.Item2.Contains(0)))
{
// make a copy that is "dead"
var deadCopy = new Tuple<bool, List<int>>(false, record.Item2.ToList());
deadCopies.Add(deadCopy);
record.Item2.Add(item);
}
sequences.Add(new Tuple<bool, List<int>>(true, new List<int> { item }));
sequences.AddRange(deadCopies);
}
In the above code, I'm building all my contiguous subsets, while taking the liberty of not adding anything to a given subset that already has a 0 value. You can omit that particular behavior if you wish.
2) Calculate each subset's product and compare that to a max value.
Once you have found all of your qualifying subsets, the next part is easy.
// find subset with highest product
int maxProduct = int.MinValue;
IEnumerable<int> maxSequence = Enumerable.Empty<int>();
foreach (var record in sequences)
{
int product = record.Item2.Aggregate((a, b) => a * b);
if (product > maxProduct)
{
maxProduct = product;
maxSequence = record.Item2;
}
}
Add whatever logic you wish to restrict the length of the original source or the subset candidates or product values. For example, if you wish to enforce minimum length requirements on either, or if a subset product of 0 is allowed if a non-zero product is available.
Also, I make no claims as to the performance of the code, it is merely to illustrate breaking the problem down into its parts.
I think you should have 2 products at the same time - they will differ in signs.
About case, when all values are zero - you can check at the end if maxProduct is still Int32.MinValue (if Int32.MinValue is really not possible)
My variant:
int maxProduct = Int32.MinValue;
int? productWithPositiveStart = null;
int? productWithNegativeStart = null;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == 0)
{
productWithPositiveStart = null;
productWithNegativeStart = null;
}
else
{
if (arr[i] > 0 && productWithPositiveStart == null)
{
productWithPositiveStart = arr[i];
}
else if (productWithPositiveStart != null)
{
productWithPositiveStart *= arr[i];
maxProduct = Math.max(maxProduct, productWithPositiveStart);
}
if (arr[i] < 0 && productWithNegativeStart == null)
{
productWithNegativeStart = arr[i];
}
else if (productWithNegativeStart != null)
{
productWithNegativeStart *= arr[i];
maxProduct = Math.max(maxProduct, productWithNegativeStart);
}
maxProduct = Math.max(arr[i], maxProduct);
}
}
if (maxProduct == Int32.MinValue)
{
maxProduct = 0;
}
At a high level, your current algorithm splits the array upon a 0 and returns the largest contiguous product of these sub-arrays. Any further iterations will be on the process of finding the largest contiguous product of a sub-array where no elements are 0.
To take into account negative numbers, we obviously first need to test if the product of one of these sub-arrays is negative, and take some special action if it is.
The negative result comes from an odd number of negative values, so we need to remove one of these negative values to make the result positive again. To do this we remove all elements up the the first negative number, or the last negative number and all elements after that, whichever results in the highest product.
To take into account an array of all 0's, simply use 0 as your starting maxProduct. If the array is a single negative value, you're special case handling of a single element will mean that is returned. After that, there will always be a positive sub-sequence product, or else the whole array is 0 and it should return 0 anyway.
it can be done in O(N). it is based on the simple idea: calculate the minimum (minCurrent) and maximum (maxCurrent) till i. This can be easily changed to fit for the condition like: {0,0,-2,0} or {-2,-3, -8} or {0,0}
a[] = {6, -3, 2, 0, 3, -2, -4, -2, 4, 5}
steps of the algorithm given below for the above array a :
private static int getMaxProduct(int[] a) {
if (a.length == 0) {
throw new IllegalArgumentException();
}
int minCurrent = 1, maxCurrent = 1, max = Integer.MIN_VALUE;
for (int current : a) {
if (current > 0) {
maxCurrent = maxCurrent * current;
minCurrent = Math.min(minCurrent * current, 1);
} else if (current == 0) {
maxCurrent = 1;
minCurrent = 1;
} else {
int x = maxCurrent;
maxCurrent = Math.max(minCurrent * current, 1);
minCurrent = x * current;
}
if (max < maxCurrent) {
max = maxCurrent;
}
}
//System.out.println(minCurrent);
return max;
}
I have an array of integers and need to find the position in the array of the maximum number along with the minimum. I have it working but it doesn't seem to be a very good way to do it. Can anyone suggest a better way to achieve what I have?
Here's my code:
int[] usageHours = { 3, 3, 5, 4, 0, 0, 2, 2, 4, 25, 158, 320, 212, 356, 401, 460, 480, 403, 298, 213, 102, 87, 34, 45 };
double myAverage = usageHours.Average();
int runningTotal = 0;
int runningMaxPosition = 0;
for (int i = 0; i < usageHours.Length; i++)
{
if (usageHours[i] > runningTotal)
{
runningMaxPosition = i;
runningTotal = usageHours[i];
}
}
txtmax.Text = Convert.ToString(runningMaxPosition)+" With: "+Convert.ToString(runningTotal)+" Users";
txtAv.Text = Convert.ToString(myAverage);
That code is mostly fine. I'd suggest changing the variable names a bit, but that's all. You can work out the minimum in the same loop. I've changed the "if" conditions very slightly to guarantee that they always pick out at least one element (even if all the values are, say, int.MinValue). There are other ways of approaching this, but this is one example. If you have an empty array, you'll end up with max=min=0, and both indexes=-1.
int currentMax = 0;
int currentMaxIndex = -1;
int currentMin = 0;
int currentMinIndex = -1;
for (int i = 0; i < usageHours.Length; i++)
{
if (currentMaxIndex == -1 || usageHours[i] > currentMax)
{
currentMaxIndex = i;
currentMax = usageHours[i];
}
if (currentMinIndex == -1 || usageHours[i] < currentMin)
{
currentMinIndex = i;
currentMin = usageHours[i];
}
}
Here's an alternative using nullable value types to represent "there were no values" answers:
int currentMax? = null;
int currentMaxIndex? = null;
int currentMin? = null;
int currentMinIndex? = null;
for (int i = 0; i < usageHours.Length; i++)
{
if (currentMax == null || usageHours[i] > currentMax.Value)
{
currentMax = i;
currentMax = usageHours[i];
}
if (currentMin == null || usageHours[i] < currentMin.Value)
{
currentMinIndex = i;
currentMin = usageHours[i];
}
}
Don't worry if you haven't come across nullable value types yet though...
The code looks OK for finding the max value. If you are using C# 3 or later you could use the LINQ extension methods (there are Min, Max and Average methods, and on List there is also a FindIndex method, amongst others), but I get the impression that you are learning programming, and then it is sometimes a good idea to implement stuff that may be built into the framework, just for the learning value.
I just wanted to provide one-liner solution for the question (for completeness).
In the OP's original question he only asks for index of the maximum and index of the minimum.
Let's stick to this question. This is the most interesting question because to find maximum value we can simply use Enumerable.Max LINQ method. The same goes for Min and Average.
Let's only provide index of the max, index of min can be retrieved with similar code.
int indexOfMax = Enumerable.Range(0, usageHours.Length).Aggregate(
(indexOfMax, i) => (usageHours[i] > usageHours[indexOfMax] ? i : indexOfMax)
);
Delegate inside of Aggregate's brackets is executed for each index of array. It gets as parameters "index of maximum value so far found", and current index. It returns "index of maximum value so far found". Obviously in each iteration "index of maximum value so far found" will only change to current index if corresponding element of array is greater than previous maximum.
scratch the linq code, it didnt work the way you wanted
you could make your code a little bit more concise
for (int i = 0; i < usageHours.Length; i++)
{
if (usageHours[i] > usageHours[runningMaxPosition])
runningMaxPosition = i;
}
all it does differently is leavs out the temporary runningTotal variable.
How about this:
double average = usageHours.Average();
int maxPosition = Enumerable.Range(0, usageHours.Length).Max(i => usageHours[i]);
int minPosition = Enumerable.Range(0, usageHours.Length).Min(i => usageHours[i]);
Your code isn't bad, but it won't work if all the values are less than zero.
Try this:
int getArrayMaxPosition (double[] theArray)
{
double maxVal = theArray[0];
int ret = 0;
int currentIndex = 0;
foreach (double aValue in theArray)
{
if (aValue > maxVal)
{
ret = currentIndex;
maxVal = avalue;
}
currentIndex++;
}
return ret;
}
As was mentioned on the comment's to Jon's answer, Jon's solution really is the best, most direct, quickest way of doing it.
If, however, you did want to use Igor's solution, here's the rest of it (to get the actual positions as well as the values):
int maxValue = Enumerable.Range(0, usageHours.Length).Max(i => usageHours[i]);
int maxPosition = Array.FindIndex(usageHours, i => i == maxValue);
int minValue = Enumerable.Range(0, usageHours.Length).Min(i => usageHours[i]);
int minPosition = Array.FindIndex(usageHours, i => i == minValue);