1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python3
# cs/q/strobogrammatic/solution_test.py
# Generated by ChatGPT
import unittest
import random
import string
# Assume implementation is in strobogrammatic.py
# with function is_strobogrammatic(num: str) -> bool
from solution import IsStrobogrammatic as is_strobogrammatic
class TestStrobogrammatic(unittest.TestCase):
# === Basic True Cases ===
def test_single_digit_true(self):
for d in ["0", "1", "8"]:
with self.subTest(d=d):
self.assertTrue(is_strobogrammatic(d))
def test_two_digits_true(self):
self.assertTrue(is_strobogrammatic("69"))
self.assertTrue(is_strobogrammatic("96"))
self.assertTrue(is_strobogrammatic("88"))
self.assertTrue(is_strobogrammatic("11"))
# No leading zeros other than `0` itself.
self.assertFalse(is_strobogrammatic("00"))
def test_multi_digit_true(self):
self.assertTrue(is_strobogrammatic("818"))
self.assertTrue(is_strobogrammatic("609"))
self.assertTrue(is_strobogrammatic("619"))
self.assertTrue(is_strobogrammatic("888"))
self.assertTrue(is_strobogrammatic("101"))
# === Basic False Cases ===
def test_single_digit_false(self):
for d in ["2", "3", "4", "5", "6", "7", "9"]:
if d not in {"6", "9"}: # 6 and 9 are valid only as pairs
with self.subTest(d=d):
self.assertFalse(is_strobogrammatic(d))
def test_two_digits_false(self):
self.assertFalse(is_strobogrammatic("12"))
self.assertFalse(is_strobogrammatic("34"))
self.assertFalse(is_strobogrammatic("67"))
self.assertFalse(is_strobogrammatic("98"))
def test_multi_digit_false(self):
self.assertFalse(is_strobogrammatic("962"))
self.assertFalse(is_strobogrammatic("123"))
self.assertFalse(is_strobogrammatic("681"))
self.assertFalse(is_strobogrammatic("890"))
self.assertFalse(is_strobogrammatic("700"))
# === Edge Cases ===
def test_leading_zeros(self):
self.assertTrue(is_strobogrammatic("0"))
# No leading zeros other than `0` itself.
self.assertFalse(is_strobogrammatic("00"))
self.assertFalse(
is_strobogrammatic("010")
) # valid symmetry, but leading zero invalid if >1 length?
def test_max_length_valid(self):
# construct a 50-char valid number (all '8')
s = "8" * 50
self.assertTrue(is_strobogrammatic(s))
def test_max_length_invalid(self):
s = "8" * 49 + "2" # last digit invalid
self.assertFalse(is_strobogrammatic(s))
# === Stress / Randomized Tests ===
def test_randomized_valid_patterns(self):
pairs = {"0": "0", "1": "1", "6": "9", "8": "8", "9": "6"}
for _ in range(100):
length = random.randint(1, 50)
chars = []
for i in range((length + 1) // 2):
a, b = random.choice(list(pairs.items()))
chars.append(a)
left = "".join(chars)
right = "".join(pairs[c] for c in reversed(chars[: length // 2]))
candidate = left + right
assert_to_use = self.assertTrue
if (len(candidate) > 1 and candidate[0] == "0") or (
(len(candidate) % 2 == 1) and candidate[len(candidate) // 2] in "69"
):
assert_to_use = self.assertFalse
assert_to_use(is_strobogrammatic(candidate), candidate)
def test_randomized_invalid_patterns(self):
# generate random digits and ensure at least one invalid
for _ in range(50):
s = "".join(
random.choice(string.digits) for _ in range(random.randint(1, 10))
)
if any(ch not in "01689" for ch in s):
self.assertFalse(is_strobogrammatic(s))
if __name__ == "__main__":
unittest.main(verbosity=2)