Jelajahi Sumber

Rewrite to handle corner case start == finish + 1

Rob Austein 7 bulan lalu
induk
melakukan
42e215baae
3 mengubah file dengan 34 tambahan dan 18 penghapusan
  1. 6 10
      rfc1982_serial_number.py
  2. 12 4
      test1.py
  3. 16 4
      test2.py

+ 6 - 10
rfc1982_serial_number.py

@@ -40,12 +40,9 @@ class Serial:
         return f"{int(self):{len(str(self.modulus))}d}"
 
 def find_intermediate(start, finish):
-    if start < finish:
-        return None
-    else:
-        wrap = start + ((Serial.modulus >> 1) - 2)
-        assert start < wrap and wrap < finish
-        return wrap
+    while not (start < finish): # sic: serial numbers are not (quite) integers
+        start += ((Serial.modulus >> 1) - 1)
+        yield start
 
 def main():
     from argparse import ArgumentParser
@@ -55,14 +52,13 @@ def main():
     ap.add_argument("finish", type = Serial)
     args = ap.parse_args()
 
-    wrap = find_intermediate(args.start, args.finish)
-
     print(f"Start at {args.start!s}")
 
-    if wrap is None:
+    if args.start < args.finish:
         print("No step needed")
     else:
-        print(f"Step via {wrap!s}")
+        for wrap in find_intermediate(args.start, args.finish):
+            print(f"Step via {wrap!s}")
 
     print(f"End at   {args.finish!s}")
 

+ 12 - 4
test1.py

@@ -1,9 +1,14 @@
 #!/usr/bin/env python3
 
 from rfc1982_serial_number import Serial, find_intermediate
+from argparse import ArgumentParser
 from random import randint
 
-for test in range(10000):
+ap = ArgumentParser()
+ap.add_argument("iterations", type = int, default = 100000, nargs = "?")
+args = ap.parse_args()
+
+for test in range(args.iterations):
     i1 = Serial(randint(0, Serial.modulus - 1))
     i2 = Serial(randint(0, Serial.modulus - 1))
 
@@ -13,8 +18,11 @@ for test in range(10000):
         int(i1) ^ int(i2) == Serial.modulus >> 1
     
     step = [i1, i2]
-    wrap = find_intermediate(i1, i2)
-    if wrap is not None:
-        step.insert(1, wrap)
+    for wrap in find_intermediate(i1, i2):
+        assert wrap > step[-2]
+        step.insert(-1, wrap)
+
+    for i in range(len(step) - 1):
+        assert step[i] < step[i + 1]
 
     print(" => ".join(str(s) for s in step))

+ 16 - 4
test2.py

@@ -4,9 +4,21 @@ from rfc1982_serial_number import Serial
 from random import randint
 from subprocess import run
 
-for test in range(10000):
-    i1 = randint(0, Serial.modulus - 1)
-    i2 = randint(0, Serial.modulus - 1)
-    cmd = "./rfc1982_serial_number.py", str(i1), str(i2)
+def test(n, cmd):
     print(f"\nTest: {test}: {cmd[0]} {cmd[1]} {cmd[2]}")
     run(cmd)
+
+for n in range(100):
+    i1 = randint(0, Serial.modulus - 1)
+    i2 = randint(0, Serial.modulus - 1)
+    test(n, ("./rfc1982_serial_number.py", str(i1), str(i2)))
+
+for n in range(10):
+    i1 = randint(0, Serial.modulus - 1)
+    i2 = i1 ^ (Serial.modulus >> 1)
+    test(n, ("./rfc1982_serial_number.py", str(i1), str(i2)))
+
+for n in range(10):
+    i1 = randint(0, Serial.modulus - 1)
+    i2 = (i1 + Serial.modulus - 1) & (Serial.modulus - 1)
+    test(n, ("./rfc1982_serial_number.py", str(i1), str(i2)))