C# calculate function min per given range - c#

I need to find the minimum from a given range without running O(n).
The array might be a some diagonal line or a hyperbole. here are three sample arrays:
var arrDiag1 = new double[10] { 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5 };
var arrDiag2 = new double[10] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
var arrHyperbole = new double[10] { 9, 8, 7, 6, 5, 4, 3, 4, 5, 6 };
I tried building some sort of calculation from the line in the desert exercise but it came out no good.
Anyone has a better idea?
Thanks for the help
update
With dasblinkenlight help I managed to get to this method:
private double BinarySearchMin(double[] arr, int left, int leftMiddle, int rightMiddle, int right)
{
if (left == right)
return arr[left];
if (arr[leftMiddle] < arr[rightMiddle])
{
right = rightMiddle;
leftMiddle = ((right - left) / 3);
rightMiddle = ((right - left) / 3 * 2);
return BinarySearchMin(arr, left, leftMiddle, rightMiddle, right);
}
if (arr[leftMiddle] > arr[rightMiddle])
{
left = leftMiddle;
leftMiddle = ((right - left) / 3) + left;
rightMiddle = ((right - left) / 3 * 2) + left;
return BinarySearchMin(arr, left, leftMiddle, rightMiddle, right);
}
if (arr[leftMiddle] == arr[rightMiddle])
{
left = leftMiddle;
right = rightMiddle;
leftMiddle = ((right - left) / 3) + left;
rightMiddle = ((right - left) / 3 * 2) + left;
return BinarySearchMin(arr, left, leftMiddle, rightMiddle, right);
}
return -1;
}
In the first array it works but not in the second and third arrays.
What am I missing here?

If the function has only one minimum, use Ternary Search:
ternary search algorithm is a technique for finding the minimum or maximum of a unimodal function.
The idea is to split the range in three equal segments, probe at the two search points and then "pull in" the one which does not contain the minimum. Assuming search points i1 on the left side of the interval and and i2 on the right:
If f[i1] < f[i2], then the minimum is between 0 and i2; pull in from right
If f[i1] > f[i2], then the minimum is between i1 and N; pull in from left
If f[i1] == f[i2], then the minimum is between i1 and i2; pull in from both sides.
The running time of the algorithm is O(log N).

I usually hate answering to homework questions, but I somewhat like this one.
First of all, think of the two "diagonal" cases as nothing special, just a different view on the hyperbole where the minimum happens to be on the edge.
Then, try something like binary search to find the minimum. Have a peek at the two middle elements, look at their relation and decide on which side the minimum will be. Repeat until only one element is left.

Related

Distributing k points among n entities to find distance between points?

I have a known list of n entries. I also have a known quantity of k points.
I need to distribute those k points as equally distant to one another as I can among the n entries. The end result is that I know what distance (d) is between the points.
Example:
So if we had n={0, 1, 2, 3, 4, 5} entries (n=6) and k=3, and we assume we can start from 0 always, then we'd end up with a result of 0, 2 and 4 getting a point each as the "distance" between them all is 1 (d=1).
I've been racking my brain on how to calculate the d for an hour now. I'm not sure how to do it.
n will always be a list of integers.
k will always be less than n and an integer
d should always be an integer where k*d <= n.
I tried using the sqrt of n but that wouldn't work if I get fractions.
I know this sounds like a math assignment but it's not homework. It's just a problem I'm sitting with for a game.
How do I calculate d? I use C#.
Turns out what I actually needed was to discretely distribute k indices across n elements.
See an example of it in action here; https://youtu.be/SC0qwkNzvmo
You can see how bombs are distributed among players. That is what I needed but had difficulty explaining.
It seems to me that you just need this:
int[] indices = new [] { 0, 2, 4, };
double distance =
Enumerable
.Range(0, indices.Length)
.SelectMany(
i => Enumerable.Range(i + 1, indices.Length - i - 1),
(i, j) => Math.Sqrt(indices[i] * indices[i] + indices[j] * indices[j]))
.Average();
If you're trying to discretely distribute the k indices across the n elements, then this is it:
int n = 6;
int k = 3;
int[] bs =
Enumerable
.Range(0, k)
.Select(i => i * n / k)
.ToArray();
That gives 0, 2, 4.

Confusing value's used in find Missing number between 1 - X

