sjec-labs 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.
Files changed (28) hide show
  1. sjec_labs-0.1.0/LICENSE +21 -0
  2. sjec_labs-0.1.0/PKG-INFO +60 -0
  3. sjec_labs-0.1.0/README.md +44 -0
  4. sjec_labs-0.1.0/pyproject.toml +27 -0
  5. sjec_labs-0.1.0/setup.cfg +4 -0
  6. sjec_labs-0.1.0/src/sjec_lab/__init__.py +6 -0
  7. sjec_labs-0.1.0/src/sjec_lab/assistant.py +15 -0
  8. sjec_labs-0.1.0/src/sjec_lab/core.py +60 -0
  9. sjec_labs-0.1.0/src/sjec_lab/programs/__init__.py +1 -0
  10. sjec_labs-0.1.0/src/sjec_lab/programs/cm/__init__.py +1 -0
  11. sjec_labs-0.1.0/src/sjec_lab/programs/dv/__init__.py +1 -0
  12. sjec_labs-0.1.0/src/sjec_lab/programs/ml/__init__.py +1 -0
  13. sjec_labs-0.1.0/src/sjec_lab/programs/ml/original/__init__.py +1 -0
  14. sjec_labs-0.1.0/src/sjec_lab/programs/ml/original/program1.py +33 -0
  15. sjec_labs-0.1.0/src/sjec_lab/programs/ml/original/program2.py +39 -0
  16. sjec_labs-0.1.0/src/sjec_lab/programs/ml/original/program3.py +66 -0
  17. sjec_labs-0.1.0/src/sjec_lab/programs/ml/original/program4.py +34 -0
  18. sjec_labs-0.1.0/src/sjec_lab/programs/ml/simple/__init__.py +1 -0
  19. sjec_labs-0.1.0/src/sjec_lab/programs/ml/simple/program1.py +20 -0
  20. sjec_labs-0.1.0/src/sjec_lab/programs/ml/simple/program2.py +32 -0
  21. sjec_labs-0.1.0/src/sjec_lab/programs/ml/simple/program3.py +44 -0
  22. sjec_labs-0.1.0/src/sjec_lab/programs/ml/simple/program4.py +30 -0
  23. sjec_labs-0.1.0/src/sjec_labs.egg-info/PKG-INFO +60 -0
  24. sjec_labs-0.1.0/src/sjec_labs.egg-info/SOURCES.txt +26 -0
  25. sjec_labs-0.1.0/src/sjec_labs.egg-info/dependency_links.txt +1 -0
  26. sjec_labs-0.1.0/src/sjec_labs.egg-info/requires.txt +3 -0
  27. sjec_labs-0.1.0/src/sjec_labs.egg-info/top_level.txt +1 -0
  28. sjec_labs-0.1.0/tests/test_core.py +12 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SJEC Labs contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: sjec-labs
