Skip to content

Repeated pattern letters are sometimes free: "aaaaaaaaaab" scores the same as an exact "ab" and outranks "abx" #89

Description

@matt-edmondson

What's wrong

In CalculateScoreCore (FuzzySearch/Fuzzy.cs ~223-260), a subject character that re-matches the current best letter (rematch) is charged unmatchedLetterPenalty only when its newScore >= bestLetterScore. When it scores lower, no branch charges it anything. It still sets prevMatched = true, so the character after it also gets the adjacency bonus.

Whether a repeated letter costs anything therefore depends on the bonus earned by the letter it repeats. A first letter with the separator bonus (10) makes every later repeat free, because an adjacent repeat only ever scores 5.

Measured scores for pattern "ab" (current main)

Subject Score
ab 15
aab 15
aaaaaaaaaab 15
AAAAAAAAb 15
abx 14
abbbbbbbbbb 6
a_b 19
a_bbbbbbbbbb 19
  • aaaaaaaaaab ties the exact match and outranks abx, even though it has nine extra characters.
  • Repeated bs after ab cost 1 each, but the same repeats after a_b cost nothing.

Why it matters

The score is used for ranking, and the documented rule is that unmatched characters are penalized. Noise made of repeated letters can rank a candidate at or above an exact match, which misorders filter results. Earlier gist-derived scoring defects were fixed in #66 and #82; this one was carried over from the same original gist.

Suggested fix / acceptance criteria

Charge the penalty when a rematch loses as well:

if (newScore >= bestLetterScore)
{
    if (bestLetterIdx is not null) score += unmatchedLetterPenalty;
    ...
}
else
{
    score += unmatchedLetterPenalty;
}

This was tried on a local build. aab scores 14, aaaaaaaaaab scores 6 and a_bbbbbbbbbb scores 10; the other rows are unchanged, and all 51 existing tests still pass.

  • Add regression tests asserting Score("ab","ab") > Score("aab","ab"), Score("abx","ab") > Score("aaaaaaaaaab","ab"), and Score("a_b","ab") > Score("a_bbbbbbbbbb","ab").

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

readyFully specified; implement as written

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions