~/problems / Arrays & hashing / Hash maps and counting

Simplified git diff

hard 2 levels ~70 min Jane Street

Level 1 Find a line both files share exactly once

Diff tools like git diff --patience start by looking for anchor lines: lines that are unmistakable in both versions of a file.

You get the old and new versions of a file as lists of lines, lines1 and lines2. Call a string a unique common line when it occurs exactly once in lines1 and exactly once in lines2. So a line that shows up twice in lines1 is ruled out no matter what lines2 contains, and vice versa.

Implement:

def unique_common_line(lines1: list[str], lines2: list[str]) -> list[int]

Return [i, j] where lines1[i] == lines2[j] is a unique common line. If there are several, any one will do. If there is none, return [-1, -1].

old = ["import os", "", "def run():", "    pass", ""]
new = ["", "def run():", "    return 0", ""]
unique_common_line(old, new)          # [2, 1]   "def run():" ("" is repeated, "import os" is gone)

unique_common_line(["x", "y", "x"], ["x", "z"])   # [-1, -1]   "x" appears twice in the first list
unique_common_line([], ["a"])                      # [-1, -1]

Lines are compared as whole strings (whitespace counts). Files can have 200,000 lines, so counting each line with list.count or list.index inside a loop is far too slow.

Show hint

Count every line in each list with a dictionary (or collections.Counter), remember where each line of lines2 sits, then scan lines1 once.

Level 2 unlocks when level 1 passes.

Topic: Hash maps and counting. Counter/defaultdict, complement lookups, prefix-sum + hash map.

Read the visual guide
0:00
Ctrl ' run · Ctrl ↵ submit
esc