3
+ Version: 0.1.0
4
+ Summary: Exam-friendly Python lab programs for SJEC students
5
+ Author: SJEC Labs contributors
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Provides-Extra: notebook
14
+ Requires-Dist: ipython>=8; extra == "notebook"
15
+ Dynamic: license-file
16
+
17
+ # sjec-labs
18
+
19
+ An expandable collection of exam-friendly Python lab programs for ML, CM and DV.
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ pip install sjec-labs
25
+ ```
26
+
27
+ For syntax-highlighted Jupyter output:
28
+
29
+ ```python
30
+ %pip install "sjec-labs[notebook]"
31
+ ```
32
+
33
+ ## Use in Jupyter or Python
34
+
35
+ ```python
36
+ from sjec_lab import LabAssistant
37
+
38
+ lab = LabAssistant()
39
+ lab.list_subjects()
40
+ lab.list_programs("ML")
41
+ lab.get_code("ML", 1) # print and return simplified code
42
+ lab.show_code("ML", 1) # formatted display in Jupyter
43
+ lab.get_code("ML", 1, version="original") # supplied original version
44
+ ```
45
+
46
+ Available initial programs:
47
+
48
+ 1. Simple Chatbot
49
+ 2. Water Jug Problem using BFS
50
+ 3. A* Search Algorithm
51
+ 4. N-Queens using Backtracking
52
+
53
+ CM and DV folders are reserved for future releases. The package will be expanded as more verified programs are added.
54
+
55
+ ## Notes
56
+
57
+ - `get_code()` returns the source as a string and prints it by default.
58
+ - Use `print_code=False` if you only want the returned string.
59
+ - The core package has no mandatory third-party dependencies.
60
+ - `show_code()` uses IPython when available.
@@ -0,0 +1,44 @@
1
+ # sjec-labs
2
+
3
+ An expandable collection of exam-friendly Python lab programs for ML, CM and DV.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install sjec-labs
9
+ ```
10
+
11
+ For syntax-highlighted Jupyter output:
12
+
13
+ ```python
14
+ %pip install "sjec-labs[notebook]"
15
+ ```
16
+
17
+ ## Use in Jupyter or Python
18
+
19
+ ```python
20
+ from sjec_lab import LabAssistant
21
+
22
+ lab = LabAssistant()
23
+ lab.list_subjects()
24
+ lab.list_programs("ML")
25
+ lab.get_code("ML", 1) # print and return simplified code
26
+ lab.show_code("ML", 1) # formatted display in Jupyter
27
+ lab.get_code("ML", 1, version="original") # supplied original version
28
+ ```
29
+
30
+ Available initial programs:
31
+
32
+ 1. Simple Chatbot
33
+ 2. Water Jug Problem using BFS
34
+ 3. A* Search Algorithm
35
+ 4. N-Queens using Backtracking
36
+
37
+ CM and DV folders are reserved for future releases. The package will be expanded as more verified programs are added.
38
+
39
+ ## Notes
40
+
41
+ - `get_code()` returns the source as a string and prints it by default.
42
+ - Use `print_code=False` if you only want the returned string.
43
+ - The core package has no mandatory third-party dependencies.
44
+ - `show_code()` uses IPython when available.
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sjec-labs"
7
+ version = "0.1.0"
8
+ description = "Exam-friendly Python lab programs for SJEC students"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ authors = [{name = "SJEC Labs contributors"}]
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3 :: Only",
16
+ "Operating System :: OS Independent",
17
+ ]
18
+ dependencies = []
19
+
20
+ [project.optional-dependencies]
21
+ notebook = ["ipython>=8"]
22
+
23
+ [tool.setuptools.packages.find]
24
+ where = ["src"]
25
+
26
+ [tool.setuptools.package-data]
27
+ "sjec_lab.programs" = ["**/*.py"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,6 @@
1
+ """SJEC Labs: exam-friendly lab programs and Jupyter helpers."""
2
+ from .assistant import LabAssistant
3
+ from .core import get_code, show_code, list_subjects, list_programs
4
+
5
+ __version__ = "0.1.0"
6
+ __all__ = ["LabAssistant", "get_code", "show_code", "list_subjects", "list_programs"]
@@ -0,0 +1,15 @@
1
+ from .core import get_code, show_code, list_subjects, list_programs
2
+
3
+ class LabAssistant:
4
+ """Convenience interface for retrieving SJEC lab programs."""
5
+ def list_subjects(self):
6
+ return list_subjects()
7
+
8
+ def list_programs(self, subject):
9
+ return list_programs(subject)
10
+
11
+ def get_code(self, subject, program, version="simple", print_code=True):
12
+ return get_code(subject, program, version, print_code)
13
+
14
+ def show_code(self, subject, program, version="simple"):
15
+ return show_code(subject, program, version)
@@ -0,0 +1,60 @@
1
+ from importlib.resources import files
2
+
3
+ PROGRAMS = {
4
+ "ML": {
5
+ 1: "Simple Chatbot",
6
+ 2: "Water Jug Problem using BFS",
7
+ 3: "A* Search Algorithm",
8
+ 4: "N-Queens using Backtracking",
9
+ },
10
+ "CM": {},
11
+ "DV": {},
12
+ }
13
+
14
+ ALIASES = {"FAIML": "ML", "MACHINE LEARNING": "ML", "COMPUTER GRAPHICS": "CM", "DATA VISUALIZATION": "DV"}
15
+
16
+
17
+ def _subject_name(subject):
18
+ key = str(subject).strip().upper()
19
+ return ALIASES.get(key, key)
20
+
21
+
22
+ def list_subjects():
23
+ """Return the subjects currently included in the package."""
24
+ return {name: len(programs) for name, programs in PROGRAMS.items()}
25
+
26
+
27
+ def list_programs(subject):
28
+ """Return program numbers and titles for a subject."""
29
+ subject = _subject_name(subject)
30
+ if subject not in PROGRAMS:
31
+ raise ValueError(f"Unknown subject {subject!r}. Choose ML, CM, or DV.")
32
+ return PROGRAMS[subject].copy()
33
+
34
+
35
+ def get_code(subject, program, version="simple", print_code=True):
36
+ """Get a program's source code. Prints it by default and always returns a string."""
37
+ subject = _subject_name(subject)
38
+ if subject not in PROGRAMS:
39
+ raise ValueError(f"Unknown subject {subject!r}. Choose ML, CM, or DV.")
40
+ if program not in PROGRAMS[subject]:
41
+ raise ValueError(f"Program {program} is not available for {subject}. Available: {list(PROGRAMS[subject])}")
42
+ version = version.lower()
43
+ if version not in ("simple", "original"):
44
+ raise ValueError("version must be 'simple' or 'original'")
45
+ resource = files(f"sjec_lab.programs.{subject.lower()}.{version}").joinpath(f"program{program}.py")
46
+ code = resource.read_text(encoding="utf-8")
47
+ if print_code:
48
+ print(code)
49
+ return code
50
+
51
+
52
+ def show_code(subject, program, version="simple"):
53
+ """Display syntax-highlighted code in Jupyter; fall back to printing elsewhere."""
54
+ code = get_code(subject, program, version=version, print_code=False)
55
+ try:
56
+ from IPython.display import display, Code
57
+ display(Code(code, language="python"))
58
+ except ImportError:
59
+ print(code)
60
+ return code
@@ -0,0 +1 @@
1
+ """SJEC Labs program collection."""
@@ -0,0 +1 @@
1
+ """SJEC Labs program collection."""
@@ -0,0 +1 @@
1
+ """SJEC Labs program collection."""
@@ -0,0 +1 @@
1
+ """SJEC Labs program collection."""
@@ -0,0 +1 @@
1
+ """SJEC Labs program collection."""
@@ -0,0 +1,33 @@
1
+ # Original version from FAIML_simplified.ipynb
2
+ def chatbot():
3
+ responses = {
4
+ "hi": "Hi there! How are you today?",
5
+ "hello": "Hello! How can I assist you?",
6
+ "how are you?": "I'm just a bot, but I'm doing great! How about you?",
7
+ "what's your name?": "I am your friendly chatbot!",
8
+ "what can you do?": "I can have simple conversations with you. Ask me anything!",
9
+ "what is ai?": "AI stands for Artificial Intelligence, which is intelligence demonstrated by machines.",
10
+ "what is machine learning?": "Machine learning is a subset of AI that allows computers to learn from data.",
11
+ "what is deep learning?": "Deep learning uses neural networks to model complex patterns.",
12
+ "tell me a joke": "Why don't scientists trust atoms? Because they make up everything!",
13
+ "bye": "Goodbye! Have a nice day!"
14
+ }
15
+
16
+ print("Hello! I am a simple chatbot. How can I help you?")
17
+
18
+ # Infinite loop for conversation
19
+ while True:
20
+ user_input = input("You: ").lower()
21
+
22
+ if user_input in responses:
23
+ print(f"Bot: {responses[user_input]}")
24
+
25
+ if user_input == "bye":
26
+ break
27
+
28
+ else:
29
+ print("Bot: Sorry, I don't understand that. Can you try asking something else?")
30
+
31
+
32
+ # Run the chatbot
33
+ chatbot()
@@ -0,0 +1,39 @@
1
+ # Original version from FAIML_simplified.ipynb
2
+ from collections import deque
3
+
4
+ def water_jug(a, b, target):
5
+ q = deque([((0,0), [(0,0)])])
6
+ visited = {(0,0)}
7
+
8
+ while q:
9
+ (x,y), path = q.popleft()
10
+
11
+ if x == target or y == target:
12
+ return path
13
+
14
+ p = min(x, b-y)
15
+ r = min(y, a-x)
16
+
17
+ states = [(a,y), (x,b), (0,y), (x,0),
18
+ (x-p,y+p), (x+r,y-r)]
19
+
20
+ for s in states:
21
+ if s not in visited:
22
+ visited.add(s)
23
+ q.append((s, path+[s]))
24
+
25
+ return None
26
+
27
+
28
+ a = int(input("Enter jug 1 capacity: "))
29
+ b = int(input("Enter jug 2 capacity: "))
30
+ t = int(input("Enter target amount: "))
31
+
32
+ ans = water_jug(a, b, t)
33
+
34
+ if ans:
35
+ print("Solution steps:")
36
+ for s in ans:
37
+ print(s)
38
+ else:
39
+ print("No solution found")
@@ -0,0 +1,66 @@
1
+ # Original version from FAIML_simplified.ipynb
2
+ import heapq
3
+
4
+ def astar(grid, start, goal):
5
+ R, C = len(grid), len(grid[0])
6
+
7
+ h = lambda p: abs(p[0]-goal[0]) + abs(p[1]-goal[1])
8
+
9
+ q = [(h(start), 0, start)]
10
+ cost = {start: 0}
11
+ parent = {start: None}
12
+
13
+ while q:
14
+ f, g, cur = heapq.heappop(q)
15
+
16
+ if g != cost[cur]:
17
+ continue
18
+
19
+ if cur == goal:
20
+ path = []
21
+ while cur is not None:
22
+ path.append(cur)
23
+ cur = parent[cur]
24
+ return path[::-1]
25
+
26
+ for dx, dy in [(0,1), (0,-1), (1,0), (-1,0)]:
27
+ x, y = cur[0]+dx, cur[1]+dy
28
+ nxt = (x, y)
29
+
30
+ if 0 <= x < R and 0 <= y < C and grid[x][y] == 0:
31
+ new = g + 1
32
+
33
+ if nxt not in cost or new < cost[nxt]:
34
+ cost[nxt] = new
35
+ parent[nxt] = cur
36
+ heapq.heappush(q, (new+h(nxt), new, nxt))
37
+
38
+ return None
39
+
40
+
41
+ grid = [
42
+ [0,1,0,0,0],
43
+ [0,1,0,1,0],
44
+ [0,0,0,1,0],
45
+ [1,1,0,1,0],
46
+ [0,0,0,1,1]
47
+ ]
48
+
49
+ s = input("Enter source node: ").upper()
50
+ d = input("Enter destination node: ").upper()
51
+
52
+ nodes = {}
53
+
54
+ for i in range(len(grid) * len(grid[0])):
55
+ nodes[chr(65+i)] = (i//len(grid[0]), i%len(grid[0]))
56
+
57
+ if s in nodes and d in nodes:
58
+ path = astar(grid, nodes[s], nodes[d])
59
+
60
+ if path:
61
+ print("Path found:", " -> ".join(
62
+ chr(65+x*len(grid[0])+y) for x,y in path))
63
+ else:
64
+ print("No path found")
65
+ else:
66
+ print("Invalid nodes")
@@ -0,0 +1,34 @@
1
+ # Original version from FAIML_simplified.ipynb
2
+ def solve(n):
3
+ solutions = []
4
+
5
+ def safe(q, col):
6
+ row = len(q)
7
+ return all(col != c and abs(col-c) != row-r
8
+ for r, c in enumerate(q))
9
+
10
+ def backtrack(q):
11
+ if len(q) == n:
12
+ solutions.append(q[:])
13
+ return
14
+
15
+ for col in range(n):
16
+ if safe(q, col):
17
+ backtrack(q + [col])
18
+
19
+ backtrack([])
20
+ return solutions
21
+
22
+
23
+ n = int(input("Enter number of queens: "))
24
+ solutions = solve(n)
25
+
26
+ if solutions:
27
+ for i, sol in enumerate(solutions, 1):
28
+ print("\nSolution", i)
29
+
30
+ for col in sol:
31
+ print(" ".join("Q" if j == col else "."
32
+ for j in range(n)))
33
+ else:
34
+ print("No solution found")
@@ -0,0 +1 @@
1
+ """SJEC Labs program collection."""
@@ -0,0 +1,20 @@
1
+ # Program 1: Simple Chatbot
2
+ responses = {
3
+ "hi": "Hi there! How are you today?",
4
+ "hello": "Hello! How can I assist you?",
5
+ "how are you?": "I'm just a bot, but I'm doing great! How about you?",
6
+ "what's your name?": "I am your friendly chatbot!",
7
+ "what can you do?": "I can have simple conversations with you. Ask me anything!",
8
+ "what is ai?": "AI stands for Artificial Intelligence, which is intelligence demonstrated by machines.",
9
+ "what is machine learning?": "Machine learning is a subset of AI that allows computers to learn from data.",
10
+ "what is deep learning?": "Deep learning uses neural networks to model complex patterns.",
11
+ "tell me a joke": "Why don't scientists trust atoms? Because they make up everything!",
12
+ "bye": "Goodbye! Have a nice day!"
13
+ }
14
+
15
+ print("Hello! I am a simple chatbot. How can I help you?")
16
+ while True:
17
+ msg = input("You: ").lower()
18
+ print("Bot:", responses.get(msg, "Sorry, I don't understand that. Can you try asking something else?"))
19
+ if msg == "bye":
20
+ break
@@ -0,0 +1,32 @@
1
+ # Program 2: Water Jug Problem using BFS
2
+ from collections import deque
3
+
4
+ def water_jug(a, b, target):
5
+ q = deque([((0, 0), [(0, 0)])])
6
+ seen = {(0, 0)}
7
+
8
+ while q:
9
+ (x, y), path = q.popleft()
10
+ if x == target or y == target:
11
+ return path
12
+
13
+ p, r = min(x, b-y), min(y, a-x)
14
+ states = [(a,y), (x,b), (0,y), (x,0), (x-p,y+p), (x+r,y-r)]
15
+
16
+ for state in states:
17
+ if state not in seen:
18
+ seen.add(state)
19
+ q.append((state, path + [state]))
20
+ return None
21
+
22
+ a = int(input("Enter jug 1 capacity: "))
23
+ b = int(input("Enter jug 2 capacity: "))
24
+ t = int(input("Enter target amount: "))
25
+ ans = water_jug(a, b, t)
26
+
27
+ if ans:
28
+ print("Solution steps:")
29
+ for step in ans:
30
+ print(step)
31
+ else:
32
+ print("No solution found")
@@ -0,0 +1,44 @@
1
+ # Program 3: A* Search Algorithm
2
+ import heapq
3
+
4
+ def astar(grid, start, goal):
5
+ rows, cols = len(grid), len(grid[0])
6
+ h = lambda p: abs(p[0]-goal[0]) + abs(p[1]-goal[1])
7
+ q = [(h(start), 0, start)]
8
+ cost, parent = {start: 0}, {start: None}
9
+
10
+ while q:
11
+ f, g, cur = heapq.heappop(q)
12
+ if g != cost[cur]:
13
+ continue
14
+ if cur == goal:
15
+ path = []
16
+ while cur is not None:
17
+ path.append(cur)
18
+ cur = parent[cur]
19
+ return path[::-1]
20
+
21
+ for dx, dy in [(0,1), (0,-1), (1,0), (-1,0)]:
22
+ x, y = cur[0]+dx, cur[1]+dy
23
+ nxt = (x, y)
24
+ if 0 <= x < rows and 0 <= y < cols and grid[x][y] == 0:
25
+ new = g + 1
26
+ if nxt not in cost or new < cost[nxt]:
27
+ cost[nxt], parent[nxt] = new, cur
28
+ heapq.heappush(q, (new+h(nxt), new, nxt))
29
+ return None
30
+
31
+ grid = [[0,1,0,0,0], [0,1,0,1,0], [0,0,0,1,0],
32
+ [1,1,0,1,0], [0,0,0,1,1]]
33
+ nodes = {chr(65+i): (i//5, i%5) for i in range(25)}
34
+ s = input("Enter source node: ").upper()
35
+ d = input("Enter destination node: ").upper()
36
+
37
+ if s in nodes and d in nodes:
38
+ path = astar(grid, nodes[s], nodes[d])
39
+ if path:
40
+ print("Path found:", " -> ".join(chr(65+x*5+y) for x,y in path))
41
+ else:
42
+ print("No path found")
43
+ else:
44
+ print("Invalid nodes")
@@ -0,0 +1,30 @@
1
+ # Program 4: N-Queens using Backtracking
2
+
3
+ def solve(n):
4
+ solutions = []
5
+
6
+ def safe(q, col):
7
+ row = len(q)
8
+ return all(col != c and abs(col-c) != row-r for r, c in enumerate(q))
9
+
10
+ def backtrack(q):
11
+ if len(q) == n:
12
+ solutions.append(q)
13
+ return
14
+ for col in range(n):
15
+ if safe(q, col):
16
+ backtrack(q + [col])
17
+
18
+ backtrack([])
19
+ return solutions
20
+
21
+ n = int(input("Enter number of queens: "))
22
+ solutions = solve(n)
23
+
24
+ if solutions:
25
+ for i, sol in enumerate(solutions, 1):
26
+ print("\nSolution", i)
27
+ for col in sol:
28
+ print(" ".join("Q" if j == col else "." for j in range(n)))
29
+ else:
30
+ print("No solution found")
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: sjec-labs
3
+ Version: 0.1.0
4
+ Summary: Exam-friendly Python lab programs for SJEC students
5
+ Author: SJEC Labs contributors
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Provides-Extra: notebook
14
+ Requires-Dist: ipython>=8; extra == "notebook"
15
+ Dynamic: license-file
16
+
17
+ # sjec-labs
18
+
19
+ An expandable collection of exam-friendly Python lab programs for ML, CM and DV.
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ pip install sjec-labs
25
+ ```
26
+
27
+ For syntax-highlighted Jupyter output:
28
+
29
+ ```python
30
+ %pip install "sjec-labs[notebook]"
31
+ ```
32
+
33
+ ## Use in Jupyter or Python
34
+
35
+ ```python
36
+ from sjec_lab import LabAssistant
37
+
38
+ lab = LabAssistant()
39
+ lab.list_subjects()
40
+ lab.list_programs("ML")
41
+ lab.get_code("ML", 1) # print and return simplified code
42
+ lab.show_code("ML", 1) # formatted display in Jupyter
43
+ lab.get_code("ML", 1, version="original") # supplied original version
44
+ ```
45
+
46
+ Available initial programs:
47
+
48
+ 1. Simple Chatbot
49
+ 2. Water Jug Problem using BFS
50
+ 3. A* Search Algorithm
51
+ 4. N-Queens using Backtracking
52
+
53
+ CM and DV folders are reserved for future releases. The package will be expanded as more verified programs are added.
54
+
55
+ ## Notes
56
+
57
+ - `get_code()` returns the source as a string and prints it by default.
58
+ - Use `print_code=False` if you only want the returned string.
59
+ - The core package has no mandatory third-party dependencies.
60
+ - `show_code()` uses IPython when available.
@@ -0,0 +1,26 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/sjec_lab/__init__.py
5
+ src/sjec_lab/assistant.py
6
+ src/sjec_lab/core.py
7
+ src/sjec_lab/programs/__init__.py
8
+ src/sjec_lab/programs/cm/__init__.py
9
+ src/sjec_lab/programs/dv/__init__.py
10
+ src/sjec_lab/programs/ml/__init__.py
11
+ src/sjec_lab/programs/ml/original/__init__.py
12
+ src/sjec_lab/programs/ml/original/program1.py
13
+ src/sjec_lab/programs/ml/original/program2.py
14
+ src/sjec_lab/programs/ml/original/program3.py
15
+ src/sjec_lab/programs/ml/original/program4.py
16
+ src/sjec_lab/programs/ml/simple/__init__.py
17
+ src/sjec_lab/programs/ml/simple/program1.py
18
+ src/sjec_lab/programs/ml/simple/program2.py
19
+ src/sjec_lab/programs/ml/simple/program3.py
20
+ src/sjec_lab/programs/ml/simple/program4.py
21
+ src/sjec_labs.egg-info/PKG-INFO
22
+ src/sjec_labs.egg-info/SOURCES.txt
23
+ src/sjec_labs.egg-info/dependency_links.txt
24
+ src/sjec_labs.egg-info/requires.txt
25
+ src/sjec_labs.egg-info/top_level.txt
26
+ tests/test_core.py
@@ -0,0 +1,3 @@
1
+
2
+ [notebook]
3
+ ipython>=8
@@ -0,0 +1 @@
1
+ sjec_lab
@@ -0,0 +1,12 @@
1
+ from sjec_lab import get_code, list_programs, list_subjects
2
+
3
+ def test_subjects():
4
+ assert set(list_subjects()) == {"ML", "CM", "DV"}
5
+
6
+ def test_ml_programs():
7
+ assert len(list_programs("ML")) == 4
8
+ assert "def chatbot" not in get_code("ML", 1, print_code=False)
9
+ assert "while True" in get_code("ML", 1, print_code=False)
10
+
11
+ def test_original_available():
12
+ assert "def chatbot" in get_code("ML", 1, version="original", print_code=False)