Hi guys im learning c# currently and Im trying to run threw some interview questions to try and understand them and learn in the process.
I found a question, How do you find the missing number in a given integer array of 1 to 100?
I think I get the General Idea of having to get the sum, Then the Sum of the Sequence then Minus X - Y;
But im confused about the code example below, Why is he using * (arr.Length + 2) When the Equation is n*(n+1)/2 I know its correct but shouldnt this be (arr.Length + 1) * (arr.Length) / 2 According tot he formula
Im terribly confused.
//array to find the missing number between 1 and 10
// Simplicity, We will take number 1 to 10 i where Number 5 is missing in the sequence.
int[] arr = { 1, 2, 3, 4, 6, 7, 8, 9, 10 };
int missingNumber,Totalsum;
// Accoreding to series rule, calculating sum of total numbers upto 10
//sum of first n natutal numbers=n*(n+1)/2
Totalsum = (arr.Length + 1) * (arr.Length + 2) / 2;
// Missing number is calculating.
foreach (int item in arr)
{
Totalsum = Totalsum - item;
}
missingNumber = Totalsum;
Console.WriteLine("missing number : {0}",missingNumber);
Not a Assignment. Just someone trying to learn programming by them selves looking up random questions to learn practically
Where i got the question
https://simpleprogrammer.com/programming-interview-questions/
The Explanation I found
https://www.interviewsansar.com/find-missing-number-between-1-to-n-in-array-in-c/
The comment gives the answer to your question:
// Accoreding to series rule, calculating sum of total numbers upto 10
//sum of first n natutal numbers=n*(n+1)/2
It's just that it's a number sequence that "should have 10 numbers but actually only has 9"
The formula needs n to be 10, but the array has a length of 9. 9+1 is n, 9+2 is n+1

How to interpolate through 3 points/numbers with a defined number of samples? (in c#)

So for example we have 1, 5, and 10 and we want to interpolate between these with 12 points, we should get:
1.0000
1.7273
2.4545
3.1818
3.9091
4.6364
5.4545
6.3636
7.2727
8.1818
9.0909
10.0000
say we have 5, 10, and 4 and again 12 points, we should get:
5.0000
5.9091
6.8182
7.7273
8.6364
9.5455
9.4545
8.3636
7.2727
6.1818
5.0909
4.0000
This is a generalized solution that works by these principles:
Performs linear interpolation
It calculates a "floating point index" into the input array
This index is used to select 1 (if the fractional parts is very close to 0) or 2 numbers from the input array
The integer part of this index is the base input array index
The fractional part says how far towards the next array element we should move
This should work with whatever size input arrays and output collections you would need.
public IEnumerable<double> Interpolate(double[] inputs, int count)
{
double maxCountForIndexCalculation = count - 1;
for (int index = 0; index < count; index++)
{
double floatingIndex = (index / maxCountForIndexCalculation) * (inputs.Length - 1);
int baseIndex = (int)floatingIndex;
double fraction = floatingIndex - baseIndex;
if (Math.Abs(fraction) < 1e-5)
yield return inputs[baseIndex];
else
{
double delta = inputs[baseIndex + 1] - inputs[baseIndex];
yield return inputs[baseIndex] + fraction * delta;
}
}
}
It produces the two collections of outputs you showed in your question but beyond that, I have not tested it. Little error checking is performed so you should add the necessary bits.
The problem is an interpolation of two straight lines with different slopes given the end points and the intersection.
Interpolation is defined as following : In the mathematical field of numerical analysis, interpolation is a method of constructing new data points within the range of a discrete set of known data points.
I'm tired of people giving negative points for solutions to hard problems. This is not a simply problem, but a problem that require "thinking out of the box". lets looks at the solution for following input : 1 12 34
I picked these numbers because the results are all integers
The step size L (Lower) = distance of elements from 1 to 12 = 2
The step size H (Higher) = distance of elements from 12 to 34 = 4
So the answer is : 1 3 5 7 9 11 [12] 14 18 22 26 30 34
Notice the distance between the 6th point 11 and center is 1 (half of L)
Notice the distance between the center point 12 and the 7th point is 2 (half of H)
Finally notice the distance between the 6th and 7th points is 3.
My results are scaled exactly the same as the OPs first example.
It is hard to see the sequence with the fractional inputs the OP posted. If you look at the OP first example and calculate the step distance of the first 6 points you get 0.72. The last 6 points the distance is 0.91. Then calculate the distance from the 6th point to the center is .36 (half 0.72). Then center to 7th point 0.45 (half 0.91). Excuse me for rounding the numbers a little bit.
It is a sequence problem just like the in junior high school where you learned arithmetic and geometric sequences. Then as a bonus question you got the sequence 23, 28, 33, 42,51,59,68,77,86 which turns out to be the train stations on the NYC 3rd Ave subway system. Solving problems like this you need to think "Outside the Box" which comes from the tests IBM gives to Job Applicants. These are the people who can solve the Nine Point Problem : http://www.brainstorming.co.uk/puzzles/ninedotsnj.html
I did the results when the number of points is EVEN which in you case is 12. You will need to complete the code if the number of points is ODD.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
const int NUMBER_POINTS = 12;
static void Main(string[] args)
{
List<List<float>> tests = new List<List<float>>() {
new List<float>() { 1,5, 10},
new List<float>() { 5,10, 4}
};
foreach (List<float> test in tests)
{
List<float> output = new List<float>();
float midPoint = test[1];
if(NUMBER_POINTS % 2 == 0)
{
//even number of points
//add lower numbers
float lowerDelta = (test[1] - test[0])/((NUMBER_POINTS / 2) - .5F);
for (int i = 0; i < NUMBER_POINTS / 2; i++)
{
output.Add(test[0] + (i * lowerDelta));
}
float upperDelta = (test[2] - test[1]) / ((NUMBER_POINTS / 2) - .5F); ;
for (int i = 0; i < NUMBER_POINTS / 2; i++)
{
output.Add(test[1] + (i * upperDelta) + (upperDelta / 2F));
}
}
else
{
}
Console.WriteLine("Numbers = {0}", string.Join(" ", output.Select(x => x.ToString())));
}
Console.ReadLine();
}
}
}

