Calculating variable distances

I’m attempting to write an algorithm that calculates the distance between vertebrae. The text parser already works perfectly in picking out vertebral references (cervical 6, c-6, c6, c six, cervical six).

It currently references a linear string array, and matches Vertebrae to their index, and then subtracts Min from Max. The solves 95% of cases.

The issue comes in from two scenarios:

  • Distance is not necessarily linear. L5 to Pelvis and L5 to Sacrum are both considered one level.
  • Genetic anomalies can produce extra vertebrae. Most people have 12 Thoracic vertebrae, some have up to 14.

If I only needed to solve one or the other, it wouldn’t an issue. I’m now looking at a complicated mess of workarounds to make this work, and I’m certain there is a simpler answer.

private static int CalculateLevelNumber(IEnumerable<string> levels)
{
    List<int> levelindexes = new List<int>();
    List<string> spinemap = new List<string> { "occiput", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10", "t11", "t12", "l1", "l2", "l3", "l4", "l5", "s1", "s2" };

    foreach(string level in levels)
    {
        levelindexes.Add(spinemap.IndexOf(level));
    }

    return levelindexes.Max() - levelindexes.Min();
}

Here is what I mean by ugly workaround:

private static int CalculateLevelNumber(IEnumerable<string> levels)
{
    List<int> levelindexes = new List<int>();
    List<string> spinemap = new List<string> { "occiput", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10", "t11", "t12", "l1", "l2", "l3", "l4", "l5", "s1", "s2" };

    if(levels.Contains("t15"))
    {
        spinemap.InsertRange(spinemap.IndexOf("t12"), new List<string> { "t13", "t14", "t15" });
    }
    else if(levels.Contains("t14"))
    {
        spinemap.InsertRange(spinemap.IndexOf("t12"), new List<string> { "t13", "t14" });
    }
    else if (levels.Contains("t13"))
    {
        spinemap.InsertRange(spinemap.IndexOf("t12"), new List<string> { "t13" });
    }

    foreach (string level in levels)
    {
        if(level == "pelvis" || level == "ilium")
            levelindexes.Add(spinemap.IndexOf("s1"));
        else
            levelindexes.Add(spinemap.IndexOf(level));
    }

    return levelindexes.Max() - levelindexes.Min();
}

3

Alright, for starters, I guess I would precompute several spinemap lists in advance, and keep them immutable during execution of the calculations, instead just picking the right one to use for each case.

To finish up, I’d use array of int instead of array of string for the spinemaps. I’d transform the levels from string form to an enum, and use that enum to index into spinemap. The spinemap arrays would store the int position directly at each enum level‘s index.

So, we’d have four(?) spinemaps as array of int position indexable by enum level, precomputed and unmodified during calculation.


There are any number of other possibilities, including defining a class to group names together with positions, which might take a bit more searching, but perhaps be more maintainable. We could also start with a set of easly maintained and readable definitions, and then build the precomputed data structures needed from that so we don’t have to do so much searching during calculation.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *