|
| 1 | +"""Module difflib -- helpers for computing deltas between objects. |
| 2 | +""" |
| 3 | + |
| 4 | +_looper_n = lambda elements: [any], n: int, func: (any, any) -> any, initial: any -> any { |
| 5 | + assert n >= 0 |
| 6 | + result = initial |
| 7 | + if n < len(elements): |
| 8 | + result = _looper_n(elements, n + 1, func, func(result, elements[n])) |
| 9 | + |
| 10 | + result |
| 11 | +} |
| 12 | + |
| 13 | +looper = lambda initial: any, elements: [any], func: (any, any) -> any -> any { |
| 14 | + _looper_n(elements, 0, func, initial) |
| 15 | +} |
| 16 | + |
| 17 | +looper_enumerate = lambda initial: any, elements: [any] | {str:}, func: (any, str | int, any) -> any -> any { |
| 18 | + looper(initial, [{"k" = k, "v" = v} for k, v in elements], lambda initial, value { |
| 19 | + func(initial, value.k, value.v) |
| 20 | + }) |
| 21 | +} |
| 22 | + |
| 23 | +for_each = lambda elements: [any], func: (any) { |
| 24 | + [func(i) for i in elements] |
| 25 | + Undefined |
| 26 | +} |
| 27 | + |
| 28 | +while_loop = lambda condition: ([any]) -> bool, body: ([any]) -> [any], vals: [any] -> [any] { |
| 29 | + """Do a while loop using the condition function, body function and variables with side effects that need to be modified in place, such as iteration variables, etc.""" |
| 30 | + vals if not condition(vals) else while_loop(condition, body, body(vals)) |
| 31 | +} |
| 32 | + |
| 33 | +list_set_index = lambda l: [], i: int, v { |
| 34 | + """Set the list `l` at index `i` with the value `v`""" |
| 35 | + l = l[:i:] + [v] + l[i + 1::] |
| 36 | + l |
| 37 | +} |
| 38 | + |
| 39 | +longest_common_subsequence = lambda a: [], b: [] -> [] { |
| 40 | + """Longest Common Subsequence (LCS) is a typical algorithm for calculating the length of the longest common subsequence between two sequences.""" |
| 41 | + # Build the lengths matrix for dp |
| 42 | + lengths = [[0] * (len(b) + 1) for _ in range(len(a) + 1)] |
| 43 | + lengths = looper_enumerate(lengths, a, lambda m, i, x { |
| 44 | + looper_enumerate(m, b, lambda v, j, y { |
| 45 | + list_set_index(v, i + 1, list_set_index(v[i + 1], j + 1, v[i][j] + 1 if x == y else max(v[i + 1][j], v[i][j + 1]))) |
| 46 | + }) |
| 47 | + }) |
| 48 | + vals = [len(a), len(b), []] |
| 49 | + # Read the substrings out from the matrix |
| 50 | + while_loop(lambda vals: [any] { |
| 51 | + vals[0] != 0 and vals[1] != 0 |
| 52 | + }, lambda vals: [any] { |
| 53 | + x = vals[0] |
| 54 | + y = vals[1] |
| 55 | + result = vals[2] |
| 56 | + if lengths[x][y] == lengths[x - 1][y]: |
| 57 | + x -= 1 |
| 58 | + elif lengths[x][y] == lengths[x][y - 1]: |
| 59 | + y -= 1 |
| 60 | + else: |
| 61 | + assert a[x - 1] == b[y - 1], "{} != {}".format(a[x - 1], b[y - 1]) |
| 62 | + result = [a[x - 1]] + result |
| 63 | + x -= 1 |
| 64 | + y -= 1 |
| 65 | + [x, y, result] |
| 66 | + }, vals)[-1] |
| 67 | +} |
| 68 | + |
| 69 | +ndiff = lambda a: [str], b: [str] -> str { |
| 70 | + """Compare a and b (lists of strings); return a Differ-style delta string.""" |
| 71 | + lcs = longest_common_subsequence(a, b) |
| 72 | + # while loop variabels: [i, j, lcs, diff_str] |
| 73 | + vals = [0, 0, lcs, ""] |
| 74 | + len_a = len(a) |
| 75 | + len_b = len(b) |
| 76 | + while_loop(lambda vals { |
| 77 | + vals[0] < len_a or vals[1] < len_b |
| 78 | + }, lambda vals { |
| 79 | + i = vals[0] |
| 80 | + j = vals[1] |
| 81 | + lcs = vals[2] |
| 82 | + diff_str = vals[3] |
| 83 | + if i < len(a) and j < len(b) and a[i] == b[j]: |
| 84 | + diff_str += " " + a[i] + "\n" |
| 85 | + i += 1 |
| 86 | + j += 1 |
| 87 | + elif j < len(b) and (not lcs or i >= len(a) or a[i] != lcs[0]): |
| 88 | + diff_str += "+ " + b[j] + "\n" |
| 89 | + j += 1 |
| 90 | + elif i < len(a) and (not lcs or j >= len(b) or b[j] != lcs[0]): |
| 91 | + diff_str += "- " + a[i] + "\n" |
| 92 | + i += 1 |
| 93 | + else: |
| 94 | + if lcs: |
| 95 | + lcs = lcs[1:] |
| 96 | + if i < len(a): |
| 97 | + i += 1 |
| 98 | + if j < len(b): |
| 99 | + j += 1 |
| 100 | + |
| 101 | + [i, j, lcs, diff_str] |
| 102 | + }, vals)[-1] |
| 103 | +} |
| 104 | + |
| 105 | +diff = lambda a: str, b: str { |
| 106 | + """Compare a and b (string type); return a Differ-style delta string.""" |
| 107 | + ndiff(a.splitlines(), b.splitlines()) |
| 108 | +} |
0 commit comments