Knitting Pattern Shorthand

Hardhash mapAlso known as Byte Pair Encoding (BPE) Merges

A knitting club writes patterns as long lists of stitches: k for knit, p for purl, yo for yarn over. Patterns repeat the same neighbours again and again, so the club invents shorthand. They find the pair of neighbouring stitches that appears most often, give it a single new symbol (k then p becomes kp), rewrite the pattern, and repeat.

This is byte pair encoding, the method many language models use to build their token vocabulary. Start from single characters, merge the most common neighbouring pair, repeat thousands of times, and common chunks of words become single tokens.

Your task

Write shorthand(stitches, merges). Repeat the following at most merges times:

  1. Count every pair of neighbouring tokens (tokens[i], tokens[i+1]) for every i. Overlapping pairs count separately, so [a, a, a] has the pair (a, a) twice.
  2. Pick the pair with the highest count. If several tie, pick the one whose first occurrence is furthest left. If no pair appears at least twice, stop.
  3. Scan left to right. Wherever that pair appears, replace the two tokens with one token, their concatenation. A token already used in a merge cannot be part of another merge in the same scan.

Return the final list of tokens.

shorthand(stitches: string[], merges: int) → string[]

Examples

Example 1
Input
stitches = ["k", "p", "k", "p", "yo", "k", "p"]
merges = 1
Output
["kp", "kp", "yo", "kp"]
Why

Pair counts: (k, p) 3, (p, k) 1, (p, yo) 1, (yo, k) 1. Merge (k, p) everywhere: ["kp", "kp", "yo", "kp"].

Example 2
Input
stitches = ["k", "p", "k", "p", "yo", "k", "p"]
merges = 3
Output
["kp", "kp", "yo", "kp"]
Why

After the first merge: [kp, kp, yo, kp]. Now (kp, kp), (kp, yo) and (yo, kp) each appear once. No pair appears twice, so stop early, even though 3 merges were allowed.

Example 3
Input
stitches = ["k", "k", "k", "p", "k", "k"]
merges = 2
Output
["kk", "k", "p", "kk"]
Why

(k, k) appears 3 times (positions 0, 1 and 4). Scanning left to right merges positions 0 and 1, then position 2 is a lone k, then p, then the last two k's merge: [kk, k, p, kk]. Second round: every pair appears once, so stop.

Constraints

  • 0 ≤ stitches.length ≤ 2,000
  • 0 ≤ merges ≤ 100
  • Each token is 1 to 10 lowercase letters.
Start with brute force

For each neighbouring pair, scan the whole list to count how often it appears, and keep the best. That is O(n²) per round. With 2,000 tokens and 100 rounds, that is up to 400 million comparisons.

A hash map counts every pair in a single O(n) pass. Real tokenizer training goes further and only updates the counts that a merge changes, because it runs tens of thousands of rounds on huge text.

Hints

0 of 4 shown

Walkthrough and solution

Unlocks when you pass every test. Stuck for a while? Looking is fine too, as long as you then close it and write the code yourself.

Ctrl+Enter runs

Run your code to see results here. Run checks the examples. Submit checks every test, including hidden edge cases.

Write code