Google Code Jam 2013 R1B - Falling Diamonds

Yesterdays Code Jam had a question titled Falling Diamonds. The full text can be found here, but in summary:
Diamonds fall down the Y axis.
If a diamond hits point to point with another diamond, there is a 50/50 chance it will slide to the right or left, provided it is not blocked from doing so.
If a diamond is blocked from sliding one direction, it will always slide the other way.
If a diamond is blocked in both directions, it will stop and rest on the blocking diamonds.
If a diamond hits the ground, it will bury itself half way, then stop.
The orientation of the diamond never changes, i.e. it will slide or sink, but not tumble.
The objective is to find the probability that a diamond will rest at a given coordinate, assuming N diamonds fall.
The above requirements basically boil down to the diamonds building successively larger pyramids, one layer at a time.
Suffice to say, I have not been able to solve this problem to google’s satisfaction. I get the sample from the problem description correct, but fail on the actual input files. Ideally I would like to see a matched input and correct output file that I can play with to try and find my error. Barring that, I would also welcome comments on my code.
In general, my approach is to find how many layers are needed to have one which contains the coordinate. Once I know which layer I am looking at, I can determine a number of values relevant to the layer and point we are trying to reach. Such as how many diamonds are in the pyramid when this layer is empty, how many diamonds can stack up on a side before the rest are forced the other way, how many have to slide in the same direction to reach the desired point, etc.
I then check to see if the number of diamonds dropping either makes it impossible to reach the point (probability 0), or guarantees we will cover the point (probability 1). The challenge is in the middle ground where it is possible but not guaranteed.
For the middle ground, I first check to see if we are dropping enough to potentially fill a side and force remaining drops to slide in the opposite direction. Reason being that in this condition we can guarantee that a certain number of diamonds will slide to each side, which reduces the number of drops we have to worry about, and resolves the problem of the probability changing when a side gets full. Example: if 12 diamonds drop it is guaranteed that each side of the outer layer will have 2 or more diamonds in it, whether a given side has 2, 3, or 4 depends on the outcome of just 2 drops, not of all 6 that fall in this layer.
Once I know how many drops are relevant to success, and the number that have to break the same way in order to cover the point, I sum the probabilities that the requisite number, or more, will go the same way.
As I said, I can solve the sample in the problem description, but I am not getting the correct output for the input files. Unfortunately I have not been able to find anything telling me what the correct output is so that I can compare it to what I am getting. Here is my code (I have spent a fair amount of time since the contest ended trying to tune this for success and adding comments to keep from getting myself lost):
protected string Solve(string Line)
{
string[] Inputs = Line.Split();
int N = int.Parse(Inputs[0]);
int X = int.Parse(Inputs[1]);
int Y = int.Parse(Inputs[2]);
int AbsX = X >= 0 ? X : -X;
int SlideCount = AbsX + Y; //number that have to stack up on one side of desired layer in order to force the remaining drops to slide the other way.
int LayerCount = (SlideCount << 1) | 1; //Layer is full when both sides have reached slidecount, and one more drops
int Layer = SlideCount >> 1; //Zero based Index of the layer is 1/2 the slide count
int TotalLayerEmpty = ((Layer * Layer) << 1) - Layer; //Total number of drops required to fill the layer below the desired layer
int LayerDrops = N - TotalLayerEmpty; //how many will drop in this layer
int MinForTarget; //Min number that have to be in the layer to hit the target location, i.e. all fall to correct side
int TargetCovered; //Min number that have to be in the layer to guarantee the target is covered
if (AbsX == 0)
{//if target X is 0 we need the layer to be full for coverage (top one would slide off until both sides were full)
MinForTarget = TargetCovered = LayerCount;
}
else
{
MinForTarget = Y + 1; //Need Y + 1 to hit an altitude of Y
TargetCovered = MinForTarget + SlideCount; //Min number that have to be in the layer to guarantee the target is covered
}
if (LayerDrops >= TargetCovered)
{//if we have enough dropping to guarantee the target is covered, probability is 1
return "1.0";
}
else if (LayerDrops < MinForTarget)
{//if we do not have enough dropping to reach the target under any scenario, probability is 0
return "0.0";
}
else
{//We have enough dropping that reaching the target is possible, but not guaranteed
int BalancedDrops = LayerDrops > SlideCount ? LayerDrops - SlideCount : 0; //guaranteed to have this many on each side
int CriticalDrops = LayerDrops - (BalancedDrops << 1);//the number of drops relevant to the probablity of success
int NumToSucceed = MinForTarget - BalancedDrops;//How many must break our way for success
double SuccessProb = 0;//Probability that the number of diamonds sliding the same way is between NumToSucceed and CriticalDrops
double ProbI;
for (int I = NumToSucceed; I <= CriticalDrops; I++)
{
ProbI = Math.Pow(0.5, I); //Probability that I diamonds will slide the same way
SuccessProb += ProbI;
}
return SuccessProb.ToString();
}
}
Your general approach seems to fit the problem, though the calculation of the last probability is not completely correct.
Let me describe how I solved this. We are looking at pyramids. These pyramids can be assigned a layer, based on how many diamonds the pyramid has. A pyramid of layer 1 has only 1 diamond. A pyramid of layer 2 has 1 + 2 + 3 diamonds. A pyramid of layer 3 has 1 + 2 + 3 + 4 + 5 diamonds. A pyramid of layer n has 1 + 2 + 3 + ... + 2*n-1 diamonds, which equals (2 * n - 1) * n.
Given this, we can calculate the layer of the biggest pyramid we are able to build with a given number of diamonds:
layer = floor( ( sqrt( 1 + 8 * diamonds ) + 1 ) / 4 )
and the number of diamonds which are not needed in order to build this pyramid. These diamonds will start to fill the next bigger pyramid:
overflow = diamonds - layer * ( 2 * layer - 1 )
We can now see the following things:
If the point is within the layer layer, it will be covered, so p = 1.0.
If the point is not within the layer layer + 1 (i.e. the next bigger pyramid), it will not be covered, so p = 0.0.
If the point is within the the layer layer + 1, is might be covered, so 0 <= p <= 1.
Since we only need to solve the last problem, we can simplify the problem statement a little bit: Given are the two sides of the triangle, r and l. Each side has a fixed capacity, the maximum number of diamonds it can take. What is the probability for one configuration (nr, nl), where nr denotes the diamonds on the right side, nl denotes the diamonds on the left side and nr + nl = overflow.
This probability can be calculated using Bernoulli's Trails:
P( nr ) = binomial_coefficient( overflow, k ) * pow( 0.5, overflow )
However, this will fail in one case: If one side is completely filled with diamonds, the probabilities change. The probability, that the diamond falls on the completely filled side is now 0, while the probability for the other side is 1.
Assume the following case: Each side can take up to 4 diamonds, while 6 diamonds are still left. The interesting case is now P( 2 ), because in this case, the left side will take 4 diamonds.
Some examples how the 6 diamonds could fall down. r stands for the decision go right, while l stands for go left:
l r l r l l => For every diamond, the probability for each side was 0.5. This case doesn't differ from the previous case. The probability for exactly this case is pow( 0.5, 6 ). There are 4 different cases like this (rllllr, lrlllr, llrllr, lllrlr). There are 10 different cases like this. The number of cases is the number of ways one element can be chosen from 5: binomial_coefficient( 5, 2 ) = 10
l r l l l r => The last diamond was going to fall on the right side, because the left side was full. The last probability was 1 for the right side and 0 for the left side. The probability for exactly this case is pow( 0.5, 5 ). There are 4 different cases like this: binomial_coefficient( 4, 1 ) = 4
l l l l r r => The last two diamonds were going to fall on the right side, because the left side was full. The last two probabilities were 1 for the right side and 0 for the left side. The probability for exactly this case is pow( 0.5, 4 ). There is exactly one case like this, because binomial_coefficient( 3, 0 ) = 1.
The general algorithm is to assume, that the last 0, 1, 2, 3, ..., nr elements will go to the right side inevitably, then to calculate the probability for each of these cases (the last 0, 1, 2, 3, ..., nr probabilites will be 1) and multiply each probability with the number of different cases where the last 0, 1, 2, 3, ..., nr probabilities are 1.
See the following code. p will be the probability for the case that nr diamonds will go on the right side and the left side is full:
p = 0.0
for i in range( nr + 1 ):
p += pow( 0.5, overflow - i ) * binomial_coefficient( overflow - i - 1, nr - i )
Now that we can calculate the probabilities for each individual combinations (nr, nl), one can simply add all cases where nr > k, with k being the minimal number of diamonds for one side for which the required point is still covered.
See the complete python code I used for this problem: https://github.com/frececroka/codejam-2013-falling-diamonds/blob/master/app.py
Your assumption are over simplicistic. You can download the correct answers of the large dataset caluclated with my solution:
http://pastebin.com/b6xVhp9U
You have to calc all the possible combinations of diamonds that will occupy your point of interests. To do that I have used this formula:
https://math.stackexchange.com/a/382123/32707
You basically have to:
Calc the height of the pyramid (ie calc the FIXED diamonds)
Calc the number of the diamonds that can freely move on the left or on the right
Calc the probability (with sums of binomial coeff)
With the latter and the Point Y you can apply that formula to calc the probability.
Also don't worry if you are not able solve this problem because it was pretty tough. If you want my solution in PHP here it is:
Note that you have to calc if the point is inside the fixed pyramid of is outside the fixed pyramid, also you have to do other minor checks.
<?php
set_time_limit(0);
$data = file('2bl.in',FILE_IGNORE_NEW_LINES);
$number = array_shift($data);
for( $i=0;$i<$number;$i++ ) {
$firstLine = array_shift($data);
$firstLine = explode(' ',$firstLine);
$s = $firstLine[0];
$x = $firstLine[1];
$y = $firstLine[2];
$s = calcCase( $s,$x,$y );
appendResult($i+1,$s);
}
function calcCase($s,$x,$y) {
echo "S: [$s] P($x,$y)\n<br>";
$realH = round(calcH($s),1);
echo "RealHeight [$realH] ";
$h = floor($realH);
if (isEven($h))
$h--;
$exactDiamonds = progression($h);
movableDiamonds($s,$h,$exactDiamonds,$movableDiamonds,$unfullyLevel);
$widthLevelPoint = $h-$y;
$spacesX = abs($x) - $widthLevelPoint;
$isFull = (int)isFull($s,$exactDiamonds);
echo "Diamonds: [$s], isFull [$isFull], Height: [$h], exactDiamonds [$exactDiamonds], movableDiamonds [$movableDiamonds], unfullyLevel [$unfullyLevel] <br>
widthlevel [$widthLevelPoint],
distance from pyramid (horizontal) [$spacesX]<br> ";
if ($spacesX>1)
return '0.0';
$pointHeight = $y+1;
if ($x==0 && $pointHeight > $h) {
return '0.0';
}
if ($movableDiamonds==0) {
echo 'Fixed pyramid';
if ( $y<=$h && abs($x) <= $widthLevelPoint )
return '1.0';
else
return '0.0';
}
if ( !$isFull ) {
echo "Pyramid Not Full ";
if ($spacesX>0)
return '0.0';
if ($unfullyLevel == $widthLevelPoint)
return '0.5';
else if ($unfullyLevel > $widthLevelPoint)
return '0.0';
else
return '1.0';
}
echo "Pyramid full";
if ($spacesX<=0)
return '1.0';
if ($movableDiamonds==0)
return '0.0';
if ( $movableDiamonds > ($h+1) ) {
$otherDiamonds = $movableDiamonds - ($h+1);
if ( $otherDiamonds - $pointHeight >= 0 ) {
return '1.0';
}
}
$totalWays = totalWays($movableDiamonds);
$goodWays = goodWays($pointHeight,$movableDiamonds,$totalWays);
echo "<br>GoodWays: [$goodWays], totalWays: [$totalWays]<br>";
return sprintf("%1.7f",$goodWays / $totalWays);
}
function goodWays($pointHeight,$movableDiamonds,$totalWays) {
echo "<br>Altezza punto [$pointHeight] ";
if ($pointHeight>$movableDiamonds)
return 0;
if ( $pointHeight == $movableDiamonds )
return 1;
$good = sumsOfBinomial( $movableDiamonds, $pointHeight );
return $good;
}
function totalWays($diamonds) {
return pow(2,$diamonds);
}
function sumsOfBinomial( $n, $k ) {
$sum = 1; //> Last element (n;n)
for($i=$k;$i<($n);$i++) {
$bc = binomial_coeff($n,$i);
//echo "<br>Binomial Coeff ($n;$i): [$bc] ";
$sum += $bc;
}
return $sum;
}
// calculate binomial coefficient
function binomial_coeff($n, $k) {
$j = $res = 1;
if($k < 0 || $k > $n)
return 0;
if(($n - $k) < $k)
$k = $n - $k;
while($j <= $k) {
$res = bcmul($res, $n--);
$res = bcdiv($res, $j++);
}
return $res;
}
function isEven($n) {
return !($n&1);
}
function isFull($s,$exact) {
return ($exact <= $s);
}
function movableDiamonds($s,$h,$exact,&$movableDiamonds,&$level) {
$baseWidth = $h;
$level=$baseWidth;
//> Full pyramid
if ( isFull($s,$exact) ) {
$movableDiamonds = ( $s-$exact );
return;
}
$movableDiamonds = $s;
while( $level ) {
//echo "<br> movable [$movableDiamonds] removing [$level] <br>" ;
if ($level > $movableDiamonds)
break;
$movableDiamonds = $movableDiamonds-$level;
$level--;
if ($movableDiamonds<=0)
break;
}
return $movableDiamonds;
}
function progression($n) {
return (1/2 * $n *(1+$n) );
}
function calcH($s) {
if ($s<=3)
return 1;
$sqrt = sqrt(1+(4*2*$s));
//echo "Sqrt: [$sqrt] ";
return ( $sqrt-1 ) / 2;
}
function appendResult($caseNumber,$string) {
static $first = true;
//> Cleaning file
if ($first) {
file_put_contents('result.out','');
$first=false;
}
$to = "Case #{$caseNumber}: {$string}";
file_put_contents( 'result.out' ,$to."\n",FILE_APPEND);
echo $to.'<br>';
}

Distance between two numbers in looping sequence [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Assuming you have a sequence like this: 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, etc. Basically a sequence consisting of N numbers, repeating over and over.
What is the simplest algorithm for finding the distance/difference between two numbers in this sequence? For example the distance from 5 to 7 is +2 and the distance from 0 to 6 is -2. For a more high level view what I have a looping/repeating sequence number, and I need to find out how much "before" or "after" a number is of another on the closest path (fewest number between them).
Assuming X>Y:
dist(X, Y) = min { X-Y, N-(X-Y-1) }
Examples for N = 7:
dist(7, 5) = min {7-5, 7-(7-5-1)} = min {2, 6} = 2
dist(6, 0) = min {6-0, 7-(6-0-1)} = min {6, 2} = 2
dist(5, 1) = min {5-1, 7-(5-1-1)} = min {4, 4} = 4
The last example points a small flaw in your distance definition: Is dist(5, 1) = 4 or dist(5, 1) = -4 ? I've changed your definition a little bit to avoid negative distances (so my algorithm calculates the absolute value of the distance). If you want to keep your definition then make the distance negative if and only if the first argument of the min is greater than the second.
This is quite simple and work with consecutive and non consecutive numbers, maybe make it an extension method :
[TestFixture]
public class NumbersFixture
{
[Test]
public void FindDistance()
{
var numbers = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2 };
var num1 = 6;
var num2 = 0;
var from = numbers.IndexOf(num1);
var indexFound = numbers.FindIndex(from, f => f == num2);
var distance = from - indexFound;
var result = string.Format("{0}", distance);
Console.WriteLine(result);
}
}

Categories

Resources