using Godot; using Rokojori.Extensions; namespace Rokojori; public class LevenshteinFuzzyMatch { public int lowestDistance; public int index; } public class LevenshteinDistance { protected static int[,] GetMatrix( int aLength, int bLength ) { var matrix = new int[ aLength + 1, bLength + 1]; for ( var i = 0; i <= aLength; i++ ) { matrix[ i, 0 ] = i; } for ( var j = 0; j <= bLength; j++ ) { matrix[ 0, j ] = j; } return matrix; } public static LevenshteinFuzzyMatch ComputeFuzzyMatch( string value, string matcher ) { var result = new LevenshteinFuzzyMatch(); if ( matcher.Length >= value.Length ) { result.index = 0; result.lowestDistance = LevenshteinDistance.Compute( value, matcher ); } else { var offsets = value.Length - matcher.Length; for ( var i = 0; i < offsets; i++ ) { var subValue = value.Substring( i, matcher.Length ); var distance = LevenshteinDistance.Compute( subValue, matcher ); if ( i == 0 ) { result.index = 0; result.lowestDistance = distance; continue; } if ( distance < result.lowestDistance ) { result.index = i; result.lowestDistance = distance; } } } return result; } public static int Compute( string a, string b ) { var aLength = a.Length; var bLength = b.Length; if ( aLength == 0 ) { return bLength; } if ( bLength == 0 ) { return aLength; } var evaluationMatrix = LevenshteinDistance.GetMatrix( aLength, bLength ); for ( var i = 1; i <= aLength; i++ ) { for ( var j = 1; j <= bLength; j++ ) { var isSame = b[ j - 1 ] == a[ i - 1 ]; var isDifferentCost = isSame ? 0 : 1; var insertionCost = evaluationMatrix[ i - 1, j ] + 1; var deletionCost = evaluationMatrix[ i , j - 1 ] + 1; var substitutionCost = evaluationMatrix[ i - 1, j - 1 ] + isDifferentCost; evaluationMatrix[ i , j ] = Mathf.Min( Mathf.Min( insertionCost, deletionCost ), substitutionCost ); } } return evaluationMatrix[ aLength, bLength ]; } }