using System.Collections;
namespace Common.Distance;
public static class Calculator
{
///
/// Calculates the levenshtein distance between two enumerables
///
///
///
///
///
public static double GetDistance(T reference, T? hypothesis)
where T : IEnumerable
{
// Setup
var refArr = reference.Cast().ToArray();
var hypArr = hypothesis?.Cast().ToArray() ?? Array.Empty();
var distance = new int[refArr.Length + 1, hypArr.Length + 1];
// Fill matrix
for (var x = 0; x <= refArr.Length; x++)
{
// Reference on X axis
distance[x, 0] = x;
}
for (var y = 0; y <= hypArr.Length; y++)
{
// Hypothesis on Y axis
distance[0, y] = y;
}
// Calculate distance
for (var x = 0; x < refArr.Length; x++)
{
for (var y = 0; y < hypArr.Length; y++)
{
// BL Cost depends on whether the two elements are equal
var cost = Equals(refArr[x], hypArr[y]) ? 0 : 1;
// Apply distance mask
var c1 = distance[x, y] + cost; // Bottom left
var c2 = distance[x, y + 1] + 1; // Top left
var c3 = distance[x + 1, y] + 1; // Bottom right
distance[x + 1, y + 1] = Min(c1, c2, c3); // Top right
}
}
return distance[refArr.Length, hypArr.Length];
}
private static T Min(params T[] values)
{
if (!values.Any())
{
throw new ArgumentException("Array cannot be empty", nameof(values));
}
return values.Min()!;
}
}