jugaadcode 0.1.16__tar.gz → 0.1.18__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.
Files changed (63) hide show
  1. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/PKG-INFO +1 -1
  2. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/pyproject.toml +1 -1
  3. jugaadcode-0.1.18/src/jugaadcode/anagram.py +86 -0
  4. jugaadcode-0.1.18/src/jugaadcode/armstrong.py +127 -0
  5. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode.egg-info/PKG-INFO +1 -1
  6. jugaadcode-0.1.16/src/jugaadcode/anagram.py +0 -115
  7. jugaadcode-0.1.16/src/jugaadcode/armstrong.py +0 -93
  8. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/README.md +0 -0
  9. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/setup.cfg +0 -0
  10. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/__init__.py +0 -0
  11. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/binary_search.py +0 -0
  12. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/bubble_sort.py +0 -0
  13. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/capitalize_words.py +0 -0
  14. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/character_frequency.py +0 -0
  15. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/climbing_stairs.py +0 -0
  16. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/coin_change.py +0 -0
  17. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/count_vowels.py +0 -0
  18. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/counting_sort.py +0 -0
  19. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/duplicate_number.py +0 -0
  20. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/even_odd.py +0 -0
  21. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/factorial.py +0 -0
  22. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/factorial_trailing_zeros_direct.py +0 -0
  23. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/factorial_with_trailing_zeros.py +0 -0
  24. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/fibonacci.py +0 -0
  25. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/find_max.py +0 -0
  26. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/find_min.py +0 -0
  27. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/first_non_repeating.py +0 -0
  28. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/gcd.py +0 -0
  29. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/harshad_number.py +0 -0
  30. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/input_utils.py +0 -0
  31. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/insertion_sort.py +0 -0
  32. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/kth_largest.py +0 -0
  33. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/lcm.py +0 -0
  34. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/linear_search.py +0 -0
  35. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/longest_consecutive.py +0 -0
  36. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/longest_word.py +0 -0
  37. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/matrix_transpose.py +0 -0
  38. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/maximum_subarray.py +0 -0
  39. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/merge_sort.py +0 -0
  40. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/move_zeros.py +0 -0
  41. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/pair_with_difference.py +0 -0
  42. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/palindrome.py +0 -0
  43. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/perfect_number.py +0 -0
  44. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/power.py +0 -0
  45. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/prime.py +0 -0
  46. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/quick_sort.py +0 -0
  47. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/remove_duplicates_array.py +0 -0
  48. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/remove_duplicates_string.py +0 -0
  49. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/reverse_linked_list.py +0 -0
  50. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/reverse_number.py +0 -0
  51. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/reverse_string.py +0 -0
  52. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/second_largest.py +0 -0
  53. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/selection_sort.py +0 -0
  54. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/strong_number.py +0 -0
  55. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/subsequence.py +0 -0
  56. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/sum_of_digits.py +0 -0
  57. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/trailing_zeros.py +0 -0
  58. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/two_sum.py +0 -0
  59. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/valid_parentheses.py +0 -0
  60. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode/word_count.py +0 -0
  61. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode.egg-info/SOURCES.txt +0 -0
  62. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode.egg-info/dependency_links.txt +0 -0
  63. {jugaadcode-0.1.16 → jugaadcode-0.1.18}/src/jugaadcode.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jugaadcode
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: A Python library for common programming logic and algorithms
5
5
  Author: Mohamed Faraazman Bin Farooq S, Surya Deepta
6
6
  Requires-Python: >=3.9
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "jugaadcode"
3
- version = "0.1.16"
3
+ version = "0.1.18"
4
4
  description = "A Python library for common programming logic and algorithms"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -0,0 +1,86 @@
