beam: convert test_levenshtein to unittest.TestCase so lane gate collects it

This commit is contained in:
beam committed 2026-10-25 22:14:26 +00:00
1 parent 090e17e134
commit aa00cd8127
1 file changed
+58 -50
+58 -50
View File
@@ -1,63 +1,71 @@
import random, string import random
import unittest
from levenshtein import edit_distance, ops from levenshtein import edit_distance, ops
def brute(a, b): def brute(a, b):
n, m = len(a), len(b) n, m = len(a), len(b)
dp = [[0]*(m+1) for _ in range(n+1)] dp = [[0] * (m + 1) for _ in range(n + 1)]
for i in range(n+1): dp[i][0]=i for i in range(n + 1):
for j in range(m+1): dp[0][j]=j dp[i][0] = i
for i in range(1,n+1): for j in range(m + 1):
for j in range(1,m+1): dp[0][j] = j
c = 0 if a[i-1]==b[j-1] else 1 for i in range(1, n + 1):
dp[i][j]=min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+c) for j in range(1, m + 1):
c = 0 if a[i - 1] == b[j - 1] else 1
dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + c)
return dp[n][m] return dp[n][m]
def test_known(): class TestLevenshtein(unittest.TestCase):
cases = [("kitten","sitting",3),("","abc",3),("abc","",3), def test_known(self):
("flaw","lawn",2),("same","same",0),("a","b",1), cases = [("kitten", "sitting", 3), ("", "abc", 3), ("abc", "", 3),
("","",-0 if False else 0)] ("flaw", "lawn", 2), ("same", "same", 0), ("a", "b", 1),
for a,b,e in cases: ("", "", 0)]
assert edit_distance(a,b)==e, (a,b,edit_distance(a,b),e) for a, b, e in cases:
with self.subTest(a=a, b=b):
self.assertEqual(edit_distance(a, b), e)
def test_random_vs_brute(self):
rng = random.Random(42)
alpha = "ab"
for _ in range(2000):
la = rng.randint(0, 8)
lb = rng.randint(0, 8)
a = "".join(rng.choice(alpha) for _ in range(la))
b = "".join(rng.choice(alpha) for _ in range(lb))
with self.subTest(a=a, b=b):
self.assertEqual(edit_distance(a, b), brute(a, b))
def test_random_vs_brute(): def test_ops_roundtrip(self):
rng = random.Random(42) rng = random.Random(7)
alpha = "ab" for _ in range(500):
for _ in range(2000): a = "".join(rng.choice("ab") for _ in range(rng.randint(0, 6)))
la = rng.randint(0,8); lb = rng.randint(0,8) b = "".join(rng.choice("ab") for _ in range(rng.randint(0, 6)))
a = "".join(rng.choice(alpha) for _ in range(la)) o = ops(a, b)
b = "".join(rng.choice(alpha) for _ in range(lb)) out = []
assert edit_distance(a,b)==brute(a,b), (a,b) i = 0
j = 0
for tag in o:
def test_ops_roundtrip(): if tag == "=":
rng = random.Random(7) self.assertEqual(a[i], b[j])
for _ in range(500): out.append(a[i])
a = "".join(rng.choice("ab") for _ in range(rng.randint(0,6))) i += 1
b = "".join(rng.choice("ab") for _ in range(rng.randint(0,6))) j += 1
o = ops(a,b) elif tag == "S":
# apply ops to a -> should yield b out.append(b[j])
out = [] i += 1
i = 0 # index into a j += 1
j = 0 # index into b elif tag == "D":
for tag in o: i += 1
if tag == "=": elif tag == "I":
assert a[i] == b[j] out.append(b[j])
out.append(a[i]); i += 1; j += 1 j += 1
elif tag == "S": self.assertEqual("".join(out), b, (a, b, o, "".join(out)))
out.append(b[j]); i += 1; j += 1 edits = sum(1 for t in o if t in ("S", "D", "I"))
elif tag == "D": self.assertEqual(edits, edit_distance(a, b), (a, b, edits, edit_distance(a, b)))
i += 1
elif tag == "I":
# need current b char; find next unconsumed b
out.append(b[j]); j += 1
assert "".join(out) == b, (a,b,o,"".join(out))
edits = sum(1 for t in o if t in ("S","D","I"))
assert edits == edit_distance(a,b), (a,b,edits,edit_distance(a,b))
if __name__ == "__main__": if __name__ == "__main__":
test_known(); test_random_vs_brute(); test_ops_roundtrip() unittest.main()
print("ALL OK")