diff --git a/_code/algorithm_c.py b/_code/algorithm_c.py index 2302ed6..af18c1d 100644 --- a/_code/algorithm_c.py +++ b/_code/algorithm_c.py @@ -37,6 +37,18 @@ def to_int(self): def to_hex(self) -> int: hex_str = self.to_str() return int(hex_str, 16) + + def shift1(self): + '''shift x as hex left by 1 bit and add the prefix''' + shifted_str = self.to_str() + shifted_str = shifted_str[1:] + shifted_str[0] + return Alpha.from_str(shifted_str, self.m) + + def rshift1(self): + '''shift x as hex right by 1 bit and add the suffix''' + shifted_str = self.to_str() + shifted_str = shifted_str[-1] + shifted_str[:-1] + return Alpha.from_str(shifted_str, self.m) class ThreeLines: def __init__(self, m, mask): @@ -46,7 +58,7 @@ def __init__(self, m, mask): self.base_power_4 = m ** 4 self.index = [-1] * self.base_power_4 self.mem = [0] * self.base_power_4 - self.tail = [0] * self.base_power_4 + self.len = [0] * self.base_power_4 # 0 for empty list, -1 for closed list self.mask = mask self.shift = self.calculate_shift(mask) @@ -69,9 +81,9 @@ def add(self, x): # x is hex number if self.index[x] == -1: st = self.start(x) - self.index[x] = st + self.tail[st] + self.index[x] = st + self.len[st] self.mem[self.index[x]] = x - self.tail[st] += 1 + self.len[st] += 1 def __len__(self): return sum([self.mem[i] != -1 for i in range(self.base_power_4)]) @@ -79,16 +91,16 @@ def __len__(self): def remove(self, x): if self.index[x] != -1: st = self.start(x) - last_element = self.mem[self.tail[st] - 1] + last_element = self.mem[self.len[st] - 1] pos = self.index[x] self.mem[pos] = last_element self.index[last_element] = pos self.index[x] = -1 - self.tail[st] -= 1 + self.len[st] -= 1 def ss_len(self, x): st = self.start(x) - return self.tail[st] + return self.len[st] def __iter__(self): for i in range(self.base_power_4): @@ -98,6 +110,40 @@ def __iter__(self): def __contains__(self, x): return self.index[x] != -1 +class CL(ThreeLines): + def __init__(self, m): + super().__init__(m, 0xFFFF) + self._st = [-1] * self.base_power_4 + self._mem = [-1] * self.base_power_4 + for i in range(self.base_power_4): + if self._st[i] != -1: + continue + st_alf = self.start_alpha(i) + st_idx = st_alf.to_int() // 4 * 4 + candidates = [] + for j in range(4): + candidates.append(st_alf.to_int()) + st_alf = st_alf.shift1() + if len(set(candidates)) != 4: + continue + while self._mem[st_idx] != -1: + st_idx += 4 + for i, candidate in enumerate(candidates): + self._mem[st_idx+i] = candidate + self._st[candidate] = st_idx + + def start_alpha(self, x): + alf = Alpha(x, self.m) + min_alf = alf + for i in range(n-1): + alf = alf.shift1() + if alf.to_hex() < min_alf.to_hex(): + min_alf = alf + return min_alf + + def start(self, x): + return self._st[x] + class CommaFreeCode: def __init__(self, m, g): self.m = m @@ -111,7 +157,7 @@ def __init__(self, m, g): self.s1 = ThreeLines(m, 0x000F) self.s2 = ThreeLines(m, 0x00FF) self.s3 = ThreeLines(m, 0x0FFF) - # self.cl = ThreeLines(m, 0xFFFF) + self.cl = CL(m) self.alf = [0] * 16**3 * self.m self.stamp = [0] * self.memory_size self.sigma = 0 @@ -149,9 +195,12 @@ def initialize(self): self.s1.add(i) self.s2.add(i) self.s3.add(i) - # for i in range(self.base_power_4): - # if self.state[i] != BLUE or self. - # self.cl[self.cl(al.to_hex())].add(i) + pr_code = self.cl.start_alpha(i) + self.cl.add(pr_code.to_int()) + for j in range(n-1): + pr_code = pr_code.shift1() + if self.state[pr_code.to_int()] != RED: + self.cl.add(pr_code.to_int()) for i in range(self.code_length): self.free[i] = i @@ -186,10 +235,6 @@ def suffix2(self, alpha): def suffix3(self, alpha): return (alpha & 0x0FFF) << 4 - def cl(self, alpha): - # Implement the logic to calculate cl(alpha) - return alpha - def search(self): self.level = 1 while True: diff --git a/_code/test_algorithm_c.py b/_code/test_algorithm_c.py index 1ab1ad7..6ef8df3 100644 --- a/_code/test_algorithm_c.py +++ b/_code/test_algorithm_c.py @@ -2,129 +2,143 @@ from algorithm_c import CommaFreeCode, Alpha, RED class TestCommaFreeCode(unittest.TestCase): - def test_p1_addition(self): - m = 2 - g = 57 - code = CommaFreeCode(m, g) + # def test_p1_addition(self): + # m = 2 + # g = 57 + # code = CommaFreeCode(m, g) - code.initialize() + # code.initialize() - for i in range(code.base_power_4): - al = Alpha(i, m) - alf = code.prefix(al.to_hex()) - if code.state[i] != RED: - self.assertIn(i, code.p1, f"Value {i} not found in p1[{alf}]") - self.assertGreater(len(code.p1), 0, f"p1[{alf}] is unexpectedly empty") - else: - self.assertNotIn(i, code.p1, f"Unexpected value {i} found in p1[{alf}]") - self.assertEqual(code.p1.ss_len(0), 5) - self.assertEqual(code.p1.ss_len(0b1000), 5) + # for i in range(code.base_power_4): + # al = Alpha(i, m) + # alf = code.prefix(al.to_hex()) + # if code.state[i] != RED: + # self.assertIn(i, code.p1, f"Value {i} not found in p1[{alf}]") + # self.assertGreater(len(code.p1), 0, f"p1[{alf}] is unexpectedly empty") + # else: + # self.assertNotIn(i, code.p1, f"Unexpected value {i} found in p1[{alf}]") + # self.assertEqual(code.p1.ss_len(0), 5) + # self.assertEqual(code.p1.ss_len(0b1000), 5) - def test_p2_addition(self): - m = 2 - g = 57 - code = CommaFreeCode(m, g) + # def test_p2_addition(self): + # m = 2 + # g = 57 + # code = CommaFreeCode(m, g) - code.initialize() + # code.initialize() - for i in range(code.base_power_4): - al = Alpha(i, m) - alf = code.prefix2(al.to_hex()) - if code.state[i] != RED: - self.assertIn(i, code.p2, f"Value {i} not found in p2[{alf}]") - self.assertGreater(len(code.p2), 0, f"p2[{alf}] is unexpectedly empty") - else: - self.assertNotIn(i, code.p2, f"Unexpected value {i} found in p2[{alf}]") - self.assertEqual(code.p2.ss_len(0), 3) - self.assertEqual(code.p2.ss_len(0b0100), 2) - self.assertEqual(code.p2.ss_len(0b1000), 2) - self.assertEqual(code.p2.ss_len(0b1100), 3) + # for i in range(code.base_power_4): + # al = Alpha(i, m) + # alf = code.prefix2(al.to_hex()) + # if code.state[i] != RED: + # self.assertIn(i, code.p2, f"Value {i} not found in p2[{alf}]") + # self.assertGreater(len(code.p2), 0, f"p2[{alf}] is unexpectedly empty") + # else: + # self.assertNotIn(i, code.p2, f"Unexpected value {i} found in p2[{alf}]") + # self.assertEqual(code.p2.ss_len(0), 3) + # self.assertEqual(code.p2.ss_len(0b0100), 2) + # self.assertEqual(code.p2.ss_len(0b1000), 2) + # self.assertEqual(code.p2.ss_len(0b1100), 3) - def test_p3_addition(self): - m = 2 - g = 57 - code = CommaFreeCode(m, g) + # def test_p3_addition(self): + # m = 2 + # g = 57 + # code = CommaFreeCode(m, g) - code.initialize() + # code.initialize() - for i in range(code.base_power_4): - al = Alpha(i, m) - alf = code.prefix3(al.to_hex()) - if code.state[i] != RED: - self.assertIn(i, code.p3, f"Value {i} not found in p3[{alf}]") - self.assertGreater(len(code.p3), 0, f"p3[{alf}] is unexpectedly empty") - else: - self.assertNotIn(i, code.p3, f"Unexpected value {i} found in p3[{alf}]") - self.assertEqual(code.p3.ss_len(0), 1) - self.assertEqual(code.p3.ss_len(0b0010), 2) - self.assertEqual(code.p3.ss_len(0b0110), 2) - self.assertEqual(code.p3.ss_len(0b1000), 1) - self.assertEqual(code.p3.ss_len(0b1010), 1) - self.assertEqual(code.p3.ss_len(0b1100), 2) - self.assertEqual(code.p3.ss_len(0b1110), 1) + # for i in range(code.base_power_4): + # al = Alpha(i, m) + # alf = code.prefix3(al.to_hex()) + # if code.state[i] != RED: + # self.assertIn(i, code.p3, f"Value {i} not found in p3[{alf}]") + # self.assertGreater(len(code.p3), 0, f"p3[{alf}] is unexpectedly empty") + # else: + # self.assertNotIn(i, code.p3, f"Unexpected value {i} found in p3[{alf}]") + # self.assertEqual(code.p3.ss_len(0), 1) + # self.assertEqual(code.p3.ss_len(0b0010), 2) + # self.assertEqual(code.p3.ss_len(0b0110), 2) + # self.assertEqual(code.p3.ss_len(0b1000), 1) + # self.assertEqual(code.p3.ss_len(0b1010), 1) + # self.assertEqual(code.p3.ss_len(0b1100), 2) + # self.assertEqual(code.p3.ss_len(0b1110), 1) - def test_s1_addition(self): - m = 2 - g = 57 - code = CommaFreeCode(m, g) + # def test_s1_addition(self): + # m = 2 + # g = 57 + # code = CommaFreeCode(m, g) - code.initialize() + # code.initialize() - for i in range(code.base_power_4): - al = Alpha(i, m) - alf = code.suffix(al.to_hex()) - if code.state[i] != RED: - self.assertIn(i, code.s1, f"Value {i} not found in s1[{alf}]") - self.assertGreater(len(code.s1), 0, f"s1[{alf}] is unexpectedly empty") - else: - self.assertNotIn(i, code.s1, f"Unexpected value {i} found in s1[{alf}]") - self.assertEqual(code.s1.ss_len(0b0010), 4) - self.assertEqual(code.s1.ss_len(0b1100), 4) - self.assertEqual(code.s1.ss_len(0b1), 6) - self.assertEqual(code.s1.ss_len(0b111), 6) + # for i in range(code.base_power_4): + # al = Alpha(i, m) + # alf = code.suffix(al.to_hex()) + # if code.state[i] != RED: + # self.assertIn(i, code.s1, f"Value {i} not found in s1[{alf}]") + # self.assertGreater(len(code.s1), 0, f"s1[{alf}] is unexpectedly empty") + # else: + # self.assertNotIn(i, code.s1, f"Unexpected value {i} found in s1[{alf}]") + # self.assertEqual(code.s1.ss_len(0b0010), 4) + # self.assertEqual(code.s1.ss_len(0b1100), 4) + # self.assertEqual(code.s1.ss_len(0b1), 6) + # self.assertEqual(code.s1.ss_len(0b111), 6) - def test_s2_addition(self): - m = 2 - g = 57 - code = CommaFreeCode(m, g) + # def test_s2_addition(self): + # m = 2 + # g = 57 + # code = CommaFreeCode(m, g) - code.initialize() + # code.initialize() - for i in range(code.base_power_4): - al = Alpha(i, m) - alf = code.suffix2(al.to_hex()) - if code.state[i] != RED: - self.assertIn(i, code.s2, f"Value {i} not found in s2[{alf}]") - self.assertGreater(len(code.s2), 0, f"s2[{alf}] is unexpectedly empty") - else: - self.assertNotIn(i, code.s2, f"Unexpected value {i} found in s2[{alf}]") - self.assertEqual(code.s2.ss_len(0b1100), 1) - self.assertEqual(code.s2.ss_len(0b1), 3) - self.assertEqual(code.s2.ss_len(0b10), 3) - self.assertEqual(code.s2.ss_len(0b11), 3) + # for i in range(code.base_power_4): + # al = Alpha(i, m) + # alf = code.suffix2(al.to_hex()) + # if code.state[i] != RED: + # self.assertIn(i, code.s2, f"Value {i} not found in s2[{alf}]") + # self.assertGreater(len(code.s2), 0, f"s2[{alf}] is unexpectedly empty") + # else: + # self.assertNotIn(i, code.s2, f"Unexpected value {i} found in s2[{alf}]") + # self.assertEqual(code.s2.ss_len(0b1100), 1) + # self.assertEqual(code.s2.ss_len(0b1), 3) + # self.assertEqual(code.s2.ss_len(0b10), 3) + # self.assertEqual(code.s2.ss_len(0b11), 3) - def test_s3_addition(self): + # def test_s3_addition(self): + # m = 2 + # g = 57 + # code = CommaFreeCode(m, g) + + # code.initialize() + + # for i in range(code.base_power_4): + # al = Alpha(i, m) + # alf = code.suffix3(al.to_hex()) + # if code.state[i] != RED: + # self.assertIn(i, code.s3, f"Value {i} not found in s3[{alf}]") + # self.assertGreater(len(code.s3), 0, f"s3[{alf}] is unexpectedly empty") + # else: + # self.assertNotIn(i, code.s3, f"Unexpected value {i} found in s3[{alf}]") + # self.assertEqual(code.s3.ss_len(0b1), 2) + # self.assertEqual(code.s3.ss_len(0b0010), 1) + # self.assertEqual(code.s3.ss_len(0b11), 2) + # self.assertEqual(code.s3.ss_len(0b1100), 1) + # self.assertEqual(code.s3.ss_len(0b1101), 1) + # self.assertEqual(code.s3.ss_len(0b110), 2) + # self.assertEqual(code.s3.ss_len(0b0111), 1) + + def test_cl(self): m = 2 g = 57 code = CommaFreeCode(m, g) - code.initialize() - for i in range(code.base_power_4): - al = Alpha(i, m) - alf = code.suffix3(al.to_hex()) + alf = Alpha(i, m) if code.state[i] != RED: - self.assertIn(i, code.s3, f"Value {i} not found in s3[{alf}]") - self.assertGreater(len(code.s3), 0, f"s3[{alf}] is unexpectedly empty") + self.assertIn(i, code.cl, f"Value {i} not found in cl[{alf}]") + self.assertGreater(len(code.cl), 0, f"cl[{alf}] is unexpectedly empty") else: - self.assertNotIn(i, code.s3, f"Unexpected value {i} found in s3[{alf}]") - self.assertEqual(code.s3.ss_len(0b1), 2) - self.assertEqual(code.s3.ss_len(0b0010), 1) - self.assertEqual(code.s3.ss_len(0b11), 2) - self.assertEqual(code.s3.ss_len(0b1100), 1) - self.assertEqual(code.s3.ss_len(0b1101), 1) - self.assertEqual(code.s3.ss_len(0b110), 2) - self.assertEqual(code.s3.ss_len(0b0111), 1) + self.assertNotIn(i, code.cl, f"Unexpected value {i} found in cl[{alf}]") + if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/_code/alpha_test.py b/_code/test_alpha.py similarity index 74% rename from _code/alpha_test.py rename to _code/test_alpha.py index 535cdc9..512459b 100644 --- a/_code/alpha_test.py +++ b/_code/test_alpha.py @@ -4,7 +4,7 @@ class TestAlpha(unittest.TestCase): def test_alpha_0to_str(self): alpha = Alpha(0, 2) - self.assertEqual(alpha.to_str(), '0') + self.assertEqual(alpha.to_str(), '0000') def test_alpha_5to_hex(self): alpha = Alpha(5, 2) @@ -24,7 +24,7 @@ def test_alpha_to_hex(self): def test_alpha_to_str_m3(self): alpha = Alpha(10, 3) - self.assertEqual(alpha.to_str(), '101') + self.assertEqual(alpha.to_str(), '0101') def test_alpha_to_int_m3(self): alpha = Alpha(10, 3) @@ -36,7 +36,7 @@ def test_alpha_to_hex_m3(self): def test_alpha_to_str_m4(self): alpha = Alpha(10, 4) - self.assertEqual(alpha.to_str(), '22') + self.assertEqual(alpha.to_str(), '0022') def test_alpha_to_int_m4(self): alpha = Alpha(10, 4) @@ -46,6 +46,11 @@ def test_alpha_to_hex_m4(self): alpha = Alpha(10, 4) self.assertEqual(alpha.to_hex(), 0x22) + def test_alpha_shift1(self): + alpha = Alpha(0b1011, 2) + self.assertEqual(alpha.shift1().to_int(), 0b111) + self.assertEqual(alpha.shift1().shift1().to_int(), 0b1110) + self.assertEqual(alpha.shift1().shift1().shift1().to_int(), 0b1101) if __name__ == '__main__': unittest.main() \ No newline at end of file