1
+ from collections.abc import Iterable
2
+
3
+
4
+ def is_anagram(*args):
5
+ """Check whether two or more strings are anagrams.
6
+
7
+ Supports:
8
+ - Interactive input
9
+ - Two individual strings
10
+ - Multiple strings, compared in pairs
11
+ - Lists, tuples, sets, and other iterables
12
+ - Collections containing pairs of strings
13
+
14
+ Returns:
15
+ - bool for one pair
16
+ - list of bools for multiple pairs
17
+ """
18
+
19
+ def compare_pair(pair):
20
+ first, second = pair
21
+
22
+ if not isinstance(first, str) or not isinstance(second, str):
23
+ raise TypeError("Both values must be strings.")
24
+
25
+ return sorted(first.casefold().replace(" ", "")) == sorted(
26
+ second.casefold().replace(" ", "")
27
+ )
28
+
29
+ def process_collection(values):
30
+ values = list(values)
31
+
32
+ if len(values) == 2 and all(
33
+ isinstance(value, str) for value in values
34
+ ):
35
+ return compare_pair(values)
36
+
37
+ if len(values) % 2 == 0 and all(
38
+ isinstance(value, str) for value in values
39
+ ):
40
+ return [
41
+ compare_pair(values[i:i + 2])
42
+ for i in range(0, len(values), 2)
43
+ ]
44
+
45
+ if all(
46
+ isinstance(pair, (list, tuple)) and len(pair) == 2
47
+ for pair in values
48
+ ):
49
+ results = [compare_pair(pair) for pair in values]
50
+ return results
51
+
52
+ raise ValueError(
53
+ "Provide two strings, an even number of strings, "
54
+ "or a collection of string pairs."
55
+ )
56
+
57
+ # No arguments: interactive mode
58
+ if not args:
59
+ first = input("Enter the first string: ")
60
+ second = input("Enter the second string: ")
61
+ return compare_pair((first, second))
62
+
63
+ # Multiple positional arguments
64
+ if len(args) > 1:
65
+ if len(args) == 2 and all(isinstance(arg, str) for arg in args):
66
+ return compare_pair(args)
67
+
68
+ return process_collection(args)
69
+
70
+ value = args[0]
71
+
72
+ # One string: prompt for the second string
73
+ if isinstance(value, str):
74
+ second = input("Enter the second string to compare: ")
75
+ return compare_pair((value, second))
76
+
77
+ # Reject non-iterable values
78
+ if isinstance(value, (bytes, bytearray)) or not isinstance(
79
+ value, Iterable
80
+ ):
81
+ raise TypeError(
82
+ "Input must be a string or an iterable of strings/pairs."
83
+ )
84
+
85
+ # Process lists, tuples, sets, generators, and other iterables
86
+ return process_collection(value)
@@ -0,0 +1,127 @@
1
+ from collections.abc import Iterable
2
+
3
+
4
+ def is_armstrong(*args):
5
+ """
6
+ Check whether one or more integers are Armstrong numbers.
7
+
8
+ Supports:
9
+ is_armstrong(153)
10
+ is_armstrong(153, 370, 123)
11
+ is_armstrong([153, 370, 123])
12
+ is_armstrong((153, 370, 123))
13
+ is_armstrong({153, 370, 123})
14
+ is_armstrong(range(100, 200))
15
+ is_armstrong(n for n in [153, 370, 123])
16
+ is_armstrong()
17
+
18
+ Returns
19
+ -------
20
+ bool
21
+ For a single integer.
22
+
23
+ list[bool]
24
+ For lists, sets, ranges, generators, and other iterables.
25
+
26
+ tuple[bool, ...]
27
+ For tuples or multiple positional arguments.
28
+
29
+ Raises
30
+ ------
31
+ TypeError
32
+ If an input is not an integer or supported iterable.
33
+
34
+ ValueError
35
+ If an input contains a negative integer or no values.
36
+ """
37
+
38
+ # Interactive input when no arguments are provided.
39
+ if not args:
40
+ value = input(
41
+ "Enter number(s) to check, separated by commas: "
42
+ ).strip()
43
+
44
+ if not value:
45
+ raise ValueError("Input cannot be empty.")
46
+
47
+ try:
48
+ args = tuple(
49
+ int(item.strip()) for item in value.split(",")
50
+ )
51
+ except ValueError as exc:
52
+ raise ValueError(
53
+ "Enter valid integers separated by commas."
54
+ ) from exc
55
+
56
+ # Determine the input format.
57
+ if len(args) > 1:
58
+ # Multiple positional arguments.
59
+ numbers = list(args)
60
+ input_type = "tuple"
61
+
62
+ else:
63
+ value = args[0]
64
+
65
+ if isinstance(value, bool):
66
+ numbers = [value]
67
+ input_type = "single"
68
+
69
+ elif isinstance(value, int):
70
+ numbers = [value]
71
+ input_type = "single"
72
+
73
+ elif isinstance(value, (str, bytes, bytearray)):
74
+ raise TypeError(
75
+ "Input must contain integers, not strings or bytes."
76
+ )
77
+
78
+ elif isinstance(value, Iterable):
79
+ numbers = list(value)
80
+
81
+ if isinstance(value, tuple):
82
+ input_type = "tuple"
83
+ else:
84
+ input_type = "list"
85
+
86
+ else:
87
+ raise TypeError(
88
+ "Input must be an integer or an iterable of integers."
89
+ )
90
+
91
+ # Reject empty collections and generators.
92
+ if not numbers:
93
+ raise ValueError("At least one number must be provided.")
94
+
95
+ def check_number(n):
96
+ # Booleans are not accepted as integers.
97
+ if isinstance(n, bool) or not isinstance(n, int):
98
+ raise TypeError("Every value must be an integer.")
99
+
100
+ if n < 0:
101
+ raise ValueError(
102
+ "Armstrong number checking requires "
103
+ "non-negative integers."
104
+ )
105
+
106
+ digits = str(n)
107
+ power = len(digits)
108
+
109
+ total = sum(
110
+ int(digit) ** power for digit in digits
111
+ )
112
+
113
+ return total == n
114
+
115
+ # Calculate results.
116
+ results = [
117
+ check_number(n) for n in numbers
118
+ ]
119
+
120
+ # Return the result in the appropriate format.
121
+ if input_type == "single":
122
+ return results[0]
123
+
124
+ if input_type == "tuple":
125
+ return tuple(results)
126
+
127
+ return results
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jugaadcode
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: A Python library for common programming logic and algorithms
5
5
  Author: Mohamed Faraazman Bin Farooq S, Surya Deepta
