I'm looking for a formula that can spread out numbers in a linear format based on a minimum number, max number and amount of numbers (or dots) between. The catch is, the closer you get to the max, the more numbers should be there.
An example (number will vary and will be about 100 times larger)
Min = 0
Max = 16
AmountOfNumbersToSpread = 6
0 1 2 3 4 5 6 7 8 9 A B C D E F
1 2 3 4 5 6
Thanks for the help in advance.
Based on the answer of Tal Pressman, you can write a distribution function like this:
IEnumerable<double> Spread(int min, int max, int count, Func<double, double> distribution)
{
double start = min;
double scale = max - min;
foreach (double offset in Redistribute(count, distribution))
yield return start + offset * scale;
}
IEnumerable<double> Redistribute(int count, Func<double, double> distribution)
{
double step = 1.0 / (count - 1);
for (int i = 0; i < count; i++)
yield return distribution(i * step);
}
You can use any kind of distribution function which maps [0;1] to [0;1] this way. Examples:
quadratic
Spread(0, 16, 6, x => 1-(1-x)*(1-x))
Output: 0 5.76 10.24 13.44 15.36 16
sine
Spread(0, 16, 6, x => Math.Sin(x * Math.PI / 2))
Output: 0 4.94427190999916 9.40456403667957 12.9442719099992 15.2169042607225 16
Basically, you should have something that looks like:
Generate a random number between 0 and 1.
Implement your desired distribution function (a 1:1 function from [0,1]->[0,1]).
Scale the result of the distribution function to match your desired range.
The exact function used for the second point is determined according to how exactly you want the numbers to be distributed, but according to your requirement, you'll want a function that has more values close to 1 than 0. For example, a sin or cos function.
Tried this on paper and it worked:
given MIN, MAX, AMOUNT:
Length = MAX - MIN
"mark" MIN and MAX
Length--, AMOUNT--
Current = MIN
While AMOUNT > 1
Space = Ceil(Length * Amount / (MAX - MIN))
Current += Space
"mark" Current
By "mark" I mean select that number, or whatever you need to do with it.
Close answer, not quite though, needs to work for larger numbers.
List<int> lstMin = new List<int>();
int Min = 1;
int Max = 1500;
int Length = Max - Min;
int Current = Min;
int ConnectedClient = 7;
double Space;
while(ConnectedClient > 0)
{
Space = Math.Ceiling((double)(Length * ConnectedClient / (Max - Min)));
Current += (int)Space;
ConnectedClient--;
Length--;
lstMin.Add(Current);
}
Related
Hi I am sick of searching I could not find the exact code for my question.
I need to code the sum of the odd numbers from 1 to 100
and sum of the even numbers from 2 to 100.
This is what i have so far.
Thank you so much
// 1) using for statement to Sum Up a Range of values using Interactive
Console.WriteLine(" Sum Up a Range of values entered by User ");
Console.WriteLine();
// 2) Declare the Variables to be used in the Project
string strFromNumber, strToNumber;
int fromNumber, toNumber;
int sum = 0;
int i, even = 0, odd = 0;
int[] array = new int[10];
// 3) Prompt the User to Enter the From Number to Sum From
Console.Write("Enter the From Number to Sum From: ");
strFromNumber = Console.ReadLine();
fromNumber = Convert.ToInt32(strFromNumber);
// 4) Prompt the User to Enter the To Number to Sum To
Console.Write("Enter the To Number to Sum To: ");
strToNumber = Console.ReadLine();
toNumber = Convert.ToInt32(strToNumber);
// 5) Use for statement to Sum up the Range of Numbers
for (i = fromNumber; i <= toNumber; ++i)
{
sum += i;
}
if //(array[i] % 2 == 0) //here if condition to check number
{ // is divided by 2 or not
even = even + array[i]; //here sum of even numbers will be stored in even
}
else
{
odd = odd + array[i]; //here sum of odd numbers will be stored in odd.
}
Console.WriteLine("The Sum of Values from {0} till {1} = {2}",
fromNumber, toNumber, sum);
Console.ReadLine();
There is no need to write the complex code which you have written.
Problem is to calculate the sum of arithmetic progression. The formula to find the sum of an arithmetic progression is Sn = n/2[2a + (n − 1) × d] where, a = first term of arithmetic progression, n = number of terms in the arithmetic progression and d = common difference.
So in case of odd numbers its a = 1, n = 50 and d = 2
and in case of even numbers its a = 2, n = 50 and d = 2
and if you try to normalize these above formulas, it will be more easy based on your problem.
the sum of the first n odd numbers is Sn= n^2
the sum of the first n even numbers is n(n+1).
and obviously, it's very simple to loop from ( 1 to 99 with an increment of 2 ) and ( 2 to 100 with an increment of 2 )
In the simplest case, you can try looping in fromNumber .. toNumber range while adding
number either to even or to odd sum:
// long : since sum of int's can be large (beyond int.MaxValue) let's use long
long evenSum = 0;
long oddSum = 0;
for (int number = fromNumber; number <= toNumber; ++number) {
if (number % 2 == 0)
evenSum += number;
else
oddSum += number;
}
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
Note, that you can compute both sums in one go with a help of arithmetics progression:
private static (long even, long odd) ComputeSums(long from, long to) {
if (to < from)
return (0, 0); // Or throw ArgumentOutOfRangeException
long total = (to + from) * (to - from + 1) / 2;
from = from / 2 * 2 + 1;
to = (to + 1) / 2 * 2 - 1;
long odd = (to + from) / 2 * ((to - from) / 2 + 1);
return (total - odd, odd);
}
Then
(long evenSum, long oddSum) = ComputeSums(fromNumber, toNumber);
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
From the code snippet you shared, it seems like the user gives the range on which the sum is calculated. Adding to #vivek-nuna's answer,
Let's say the sum of the first N odd numbers is given by, f(n) = n^2 and
the sum of the first N even numbers is given by, g(n) = n(n + 1).
So the sum of odd numbers from (l, r) = f(r) - f(l - 1).
Similarly, the sum of even numbers from (l, r) = g(r) - g(l - 1).
Hope this helps.
I have a task to find pairs of amicable numbers and I've already solved it. My solution is not efficient, so please help me to make my algorithm faster.
Amicable numbers are two different numbers so related that the sum of the proper divisors of each is equal to the other number. The smallest pair of amicable numbers is (220, 284). They are amicable because the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110, of which the sum is 284; and the proper divisors of 284 are 1, 2, 4, 71 and 142, of which the sum is 220.
Task: two long numbers and find the first amicable numbers between them. Let s(n) be the sum of the proper divisors of n:
For example:
s(10) = 1 + 2 + 5 = 8
s(11) = 1
s(12) = 1 + 2 + 3 + 4 + 6 = 16
If s(firstlong) == s(secondLong) they are amicable numbers
My code:
public static IEnumerable<long> Ranger(long length) {
for (long i = 1; i <= length; i++) {
yield return i;
}
}
public static IEnumerable<long> GetDivisors(long num) {
return from a in Ranger(num/2)
where num % a == 0
select a;
}
public static string FindAmicable(long start, long limit) {
long numberN = 0;
long numberM = 0;
for (long n = start; n <= limit; n++) {
long sumN = GetDivisors(n).Sum();
long m = sumN;
long sumM = GetDivisors(m).Sum();
if (n == sumM ) {
numberN = n;
numberM = m;
break;
}
}
return $"First amicable numbers: {numberN} and {numberM}";
}
I generally don't write C#, so rather than stumble through some incoherent C# spaghetti, I'll describe an improvement in C#-madeup-psuedo-code.
The problem seems to be in your GetDivisors function. This is linear O(n) time with respect to each divisor n, when it could be O(sqrt(n)). The trick is to only divide up to the square root, and infer the rest of the factors from that.
GetDivisors(num) {
// same as before, but up to sqrt(num), plus a bit for floating point error
yield return a in Ranger((long)sqrt(num + 0.5)) where num % a == 0
if ((long)sqrt(num + 0.5) ** 2 == num) { // perfect square, exists
num -= 1 // don't count it twice
}
// repeat, but return the "other half"- num / a instead of a
yield return num/a in Ranger((long)sqrt(num + 0.5)) where num % a == 0
}
This will reduce your complexity of that portion from O(n) to O(sqrt(n)), which should provide a noticeable speedup.
There is a simple formula giving the sum of divisors of a number knowing its prime decomposition:
let x = p1^a1 * ... * pn^an, where pi is a prime for all i
sum of divisors = (1+p1+...+p1^a1) * ... (1+pn+...+pn^an)
= (1-p1^(a1+1))/(1-p1) * ... ((1-pn^(an+1))/(1-pn)
In order to do a prime decomposition you must compute all prime numbers up to the square root of the maximal value in your search range. This is easily done using the sieve of Erathostenes.
I am trying to create some kind of heatmap to visualize data I get from a sensor. So far this works but it looked odd. So I figured out that my code which normalizes the values (ranging from at least -100 to 100) must be invalid.
I often got exceptions because the factor (the normalized value) I use to calculate the color (byte) was negative or greater than 1.
So I modified my code and basically shifted min, max and the value by Math.Abs(min) to ensure that my values are positive. The negative issue is fixed but I sometimes end up with values like 1.02xxxx which must not happen. EDIT: Still getting negative values in some cases...
This is my code so far:
double min = data.Min();
double max = data.Max();
double avg = data.Average();
double v = max - min;
byte a, b, g, r;
// Set minimum and maximum
Dispatcher.InvokeAsync(() =>
{
Minimum = min;
Maximum = max;
Average = avg;
});
double shift = 0;
if (min < 0) // If minimum is negative, shift it to 0 and everything else positively by Abs(min)
{
max += shift = Math.Abs(min);
min += shift;
}
int skipFactor = (int)(1 / _pointResolution);
for (int i = 0; i < data.Length; i += skipFactor)
{
// If min == 0 then shift data
double value = Math.Abs(min) < 0.0001d ? (data[i] + shift) / max : (data[i] - min) / v;
...
}
How can I fix this without adding rounding or "edge-cases"? I assume the Math.Abs() combined with adding operations results in slightly off values... But there must be a solution to that, right?
Suppose I have a List. I'd like to be able to calculate semi-equi-distant max and min bounding points. I don't want to simply get the Max() and Min() its slightly more complicated.
To start, I'd like to specify a point in the list in which the list can be divided. To make it easy for now, suppose that point is 0. I'd then like to specify the number of divisions. Example:
List<int> Array = {-9,-8,-7,-2,-1,0,1,6,9,12};
int Divisions = 4;
int CutOff = 0;
So using these parameters I'd like to walk out to the extremes starting from 0 until there are 4 divisions. In this case the DivisionSize should be 6.
So the algorithm would start at 0 and walk to -6 for 1 Division then walk to -12 for the 2nd division. -12 would then become the bounding Min for the purposes of this algorithm.
The Max would then be calculated by starting at 0 and walking to 6, then 12. The bounding Max would then be 12. Its okay if the Calculate Max and Min are the actual Max and Min of the list, this is just an unlikely case.
I'm basically have some issues calculating the DivisionSize. I started with (Abs(Max)+Abs(Min))/Divisions but I can't seem to get the edge case where the Calculated size of the each division needs to be expanded to actually encompass the original Min and Max. Can somebody provided some guidance?
Edit: I don't necessarily want the BoundedMax and BoundedMin to be symmetrical about the cutoff. I want to add slack to either side of the cutoff until the BoundedMin and BoundedMax are >= and <= the range of the List.
Since your divisions are going to be "semi-equidistant" from the cutoff, your algorithm should only focus on half the divisions (one side from the cutoff). The next step would be to determine which of the "sides" of the cutoff is larger.
Next, we divide the larger side by half the division, and get the Ceiling of the value (round to next higher integer). This will give us the size of each division of the larger side which would encompass all the values on both sides of the cutoff.
The following algorithm would give you the DivisionSize of 6 when applied to the example you provided:
int NewMax = Abs(Max - CutOff);
int NewMin = Abs(Min - CutOff);
int DivisionSize = (int)Math.Ceiling(NewMax > NewMin ? NewMax/(Divisions/2) : NewMin/(Divisions/2));
L = abs(min(A)-cut)
R = abs(max(A)-cut)
size = max(L,R) # ate least two divisions
while divisions >= (1+(L-1)/size + 1+(R-1)/size)
size = size-1
size = size+1
Lets try it out:
L = 9
R = 12
size = 12
d = 1 + (9-1)/12 + 1 + (12-1)/12 = 1 + 1 = 2
size = 11
d = 1 + (9-1)/11 + 1 + (12-1)/11 = 1 + 2 = 3
size = 10
d = 1 + (9-1)/10 + 1 + (12-1)/10 = 1 + 2 = 3
size = 9
d = 1 + (9-1)/9 + 1 + (12-1) / 9 = 1 + 2 = 3
size = 8
d = 1 + (9-1)/8 + 1 + (12-1) / 8 = 2 + 2 = 4
size = 7
d = 1 + (9-1)/7 + 1 + (12-1) / 7 = 2 + 2 = 4
size = 6
d = 1 + (9-1)/6 + 1 + (12-1) / 6 = 2 + 2 = 4
size = 5
d = 1 + (9-1)/5 + 1 + (12-1) / 5 = 2 + 3 = 5
--> size = 6
Note that the integer divisions must be floored (not rounded).
For optimization, you can use a binary search between 1 and R for the size.
I think the key is to determine how many of your divisions you want either side of the CutOff point, by taking the ratio of each side's length to the total length.
In your example, the sides are 9 and 12, giving (approx) 1.7 and 2.2 divisions either side. The actual numbers must be integers, so try (1,3) and (2,2). 1 division on the left means the size must be 9, 2 divisions on either side allow you to use division size 6.
Wrote some C# to illustrate this. Not particularly elegant, but it seems to work.
public class RangeDivider
{
public int Min;
public int CutOff;
public int Max;
public int NumDivisions;
public RangeDivider(int min, int cutOff, int max, int numDivisions)
{
Min = min;
CutOff = cutOff;
Max = max;
NumDivisions = numDivisions;
System.Diagnostics.Debug.Assert(Min < CutOff && CutOff < Max && numDivisions >= 2);
}
public int LeftSize { get { return CutOff - Min; } }
public int RightSize { get { return Max - CutOff; } }
public int WholeSize { get { return Max - Min; } }
private static int divCeil(int dividend, int divisor) { return 1 + (dividend - 1)/divisor; }
private int ReturnSize(int leftDivisions)
{
int rightDivisions = NumDivisions - leftDivisions;
if (leftDivisions > 0 && rightDivisions > 0)
{
return Math.Max(divCeil(LeftSize, leftDivisions), divCeil(RightSize, rightDivisions));
}
else
{ //Must have at least 1 division each side of cutoff
return int.MaxValue;
}
}
public int GetSize()
{
var leftDivisions = NumDivisions * LeftSize / WholeSize;
var size = Math.Min(ReturnSize(leftDivisions), ReturnSize(leftDivisions + 1));
Console.WriteLine("Min {0}, CutOff {1}, Max {2}, NumDivisions {3} gives a Division Size of {4}", Min, CutOff, Max, NumDivisions, size);
return size;
}
public static int Get(int min, int cutOff, int max, int numDivisions)
{
return new RangeDivider(min, cutOff, max, numDivisions).GetSize();
}
public static void Test()
{
Get(-7,0,57,4);
Get(-9, 0, 12, 4);
Get(-1, 0, 7, 6);
}
}
Min -7, CutOff 0, Max 57, NumDivisions 4 gives a Division Size of 19
Min -9, CutOff 0, Max 12, NumDivisions 4 gives a Division Size of 6
Min -1, CutOff 0, Max 7, NumDivisions 6 gives a Division Size of 2
For example :
I have the number of list like below : {12,23,34,45,65} to change between 0 and 1 like
{0, 0.2, 0.4, 0.6, 0.8}. Does any body know some algorithm?
double max = 1.0 * oldList.Max();
var newList = oldList.Select(x => x / max);
If you want the lowest number to map to 0 then you'll need something like this:
double min = 1.0 * oldList.Min();
double max = 1.0 * oldList.Max();
var newList = oldList.Select(x => (x - min) / (max - min));
A very easy and efficient way to do this is to do a logit transformation. Logit formula is:
y = ln (x / (1 - x))
where y is a number between 0 and 1, following the binary distribution. Also, it is great because y can be zero or negative.
So let's do the way around it, so we can transform our data (y) into binominal distribution (infinite numbers constricted between 0 and 1).
y = ln (x / (1 - x))
exp(y) = exp (ln(x / (1 - x)) # to get rid of ln() we can make the exp() on both sides
exp(y) = x / (1 - x) # exponential rule: exp(ln(z)) = z
x = exp(y) * (1 - x)
x = exp(y) - x * exp(y)
x + x * exp(y) = exp(y)
x (1 + exp(y) = exp(y)
x = exp(y)/(1 + exp(y))
This is WAY easier and simpler than the other suggestions!
I hope that helps!
Find the max number in the sequence.
Divide all the numbers by the max
number
Algorithm:
find maximum and minimum
divide each (element - minimum) by (maximum - minimum)
Note: This will map the maximum to 1.0 ... which however is not the case in your example.
Edit:
var min = list.First(); // assumes a sorted list, else use Min()
var max = list.Last(); // assumes a sorted list, else use Max()
double difference = max - min;
var newList = list.Select( i => Math.Round( (i - min ) / difference, 1 ) );
If you want the lowest to map to 0, and the highest to map to 1, then the following will achieve this:
var input = new double[] { 12, 23, 34, 45, 65 };
var outputList = input.ToList().Select(i => (i - input.Min()) / (input.Max() - input.Min()));
foreach (var i in outputList)
{
Console.WriteLine(i);
}
expecting you want the highest to be 1.0 and the lowest value to be 0.0 and your array is in order from lowest to highest:
int lowest = myArray[0];
int highest = myArray[myArray.Length-1];
int diff = highest - lowest;
foreach (int item in myArray)
Console.WriteLine = (float)(item - lowest) / diff;