supermegaexplosion 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- supermegaexplosion-0.1.0/PKG-INFO +39 -0
- supermegaexplosion-0.1.0/README.md +26 -0
- supermegaexplosion-0.1.0/libbs/__init__.py +9 -0
- supermegaexplosion-0.1.0/libbs/ai_helper.py +30 -0
- supermegaexplosion-0.1.0/libbs/arrays.py +112 -0
- supermegaexplosion-0.1.0/libbs/catalog.py +84 -0
- supermegaexplosion-0.1.0/libbs/ds.py +136 -0
- supermegaexplosion-0.1.0/libbs/input_utils.py +66 -0
- supermegaexplosion-0.1.0/libbs/math_utils.py +109 -0
- supermegaexplosion-0.1.0/libbs/strings.py +119 -0
- supermegaexplosion-0.1.0/pyproject.toml +18 -0
- supermegaexplosion-0.1.0/setup.cfg +4 -0
- supermegaexplosion-0.1.0/supermegaexplosion.egg-info/PKG-INFO +39 -0
- supermegaexplosion-0.1.0/supermegaexplosion.egg-info/SOURCES.txt +15 -0
- supermegaexplosion-0.1.0/supermegaexplosion.egg-info/dependency_links.txt +1 -0
- supermegaexplosion-0.1.0/supermegaexplosion.egg-info/requires.txt +4 -0
- supermegaexplosion-0.1.0/supermegaexplosion.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: supermegaexplosion
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: DSA utility library — input helpers, algorithms, data structures, and AI assistant
|
|
5
|
+
Author-email: "Hadoopnb.ai" <hadoopnb@example.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Provides-Extra: ai
|
|
11
|
+
Requires-Dist: transformers>=4.30.0; extra == "ai"
|
|
12
|
+
Requires-Dist: torch>=2.0.0; extra == "ai"
|
|
13
|
+
|
|
14
|
+
# libbs
|
|
15
|
+
|
|
16
|
+
DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an optional AI coding assistant.
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from libbs import *
|
|
20
|
+
|
|
21
|
+
show_commands() # list everything available
|
|
22
|
+
input_matrix() # interactively type a matrix
|
|
23
|
+
is_palindrome("racecar") # True
|
|
24
|
+
sieve(100) # primes up to 100
|
|
25
|
+
max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) # 6
|
|
26
|
+
ListNode.from_list([1,2,3,4,5])
|
|
27
|
+
respond_help("How to reverse a linked list?") # requires: pip install libbs[ai]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install libbs # core
|
|
34
|
+
pip install libbs[ai] # with AI assistant (transformers + torch)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# libbs
|
|
2
|
+
|
|
3
|
+
DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an optional AI coding assistant.
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from libbs import *
|
|
7
|
+
|
|
8
|
+
show_commands() # list everything available
|
|
9
|
+
input_matrix() # interactively type a matrix
|
|
10
|
+
is_palindrome("racecar") # True
|
|
11
|
+
sieve(100) # primes up to 100
|
|
12
|
+
max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) # 6
|
|
13
|
+
ListNode.from_list([1,2,3,4,5])
|
|
14
|
+
respond_help("How to reverse a linked list?") # requires: pip install libbs[ai]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install libbs # core
|
|
21
|
+
pip install libbs[ai] # with AI assistant (transformers + torch)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from libbs.input_utils import *
|
|
2
|
+
from libbs.strings import *
|
|
3
|
+
from libbs.math_utils import *
|
|
4
|
+
from libbs.arrays import *
|
|
5
|
+
from libbs.ds import *
|
|
6
|
+
from libbs.ai_helper import respond_help
|
|
7
|
+
from libbs.catalog import show_commands, show_command
|
|
8
|
+
|
|
9
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
def respond_help(query, model_name="TinyLlama/TinyLlama-1.1B-Chat-v1.0"):
|
|
2
|
+
try:
|
|
3
|
+
from transformers import pipeline
|
|
4
|
+
except ImportError:
|
|
5
|
+
print(
|
|
6
|
+
"The AI helper requires extra dependencies.\n"
|
|
7
|
+
"Install them with: pip install libbs[ai]\n"
|
|
8
|
+
"Or: pip install transformers torch"
|
|
9
|
+
)
|
|
10
|
+
return
|
|
11
|
+
|
|
12
|
+
print(f"Loading AI model ({model_name})... This may take a while on first run.")
|
|
13
|
+
pipe = pipeline(
|
|
14
|
+
"text-generation",
|
|
15
|
+
model=model_name,
|
|
16
|
+
trust_remote_code=True,
|
|
17
|
+
)
|
|
18
|
+
prompt = (
|
|
19
|
+
"You are a helpful DSA and Python coding assistant. "
|
|
20
|
+
"Answer the following question concisely with code examples.\n\n"
|
|
21
|
+
f"Question: {query}\n\nAnswer:"
|
|
22
|
+
)
|
|
23
|
+
result = pipe(
|
|
24
|
+
prompt,
|
|
25
|
+
max_new_tokens=512,
|
|
26
|
+
temperature=0.3,
|
|
27
|
+
do_sample=True,
|
|
28
|
+
pad_token_id=pipe.tokenizer.eos_token_id,
|
|
29
|
+
)
|
|
30
|
+
print(result[0]["generated_text"].split("Answer:")[-1].strip())
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
def rotate(arr, k):
|
|
2
|
+
if not arr:
|
|
3
|
+
return arr
|
|
4
|
+
k %= len(arr)
|
|
5
|
+
arr[:] = arr[-k:] + arr[:-k]
|
|
6
|
+
return arr
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def chunk(arr, size):
|
|
10
|
+
return [arr[i:i + size] for i in range(0, len(arr), size)]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def flatten(lst):
|
|
14
|
+
return [item for sub in lst for item in sub]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def two_sum(nums, target):
|
|
18
|
+
seen = {}
|
|
19
|
+
for i, v in enumerate(nums):
|
|
20
|
+
complement = target - v
|
|
21
|
+
if complement in seen:
|
|
22
|
+
return [seen[complement], i]
|
|
23
|
+
seen[v] = i
|
|
24
|
+
return []
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def max_subarray_sum(nums):
|
|
28
|
+
if not nums:
|
|
29
|
+
return 0
|
|
30
|
+
max_ending = max_sofar = nums[0]
|
|
31
|
+
for v in nums[1:]:
|
|
32
|
+
max_ending = max(v, max_ending + v)
|
|
33
|
+
max_sofar = max(max_sofar, max_ending)
|
|
34
|
+
return max_sofar
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def merge_intervals(intervals):
|
|
38
|
+
if not intervals:
|
|
39
|
+
return []
|
|
40
|
+
intervals.sort(key=lambda x: x[0])
|
|
41
|
+
merged = [list(intervals[0])]
|
|
42
|
+
for start, end in intervals[1:]:
|
|
43
|
+
if start <= merged[-1][1]:
|
|
44
|
+
merged[-1][1] = max(merged[-1][1], end)
|
|
45
|
+
else:
|
|
46
|
+
merged.append([start, end])
|
|
47
|
+
return merged
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def binary_search(arr, target):
|
|
51
|
+
lo, hi = 0, len(arr) - 1
|
|
52
|
+
while lo <= hi:
|
|
53
|
+
mid = (lo + hi) // 2
|
|
54
|
+
if arr[mid] == target:
|
|
55
|
+
return mid
|
|
56
|
+
if arr[mid] < target:
|
|
57
|
+
lo = mid + 1
|
|
58
|
+
else:
|
|
59
|
+
hi = mid - 1
|
|
60
|
+
return -1
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def next_permutation(arr):
|
|
64
|
+
i = len(arr) - 2
|
|
65
|
+
while i >= 0 and arr[i] >= arr[i + 1]:
|
|
66
|
+
i -= 1
|
|
67
|
+
if i >= 0:
|
|
68
|
+
j = len(arr) - 1
|
|
69
|
+
while arr[j] <= arr[i]:
|
|
70
|
+
j -= 1
|
|
71
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
72
|
+
arr[i + 1:] = reversed(arr[i + 1:])
|
|
73
|
+
return arr
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def merge_sorted(arr1, arr2):
|
|
77
|
+
result = []
|
|
78
|
+
i = j = 0
|
|
79
|
+
while i < len(arr1) and j < len(arr2):
|
|
80
|
+
if arr1[i] <= arr2[j]:
|
|
81
|
+
result.append(arr1[i])
|
|
82
|
+
i += 1
|
|
83
|
+
else:
|
|
84
|
+
result.append(arr2[j])
|
|
85
|
+
j += 1
|
|
86
|
+
result.extend(arr1[i:])
|
|
87
|
+
result.extend(arr2[j:])
|
|
88
|
+
return result
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def majority_element(nums):
|
|
92
|
+
count = 0
|
|
93
|
+
candidate = None
|
|
94
|
+
for v in nums:
|
|
95
|
+
if count == 0:
|
|
96
|
+
candidate = v
|
|
97
|
+
count += 1 if v == candidate else -1
|
|
98
|
+
return candidate
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
__all__ = [
|
|
102
|
+
"rotate",
|
|
103
|
+
"chunk",
|
|
104
|
+
"flatten",
|
|
105
|
+
"two_sum",
|
|
106
|
+
"max_subarray_sum",
|
|
107
|
+
"merge_intervals",
|
|
108
|
+
"binary_search",
|
|
109
|
+
"next_permutation",
|
|
110
|
+
"merge_sorted",
|
|
111
|
+
"majority_element",
|
|
112
|
+
]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
COMMANDS = {
|
|
2
|
+
"Input": {
|
|
3
|
+
"input_matrix": "Read a matrix interactively. Optionally specify rows/cols/dtype/sep.",
|
|
4
|
+
"input_list": "Read a 1D list. Optionally specify n/dtype/sep.",
|
|
5
|
+
"input_linked_list": "Read values from stdin, return a ListNode head.",
|
|
6
|
+
"input_tree": "Read level-order values (null for gaps), return TreeNode root.",
|
|
7
|
+
"input_grid": "Read lines until blank line, return list of strings.",
|
|
8
|
+
},
|
|
9
|
+
"Strings": {
|
|
10
|
+
"is_anagram": "Check if two strings are anagrams (same chars, same count).",
|
|
11
|
+
"is_palindrome": "Check if a string reads the same forwards and backwards.",
|
|
12
|
+
"is_balanced": "Check if brackets/parens/braces in string are balanced.",
|
|
13
|
+
"reverse_words": "Reverse the order of space-separated words in a string.",
|
|
14
|
+
"longest_common_prefix": "Find the longest common prefix among a list of strings.",
|
|
15
|
+
"longest_substring": "Length of longest substring without repeating characters.",
|
|
16
|
+
"count_vowels": "Count vowels (a/e/i/o/u) in a string.",
|
|
17
|
+
"is_subsequence": "Check if s is a subsequence of t (order-preserving).",
|
|
18
|
+
"rabin_karp": "Rabin-Karp string matching. Returns list of start indices.",
|
|
19
|
+
"kmp_search": "KMP string matching. Returns list of start indices.",
|
|
20
|
+
},
|
|
21
|
+
"Math": {
|
|
22
|
+
"is_prime": "Check if n is a prime number.",
|
|
23
|
+
"sieve": "Return list of all primes up to n using Sieve of Eratosthenes.",
|
|
24
|
+
"prime_factors": "Return list of prime factors of n.",
|
|
25
|
+
"gcd": "Greatest common divisor of a and b.",
|
|
26
|
+
"lcm": "Least common multiple of a and b.",
|
|
27
|
+
"is_perfect_square": "Check if n is a perfect square.",
|
|
28
|
+
"is_power_of_two": "Check if n is a power of two.",
|
|
29
|
+
"nCr": "Binomial coefficient: n choose r.",
|
|
30
|
+
"nPr": "Permutation: n permute r (n! / (n-r)!).",
|
|
31
|
+
"fibonacci": "Return a list of the first n Fibonacci numbers.",
|
|
32
|
+
"is_armstrong": "Check if n is an Armstrong (narcissistic) number.",
|
|
33
|
+
},
|
|
34
|
+
"Arrays": {
|
|
35
|
+
"rotate": "Rotate list arr by k positions to the right (in-place).",
|
|
36
|
+
"chunk": "Split arr into subarrays of a given size.",
|
|
37
|
+
"flatten": "Flatten a nested list one level deep.",
|
|
38
|
+
"two_sum": "Return indices of two numbers that add up to target.",
|
|
39
|
+
"max_subarray_sum": "Maximum subarray sum using Kadane's algorithm.",
|
|
40
|
+
"merge_intervals": "Merge overlapping intervals [[s1,e1], [s2,e2], ...].",
|
|
41
|
+
"binary_search": "Return index of target in sorted arr, or -1 if not found.",
|
|
42
|
+
"next_permutation": "Rearrange arr into the next lexicographic permutation.",
|
|
43
|
+
"merge_sorted": "Merge two sorted lists into a single sorted list.",
|
|
44
|
+
"majority_element": "Find the majority element (> n/2 occurrences) using Boyer-Moore.",
|
|
45
|
+
},
|
|
46
|
+
"Data Structures": {
|
|
47
|
+
"ListNode": "Linked list node. Use ListNode.from_list(values) to construct.",
|
|
48
|
+
"TreeNode": "Binary tree node. Use TreeNode.from_level_order(values) to construct.",
|
|
49
|
+
"print_linked_list": "Print a linked list as space-separated values.",
|
|
50
|
+
"print_tree": "Print a binary tree sideways in ASCII.",
|
|
51
|
+
"linked_list_to_list": "Convert a linked list head to a Python list.",
|
|
52
|
+
"reverse_linked_list": "Reverse a linked list in-place, return new head.",
|
|
53
|
+
"detect_cycle": "Detect cycle in a linked list using Floyd's algorithm.",
|
|
54
|
+
"middle_node": "Return the middle node of a linked list.",
|
|
55
|
+
"has_path_sum": "Check if root-to-leaf path sums to target.",
|
|
56
|
+
},
|
|
57
|
+
"AI Assistant": {
|
|
58
|
+
"respond_help": "Ask a coding/DSA question and get an answer from a free local AI model.",
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def show_commands():
|
|
64
|
+
print("\n" + "=" * 60)
|
|
65
|
+
print(" libbs — Available Commands")
|
|
66
|
+
print("=" * 60)
|
|
67
|
+
for category, funcs in COMMANDS.items():
|
|
68
|
+
print(f"\n [{category}]")
|
|
69
|
+
print(" " + "-" * 56)
|
|
70
|
+
for name, desc in funcs.items():
|
|
71
|
+
print(f" {name:<30} {desc}")
|
|
72
|
+
print("\n" + "=" * 60)
|
|
73
|
+
print(" Use show_command('name') for detailed help on any function.")
|
|
74
|
+
print("=" * 60 + "\n")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def show_command(name):
|
|
78
|
+
for category, funcs in COMMANDS.items():
|
|
79
|
+
if name in funcs:
|
|
80
|
+
print(f"\n [{category}] {name}")
|
|
81
|
+
print(" " + "-" * 50)
|
|
82
|
+
print(f" {funcs[name]}\n")
|
|
83
|
+
return
|
|
84
|
+
print(f" Unknown command: '{name}'. Use show_commands() to list all.\n")
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
class ListNode:
|
|
2
|
+
def __init__(self, val=0, next=None):
|
|
3
|
+
self.val = val
|
|
4
|
+
self.next = next
|
|
5
|
+
|
|
6
|
+
def __repr__(self):
|
|
7
|
+
vals = []
|
|
8
|
+
cur = self
|
|
9
|
+
while cur:
|
|
10
|
+
vals.append(str(cur.val))
|
|
11
|
+
cur = cur.next
|
|
12
|
+
return " -> ".join(vals) if vals else "None"
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def from_list(vals):
|
|
16
|
+
if not vals:
|
|
17
|
+
return None
|
|
18
|
+
head = ListNode(vals[0])
|
|
19
|
+
cur = head
|
|
20
|
+
for v in vals[1:]:
|
|
21
|
+
cur.next = ListNode(v)
|
|
22
|
+
cur = cur.next
|
|
23
|
+
return head
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TreeNode:
|
|
27
|
+
def __init__(self, val=0, left=None, right=None):
|
|
28
|
+
self.val = val
|
|
29
|
+
self.left = left
|
|
30
|
+
self.right = right
|
|
31
|
+
|
|
32
|
+
def __repr__(self):
|
|
33
|
+
return f"TreeNode({self.val})"
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def from_level_order(vals):
|
|
37
|
+
if not vals or vals[0] is None:
|
|
38
|
+
return None
|
|
39
|
+
root = TreeNode(vals[0])
|
|
40
|
+
queue = [root]
|
|
41
|
+
i = 1
|
|
42
|
+
while queue and i < len(vals):
|
|
43
|
+
node = queue.pop(0)
|
|
44
|
+
if i < len(vals) and vals[i] is not None:
|
|
45
|
+
node.left = TreeNode(vals[i])
|
|
46
|
+
queue.append(node.left)
|
|
47
|
+
i += 1
|
|
48
|
+
if i < len(vals) and vals[i] is not None:
|
|
49
|
+
node.right = TreeNode(vals[i])
|
|
50
|
+
queue.append(node.right)
|
|
51
|
+
i += 1
|
|
52
|
+
return root
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def print_linked_list(head):
|
|
56
|
+
vals = []
|
|
57
|
+
cur = head
|
|
58
|
+
while cur:
|
|
59
|
+
vals.append(str(cur.val))
|
|
60
|
+
cur = cur.next
|
|
61
|
+
print(" -> ".join(vals) if vals else "None")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def linked_list_to_list(head):
|
|
65
|
+
result = []
|
|
66
|
+
cur = head
|
|
67
|
+
while cur:
|
|
68
|
+
result.append(cur.val)
|
|
69
|
+
cur = cur.next
|
|
70
|
+
return result
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def reverse_linked_list(head):
|
|
74
|
+
prev = None
|
|
75
|
+
cur = head
|
|
76
|
+
while cur:
|
|
77
|
+
nxt = cur.next
|
|
78
|
+
cur.next = prev
|
|
79
|
+
prev = cur
|
|
80
|
+
cur = nxt
|
|
81
|
+
return prev
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def detect_cycle(head):
|
|
85
|
+
slow = fast = head
|
|
86
|
+
while fast and fast.next:
|
|
87
|
+
slow = slow.next
|
|
88
|
+
fast = fast.next.next
|
|
89
|
+
if slow is fast:
|
|
90
|
+
return True
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def middle_node(head):
|
|
95
|
+
slow = fast = head
|
|
96
|
+
while fast and fast.next:
|
|
97
|
+
slow = slow.next
|
|
98
|
+
fast = fast.next.next
|
|
99
|
+
return slow
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def print_tree(root):
|
|
103
|
+
def inner(node, prefix, is_left):
|
|
104
|
+
if not node:
|
|
105
|
+
return
|
|
106
|
+
inner(node.right, prefix + ("| " if is_left else " "), False)
|
|
107
|
+
print(prefix + ("+-- " if is_left else "+-- ") + str(node.val))
|
|
108
|
+
inner(node.left, prefix + (" " if is_left else "| "), True)
|
|
109
|
+
|
|
110
|
+
if root:
|
|
111
|
+
print(root.val)
|
|
112
|
+
inner(root.right, "", False)
|
|
113
|
+
inner(root.left, "", True)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def has_path_sum(root, target):
|
|
117
|
+
if not root:
|
|
118
|
+
return False
|
|
119
|
+
if not root.left and not root.right:
|
|
120
|
+
return root.val == target
|
|
121
|
+
return has_path_sum(root.left, target - root.val) or has_path_sum(
|
|
122
|
+
root.right, target - root.val
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
__all__ = [
|
|
127
|
+
"ListNode",
|
|
128
|
+
"TreeNode",
|
|
129
|
+
"print_linked_list",
|
|
130
|
+
"linked_list_to_list",
|
|
131
|
+
"reverse_linked_list",
|
|
132
|
+
"detect_cycle",
|
|
133
|
+
"middle_node",
|
|
134
|
+
"print_tree",
|
|
135
|
+
"has_path_sum",
|
|
136
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
def input_matrix(rows=None, cols=None, dtype=int, sep=None):
|
|
2
|
+
mat = []
|
|
3
|
+
if rows is not None:
|
|
4
|
+
for i in range(rows):
|
|
5
|
+
line = input(f"Row {i+1}: ").strip()
|
|
6
|
+
vals = line.split(sep) if sep else line.split()
|
|
7
|
+
if cols is not None and len(vals) != cols:
|
|
8
|
+
raise ValueError(f"Expected {cols} elements, got {len(vals)}")
|
|
9
|
+
mat.append([dtype(v) for v in vals])
|
|
10
|
+
else:
|
|
11
|
+
print("Enter matrix rows (empty line to stop):")
|
|
12
|
+
while True:
|
|
13
|
+
line = input().strip()
|
|
14
|
+
if not line:
|
|
15
|
+
break
|
|
16
|
+
vals = line.split(sep) if sep else line.split()
|
|
17
|
+
mat.append([dtype(v) for v in vals])
|
|
18
|
+
return mat
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def input_list(n=None, dtype=int, sep=None):
|
|
22
|
+
line = input("Enter values: ").strip()
|
|
23
|
+
vals = line.split(sep) if sep else line.split()
|
|
24
|
+
if n is not None and len(vals) != n:
|
|
25
|
+
raise ValueError(f"Expected {n} elements, got {len(vals)}")
|
|
26
|
+
return [dtype(v) for v in vals]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def input_grid():
|
|
30
|
+
print("Enter grid lines (empty line to stop):")
|
|
31
|
+
grid = []
|
|
32
|
+
while True:
|
|
33
|
+
line = input()
|
|
34
|
+
if not line.strip():
|
|
35
|
+
break
|
|
36
|
+
grid.append(line)
|
|
37
|
+
return grid
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def input_linked_list(dtype=int, sep=None):
|
|
41
|
+
from libbs.ds import ListNode
|
|
42
|
+
line = input("Enter linked list values: ").strip()
|
|
43
|
+
vals = line.split(sep) if sep else line.split()
|
|
44
|
+
return ListNode.from_list([dtype(v) for v in vals])
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def input_tree(dtype=int):
|
|
48
|
+
from libbs.ds import TreeNode
|
|
49
|
+
line = input("Enter tree level-order (null for gaps): ").strip()
|
|
50
|
+
vals = line.split()
|
|
51
|
+
parsed = []
|
|
52
|
+
for v in vals:
|
|
53
|
+
if v.lower() in ("null", "none", "n"):
|
|
54
|
+
parsed.append(None)
|
|
55
|
+
else:
|
|
56
|
+
parsed.append(dtype(v))
|
|
57
|
+
return TreeNode.from_level_order(parsed)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"input_matrix",
|
|
62
|
+
"input_list",
|
|
63
|
+
"input_grid",
|
|
64
|
+
"input_linked_list",
|
|
65
|
+
"input_tree",
|
|
66
|
+
]
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
def is_prime(n):
|
|
2
|
+
if n < 2:
|
|
3
|
+
return False
|
|
4
|
+
i = 2
|
|
5
|
+
while i * i <= n:
|
|
6
|
+
if n % i == 0:
|
|
7
|
+
return False
|
|
8
|
+
i += 1
|
|
9
|
+
return True
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def sieve(n):
|
|
13
|
+
if n < 2:
|
|
14
|
+
return []
|
|
15
|
+
prime = [True] * (n + 1)
|
|
16
|
+
prime[0] = prime[1] = False
|
|
17
|
+
for i in range(2, int(n ** 0.5) + 1):
|
|
18
|
+
if prime[i]:
|
|
19
|
+
step = i
|
|
20
|
+
start = i * i
|
|
21
|
+
prime[start:n + 1:step] = [False] * (((n - start) // step) + 1)
|
|
22
|
+
return [i for i, v in enumerate(prime) if v]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def prime_factors(n):
|
|
26
|
+
factors = []
|
|
27
|
+
d = 2
|
|
28
|
+
while d * d <= n:
|
|
29
|
+
while n % d == 0:
|
|
30
|
+
factors.append(d)
|
|
31
|
+
n //= d
|
|
32
|
+
d += 1 if d == 2 else 2
|
|
33
|
+
if n > 1:
|
|
34
|
+
factors.append(n)
|
|
35
|
+
return factors
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def gcd(a, b):
|
|
39
|
+
while b:
|
|
40
|
+
a, b = b, a % b
|
|
41
|
+
return a
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def lcm(a, b):
|
|
45
|
+
return a * b // gcd(a, b)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def is_perfect_square(n):
|
|
49
|
+
if n < 0:
|
|
50
|
+
return False
|
|
51
|
+
r = int(n ** 0.5)
|
|
52
|
+
return r * r == n
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def is_power_of_two(n):
|
|
56
|
+
return n > 0 and (n & (n - 1)) == 0
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def nCr(n, r):
|
|
60
|
+
if r < 0 or r > n:
|
|
61
|
+
return 0
|
|
62
|
+
r = min(r, n - r)
|
|
63
|
+
res = 1
|
|
64
|
+
for i in range(1, r + 1):
|
|
65
|
+
res = res * (n - r + i) // i
|
|
66
|
+
return res
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def nPr(n, r):
|
|
70
|
+
if r < 0 or r > n:
|
|
71
|
+
return 0
|
|
72
|
+
res = 1
|
|
73
|
+
for i in range(r):
|
|
74
|
+
res *= (n - i)
|
|
75
|
+
return res
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def fibonacci(n):
|
|
79
|
+
if n <= 0:
|
|
80
|
+
return []
|
|
81
|
+
if n == 1:
|
|
82
|
+
return [0]
|
|
83
|
+
seq = [0, 1]
|
|
84
|
+
for _ in range(2, n):
|
|
85
|
+
seq.append(seq[-1] + seq[-2])
|
|
86
|
+
return seq[:n]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def is_armstrong(n):
|
|
90
|
+
if n < 0:
|
|
91
|
+
return False
|
|
92
|
+
s = str(n)
|
|
93
|
+
power = len(s)
|
|
94
|
+
return sum(int(d) ** power for d in s) == n
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = [
|
|
98
|
+
"is_prime",
|
|
99
|
+
"sieve",
|
|
100
|
+
"prime_factors",
|
|
101
|
+
"gcd",
|
|
102
|
+
"lcm",
|
|
103
|
+
"is_perfect_square",
|
|
104
|
+
"is_power_of_two",
|
|
105
|
+
"nCr",
|
|
106
|
+
"nPr",
|
|
107
|
+
"fibonacci",
|
|
108
|
+
"is_armstrong",
|
|
109
|
+
]
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from collections import Counter
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def is_anagram(s1, s2):
|
|
5
|
+
return Counter(s1) == Counter(s2)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def is_palindrome(s):
|
|
9
|
+
cleaned = "".join(c.lower() for c in s if c.isalnum())
|
|
10
|
+
return cleaned == cleaned[::-1]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def is_balanced(s):
|
|
14
|
+
pairs = {")": "(", "]": "[", "}": "{"}
|
|
15
|
+
stack = []
|
|
16
|
+
for ch in s:
|
|
17
|
+
if ch in pairs.values():
|
|
18
|
+
stack.append(ch)
|
|
19
|
+
elif ch in pairs:
|
|
20
|
+
if not stack or stack[-1] != pairs[ch]:
|
|
21
|
+
return False
|
|
22
|
+
stack.pop()
|
|
23
|
+
return len(stack) == 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def reverse_words(s):
|
|
27
|
+
return " ".join(s.split()[::-1])
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def longest_common_prefix(strs):
|
|
31
|
+
if not strs:
|
|
32
|
+
return ""
|
|
33
|
+
prefix = strs[0]
|
|
34
|
+
for s in strs[1:]:
|
|
35
|
+
while not s.startswith(prefix):
|
|
36
|
+
prefix = prefix[:-1]
|
|
37
|
+
if not prefix:
|
|
38
|
+
return ""
|
|
39
|
+
return prefix
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def longest_substring(s):
|
|
43
|
+
seen = {}
|
|
44
|
+
start = 0
|
|
45
|
+
max_len = 0
|
|
46
|
+
for i, ch in enumerate(s):
|
|
47
|
+
if ch in seen and seen[ch] >= start:
|
|
48
|
+
start = seen[ch] + 1
|
|
49
|
+
seen[ch] = i
|
|
50
|
+
max_len = max(max_len, i - start + 1)
|
|
51
|
+
return max_len
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def count_vowels(s):
|
|
55
|
+
return sum(1 for ch in s.lower() if ch in "aeiou")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def is_subsequence(s, t):
|
|
59
|
+
it = iter(t)
|
|
60
|
+
return all(ch in it for ch in s)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def rabin_karp(text, pattern):
|
|
64
|
+
d, q = 256, 101
|
|
65
|
+
n, m = len(text), len(pattern)
|
|
66
|
+
if m > n or m == 0:
|
|
67
|
+
return []
|
|
68
|
+
h = pow(d, m - 1, q)
|
|
69
|
+
p_hash = t_hash = 0
|
|
70
|
+
for i in range(m):
|
|
71
|
+
p_hash = (d * p_hash + ord(pattern[i])) % q
|
|
72
|
+
t_hash = (d * t_hash + ord(text[i])) % q
|
|
73
|
+
result = []
|
|
74
|
+
for i in range(n - m + 1):
|
|
75
|
+
if p_hash == t_hash:
|
|
76
|
+
if text[i:i + m] == pattern:
|
|
77
|
+
result.append(i)
|
|
78
|
+
if i < n - m:
|
|
79
|
+
t_hash = (d * (t_hash - ord(text[i]) * h) + ord(text[i + m])) % q
|
|
80
|
+
return result
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def kmp_search(text, pattern):
|
|
84
|
+
n, m = len(text), len(pattern)
|
|
85
|
+
if m == 0:
|
|
86
|
+
return []
|
|
87
|
+
lps = [0] * m
|
|
88
|
+
j = 0
|
|
89
|
+
for i in range(1, m):
|
|
90
|
+
while j > 0 and pattern[i] != pattern[j]:
|
|
91
|
+
j = lps[j - 1]
|
|
92
|
+
if pattern[i] == pattern[j]:
|
|
93
|
+
j += 1
|
|
94
|
+
lps[i] = j
|
|
95
|
+
result = []
|
|
96
|
+
j = 0
|
|
97
|
+
for i in range(n):
|
|
98
|
+
while j > 0 and text[i] != pattern[j]:
|
|
99
|
+
j = lps[j - 1]
|
|
100
|
+
if text[i] == pattern[j]:
|
|
101
|
+
j += 1
|
|
102
|
+
if j == m:
|
|
103
|
+
result.append(i - m + 1)
|
|
104
|
+
j = lps[j - 1]
|
|
105
|
+
return result
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
__all__ = [
|
|
109
|
+
"is_anagram",
|
|
110
|
+
"is_palindrome",
|
|
111
|
+
"is_balanced",
|
|
112
|
+
"reverse_words",
|
|
113
|
+
"longest_common_prefix",
|
|
114
|
+
"longest_substring",
|
|
115
|
+
"count_vowels",
|
|
116
|
+
"is_subsequence",
|
|
117
|
+
"rabin_karp",
|
|
118
|
+
"kmp_search",
|
|
119
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "supermegaexplosion"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "DSA utility library — input helpers, algorithms, data structures, and AI assistant"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{ name = "Hadoopnb.ai", email = "hadoopnb@example.com" }]
|
|
11
|
+
license = "MIT"
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
]
|
|
15
|
+
requires-python = ">=3.8"
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
ai = ["transformers>=4.30.0", "torch>=2.0.0"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: supermegaexplosion
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: DSA utility library — input helpers, algorithms, data structures, and AI assistant
|
|
5
|
+
Author-email: "Hadoopnb.ai" <hadoopnb@example.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Provides-Extra: ai
|
|
11
|
+
Requires-Dist: transformers>=4.30.0; extra == "ai"
|
|
12
|
+
Requires-Dist: torch>=2.0.0; extra == "ai"
|
|
13
|
+
|
|
14
|
+
# libbs
|
|
15
|
+
|
|
16
|
+
DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an optional AI coding assistant.
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from libbs import *
|
|
20
|
+
|
|
21
|
+
show_commands() # list everything available
|
|
22
|
+
input_matrix() # interactively type a matrix
|
|
23
|
+
is_palindrome("racecar") # True
|
|
24
|
+
sieve(100) # primes up to 100
|
|
25
|
+
max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) # 6
|
|
26
|
+
ListNode.from_list([1,2,3,4,5])
|
|
27
|
+
respond_help("How to reverse a linked list?") # requires: pip install libbs[ai]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install libbs # core
|
|
34
|
+
pip install libbs[ai] # with AI assistant (transformers + torch)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
libbs/__init__.py
|
|
4
|
+
libbs/ai_helper.py
|
|
5
|
+
libbs/arrays.py
|
|
6
|
+
libbs/catalog.py
|
|
7
|
+
libbs/ds.py
|
|
8
|
+
libbs/input_utils.py
|
|
9
|
+
libbs/math_utils.py
|
|
10
|
+
libbs/strings.py
|
|
11
|
+
supermegaexplosion.egg-info/PKG-INFO
|
|
12
|
+
supermegaexplosion.egg-info/SOURCES.txt
|
|
13
|
+
supermegaexplosion.egg-info/dependency_links.txt
|
|
14
|
+
supermegaexplosion.egg-info/requires.txt
|
|
15
|
+
supermegaexplosion.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
libbs
|