6
6
  Requires-Python: >=3.9
@@ -1,115 +0,0 @@
1
- from collections import Counter
2
-
3
-
4
- def is_anagram(*args):
5
- """
6
- Check whether two or more strings form anagrams.
7
-
8
- Supports:
9
- is_anagram("listen", "silent")
10
- is_anagram(["listen", "silent"])
11
- is_anagram(("listen", "silent"))
12
- is_anagram(("listen", "silent"), ("hello", "world"))
13
- is_anagram("listen", "silent", "hello", "world")
14
-
15
- Spaces and letter case are ignored.
16
-
17
- Parameters
18
- ----------
19
- *args : str or collections of strings
20
- Two strings for a single comparison, or multiple pairs
21
- supplied as separate arguments or collections.
22
-
23
- Returns
24
- -------
25
- bool or list[bool]
26
- A boolean for one comparison, or a list of booleans
27
- for multiple comparisons.
28
-
29
- Raises
30
- ------
31
- TypeError
32
- If an input is not a string or a supported collection.
33
- ValueError
34
- If a comparison does not contain exactly two strings,
35
- or either string is empty after removing whitespace.
36
- """
37
-
38
- if not args:
39
- first = input("Enter first string: ")
40
- second = input("Enter second string: ")
41
- args = (first, second)
42
-
43
- def normalize(text):
44
- if not isinstance(text, str):
45
- raise TypeError("Every string must be of type str.")
46
-
47
- normalized = "".join(text.split()).casefold()
48
-
49
- if not normalized:
50
- raise ValueError(
51
- "Strings must contain at least one non-whitespace character."
52
- )
53
-
54
- return Counter(normalized)
55
-
56
- def compare_pair(pair):
57
- if len(pair) != 2:
58
- raise ValueError(
59
- "Each anagram comparison must contain exactly two strings."
60
- )
61
-
62
- first, second = pair
63
- return normalize(first) == normalize(second)
64
-
65
- # Two strings represent one comparison.
66
- if len(args) == 2 and all(isinstance(arg, str) for arg in args):
67
- return compare_pair(args)
68
-
69
- # Multiple strings represent consecutive pairs.
70
- if all(isinstance(arg, str) for arg in args):
71
- if len(args) % 2 != 0:
72
- raise ValueError(
73
- "Multiple strings must be supplied in pairs."
74
- )
75
-
76
- return [
77
- compare_pair(args[index:index + 2])
78
- for index in range(0, len(args), 2)
79
- ]
80
-
81
- # A single collection may contain a pair of strings
82
- # or multiple pairs of strings.
83
- if len(args) == 1:
84
- collection = args[0]
85
-
86
- if isinstance(collection, (list, tuple)):
87
- if len(collection) == 2 and all(
88
- isinstance(item, str) for item in collection
89
- ):
90
- return compare_pair(collection)
91
-
92
- results = []
93
-
94
- for pair in collection:
95
- if not isinstance(pair, (list, tuple)):
96
- raise TypeError(
97
- "Multiple comparisons must be supplied as pairs."
98
- )
99
-
100
- results.append(compare_pair(pair))
101
-
102
- return results
103
-
104
- # Multiple pairs passed as separate arguments.
105
- results = []
106
-
107
- for pair in args:
108
- if not isinstance(pair, (list, tuple)):
109
- raise TypeError(
110
- "Supply strings in pairs or provide collections of string pairs."
111
- )
112
-
113
- results.append(compare_pair(pair))
114
-
115
- return results
@@ -1,93 +0,0 @@
1
- def is_armstrong(*args):
2
- """
3
- Check whether one or more integers are Armstrong numbers.
4
-
5
- Supports:
6
- is_armstrong(153)
7
- is_armstrong(153, 370, 123)
8
- is_armstrong([153, 370, 123])
9
- is_armstrong((153, 370, 123))
10
- is_armstrong({153, 370, 123})
11
- is_armstrong(range(100, 200))
12
- is_armstrong()
13
-
14
- Returns
15
- -------
16
- bool
17
- For a single integer.
18
- list[bool] or tuple[bool, ...] or set[bool]
19
- For multiple integers, according to the input format.
20
-
21
- Raises
22
- ------
23
- TypeError
24
- If an input is not an integer or supported collection.
25
- ValueError
26
- If an input contains a negative integer or no values.
27
- """
28
-
29
- if not args:
30
- value = input(
31
- "Enter number(s) to check, separated by commas: "
32
- ).strip()
33
-
34
- if not value:
35
- raise ValueError("Input cannot be empty.")
36
-
37
- try:
38
- args = tuple(int(item.strip()) for item in value.split(","))
39
- except ValueError as exc:
40
- raise ValueError(
41
- "Enter valid integers separated by commas."
42
- ) from exc
43
-
44
- # Determine whether the caller supplied a collection or
45
- # multiple individual arguments.
46
- if len(args) == 1:
47
- value = args[0]
48
-
49
- if isinstance(value, (list, tuple, set, range)):
50
- numbers = list(value)
51
- input_type = type(value)
52
- else:
53
- numbers = [value]
54
- input_type = None
55
- else:
56
- numbers = list(args)
57
- input_type = tuple
58
-
59
- if not numbers:
60
- raise ValueError("At least one number must be provided.")
61
-
62
- def check_number(n):
63
- if isinstance(n, bool) or not isinstance(n, int):
64
- raise TypeError("Every value must be an integer.")
65
-
66
- if n < 0:
67
- raise ValueError(
68
- "Armstrong number checking requires non-negative integers."
69
- )
70
-
71
- digits = str(n)
72
- power = len(digits)
73
-
74
- total = sum(int(digit) ** power for digit in digits)
75
-
76
- return total == n
77
-
78
- results = [check_number(n) for n in numbers]
79
-
80
- # Preserve a single result for a single integer.
81
- if input_type is None:
82
- return results[0]
83
-
84
- if input_type is list or input_type is range:
85
- return results
86
-
87
- if input_type is tuple:
88
- return tuple(results)
89
-
90
- if input_type is set:
91
- return set(results)
92
-
93
- return results
File without changes
File without changes