| Bytes | Lang | Time | Link |
|---|---|---|---|
| 095 | Charcoal | 250908T110430Z | Neil |
| 045 | Jelly | 250907T124601Z | Jonathan |
Charcoal, 95 bytes
≔⪪S θ≔⊟Φθ№ι#η⊞υ⟦⁰χ⁻η#⟧F⁻θ⟦η⟧«≔¬⌕ι⁻η#ζ≔ιεFη«≧⁺¬¬№εκζ≔✂ε⊕⌕εκLε¹ε»⊞υ⟦ζ±Lι±⌕⊞O⮌…θ⌕θηιι№θι±⌕θιι⟧»⊟⌈υ
Try it online! Link is to verbose version of code. Explanation:
≔⪪S θ≔⊟Φθ№ι#η
Split the input into words and find the cursor word w.
⊞υ⟦⁰χ⁻η#⟧
w counts as the shortest word having no matching letters. This prioritises it over words with no matching letters but words with at least one matching letter take priority over w.
F⁻θ⟦η⟧«
Loop over the other words.
≔¬⌕ι⁻η#ζ
Prioritise a word that w is a prefix of. (This word will already have all of the letters of w in order, but it just needs a little extra boost.)
≔ιεFη«≧⁺¬¬№εκζ≔✂ε⊕⌕εκLε¹ε»
Count how many letters of w appear in the word in order.
⊞υ⟦ζ±Lι±⌕⊞O⮌…θ⌕θηιι№θι±⌕θιι⟧
Push this and all of the tiebreak values to the list of results.
»⊟⌈υ
Output the word that is the best match.
Jelly, 45 bytes
RFḟ@ḣ1⁸;
ẹⱮŻç/⁼⁹Jݤ,LƲʋÐṀ⁹fƇLÐṂfṚȯÆṃ'{ʋ⁸ḣ⁵¤Ḣȯ
A full program that accepts the existing words, e, the word at the cursor, w, and the zero index of w, i, and prints the result to stdout.
Try it online! Or see the test-suite (employs the register, ®, in place of ⁵ to allow multiple tests.).
How?
ẹⱮŻç/⁼⁹Jݤ,LƲʋÐṀ⁹fƇ... - Main Link: e, w
ʋÐṀ⁹ - keep those x of e maximal under f(x, w):
ẹⱮ - all 1-indices of each c of w in x
Ż - prefix this list of lists with a zero
ç/ - reduce by last Link (RFḟ@ḣ1⁸;) as a dyad, see below
-> MatchIndices
Ʋ - last four links as a monad - f(MatchIndices)
⁼ - {MatchIndices} equals...
⁹Jݤ - ...indices of w prefixed with a zero? -> StartsWithW
, - paired with...
L - length -> [StartsWithW, MatchCount]
fƇ - only keep those with any match
-> PotentialMatches (ready for tie-breaks)
RFḟ@ḣ1⁸; - Helper Link, get MatchIndices: CurrentMatchIndices, NextIndices = [e.indices_of(c)]
R - {CurrentMatchIndices} Range -> [[1..v] for v in CurrentMatchIndices]
F - flatten
ḟ@ - filter from {NextIndices}
ḣ1 - head to 1-index 1 (no-op given an empty list)
⁸; - concatenate to {CurrentMatchIndices}
LÐṂfṚȯÆṃ'{ʋ⁸ḣ⁵¤Ḣȯ - ...Main Link continued:PotentialMatches
LÐṂ - keep those of minimal length -> ShortestMatches
⁸ḣ⁵¤ - get WordsLeftOfCursor
ʋ - last four links as a monad -> f(ShortestMatches, WordsLeftOfCursor):
f - {ShortestMatches} filter keep {WordsLeftOfCursor}
Ṛ - reverse
ȯ - logical OR... (i.e. if empty)
Æṃ'{ - ...mode of {ShortestMatches} -> Most frequent(s), in left-right order
Ḣ - head -> WinningMatch or 0 if none found
ȯ - logical OR {w}
- implicit print