private static int CheckSequence(IFuzzyComparer <T> _Comparer, SequencePart _Subject, SequencePart _Target, int _LimitCheck = -1, int _SkipItems = 0) { int SubjectStart = _Subject.SequencePosition; SequencePart NextItem = _Subject.Next; SequencePart NextComparisonTarget = _Target.Next; int CorrectCount = 1; for (int i = 0; CorrectCount < _SkipItems; ++i) { NextItem = NextItem.Next; NextComparisonTarget = NextComparisonTarget.Next; CorrectCount++; } while (NextItem.SequencePosition != SubjectStart) { FuzzyCompareResult CompareResult = _Comparer.CompareItems(NextItem.SequenceValue, NextComparisonTarget.SequenceValue); if (CompareResult == FuzzyCompareResult.ExactMatch || CompareResult == FuzzyCompareResult.GreaterThanWithinMargins || CompareResult == FuzzyCompareResult.SmallerThanWithinMargins || CompareResult == FuzzyCompareResult.NotEqualUndefinedWithinMargins) { CorrectCount++; if (_LimitCheck > 0 && CorrectCount >= _LimitCheck) { break; } } else { break; } NextItem = NextItem.Next; NextComparisonTarget = NextComparisonTarget.Next; } return(CorrectCount); }
public LoopingSequence(T[] _Sequence) { if (_Sequence == null || _Sequence.Length < 1) { throw new Exception("A sequence must contain something"); } SequencePart[] temp = new SequencePart[_Sequence.Length]; for (int i = 0; i < temp.Length; i++) { temp[i] = new SequencePart(i, _Sequence[i]); Indexer.Add(i, temp[i]); } for (int i = 0; i < temp.Length; i++) { if (i == 0) { temp[i].Previous = temp[temp.Length - 1]; temp[i].Next = temp[i + 1]; } else if (i == temp.Length - 1) { temp[i].Previous = temp[i - 1]; temp[i].Next = temp[0]; } else { temp[i].Previous = temp[i - 1]; temp[i].Next = temp[i + 1]; } } Parts = temp.OrderBy(x => x.SequenceValue).ThenBy(x => x.SequencePosition).ToArray(); }
public List <SequenceMatchScore> CompareSequence(LoopingSequence <T> _OtherSeqence, IFuzzyComparer <T> _Comparer, out int _ThisBestStartIndex, out int _BestMatchScore, out int _BestOtherMatchIndex, int _CandidateConsiderationLength = 1, int _MinScore = -1) { List <SequenceMatchScore> Scores = new List <SequenceMatchScore>(); Parallel.For(0, Parts.Length, (s) => { SequencePart Subject = this.Parts[s]; int CandidateGatherPoint = -1; int LowerBound = 0; int UpperBound = _OtherSeqence.Parts.Length - 1; //Do binary search for start point while (LowerBound <= UpperBound) { int Midpoint = (LowerBound + UpperBound) / 2; FuzzyCompareResult Result = _Comparer.CompareItems(Subject.SequenceValue, _OtherSeqence.Parts[Midpoint].SequenceValue); if (Result == FuzzyCompareResult.ExactMatch || Result == FuzzyCompareResult.GreaterThanWithinMargins || Result == FuzzyCompareResult.SmallerThanWithinMargins || Result == FuzzyCompareResult.NotEqualUndefinedWithinMargins) { CandidateGatherPoint = Midpoint; break; } else if (Result == FuzzyCompareResult.SmallerThan) { UpperBound = Midpoint - 1; } else { LowerBound = Midpoint + 1; } } if (CandidateGatherPoint != -1) { List <SequencePart> Candidates = new List <SequencePart>(); int InitialCorrect = CheckSequence(_Comparer, Subject, _OtherSeqence.Parts[CandidateGatherPoint], _CandidateConsiderationLength); if (InitialCorrect >= _CandidateConsiderationLength) { Candidates.Add(_OtherSeqence.Parts[CandidateGatherPoint]); } bool FoundEnd = false; int SearchIndex = CandidateGatherPoint + 1; //Check above starting point for matches while (!FoundEnd) { if (SearchIndex >= _OtherSeqence.Parts.Length) { FoundEnd = true; break; } FuzzyCompareResult CompareResult = _Comparer.CompareItems(Subject.SequenceValue, _OtherSeqence.Parts[SearchIndex].SequenceValue); if (CompareResult == FuzzyCompareResult.ExactMatch || CompareResult == FuzzyCompareResult.GreaterThanWithinMargins || CompareResult == FuzzyCompareResult.SmallerThanWithinMargins || CompareResult == FuzzyCompareResult.NotEqualUndefinedWithinMargins) { int CorrectCount = CheckSequence(_Comparer, Subject, _OtherSeqence.Parts[SearchIndex], _CandidateConsiderationLength); if (_CandidateConsiderationLength > 0 && _CandidateConsiderationLength <= CorrectCount) { Candidates.Add(_OtherSeqence.Parts[SearchIndex]); } } else { FoundEnd = true; break; } SearchIndex++; } FoundEnd = false; SearchIndex = CandidateGatherPoint - 1; //Check below starting point for matches while (!FoundEnd) { if (SearchIndex < 0) { FoundEnd = true; break; } FuzzyCompareResult CompareResult = _Comparer.CompareItems(Subject.SequenceValue, _OtherSeqence.Parts[SearchIndex].SequenceValue); if (CompareResult == FuzzyCompareResult.ExactMatch || CompareResult == FuzzyCompareResult.GreaterThanWithinMargins || CompareResult == FuzzyCompareResult.SmallerThanWithinMargins || CompareResult == FuzzyCompareResult.NotEqualUndefinedWithinMargins) { int CorrectCount = CheckSequence(_Comparer, Subject, _OtherSeqence.Parts[SearchIndex], _CandidateConsiderationLength); if (_CandidateConsiderationLength > 0 && _CandidateConsiderationLength <= CorrectCount) { Candidates.Add(_OtherSeqence.Parts[SearchIndex]); } } else { FoundEnd = true; break; } SearchIndex--; } Parallel.For(0, Candidates.Count, (i) => { SequencePart Target = Candidates[i]; int CorrectCount = CheckSequence(_Comparer, Subject, Target, -1, _CandidateConsiderationLength); if ((_MinScore == -1) || (_MinScore >= 0 && CorrectCount >= _MinScore)) { SequenceMatchScore score = new SequenceMatchScore(); score.ThisBestIndex = Subject.SequencePosition; score.BestMatchLengthOther = CorrectCount; score.BestMatchIndexOther = Candidates[i].SequencePosition; lock (Scores) { Scores.Add(score); } } }); } }); int Best = -1; int BestIndex = -1; int ThisBestIndex = -1; for (int i = 0; i < Scores.Count; ++i) { if (Scores[i].BestMatchLengthOther > Best) { Best = Scores[i].BestMatchLengthOther; BestIndex = Scores[i].BestMatchIndexOther; ThisBestIndex = Scores[i].ThisBestIndex; } } _BestMatchScore = Best; _BestOtherMatchIndex = BestIndex; _ThisBestStartIndex = ThisBestIndex; return(Scores); }
static IEnumerable <Range> SequenceIterator ( string aInputText, string aSeparator = CConvertOptions.DefaultSeparator, string aJoint = CConvertOptions.DefaultJoint ) { if (aInputText.Length <= 0) { yield break; } var Separators = new string[] { aSeparator }; var Joints = new string[] { aJoint }; var AllowedChars = new char[] { ' ' }; var NumberGroup = new Range(0, 0); foreach (string SequencePart in aInputText.Split(Separators, StringSplitOptions.None)) { var RangeParts = SequencePart.Split(Joints, StringSplitOptions.None); string MinPart, MaxPart; if (RangeParts.Length >= 3) { goto Error; } if (RangeParts.Length > 1) { MinPart = RangeParts[0].Trim(AllowedChars); MaxPart = RangeParts[1].Trim(AllowedChars); } else { MinPart = RangeParts[0].Trim(AllowedChars); MaxPart = MinPart; } if (!int.TryParse(MinPart, out int MinValue)) { goto Error; } if (!int.TryParse(MaxPart, out int MaxValue)) { goto Error; } NumberGroup.Reset(MinValue, MaxValue); yield return(NumberGroup); } yield break; Error: throw new ArgumentException ( $"The input set contains invalid data. " + $"Set value in invalid format.", "InputText" ); }