Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions .github/workflows/datadog-synthetics.yml

This file was deleted.

27 changes: 9 additions & 18 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
types: [opened, synchronize, reopened]
push:
branches:
- main
- main

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand All @@ -21,33 +21,24 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'

- name: Cache Python dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-python-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-python-
python-version: '3.13.7'

- name: Install all dependencies and tools
run: |
python -m pip install --upgrade pip
pip install ruff bandit mypy pytest codespell
pip install ruff bandit mypy pytest codespell requests-mock colorama

- name: Run Codespell check
run: codespell --skip "*.json,*.txt,*.pdf" || true

- name: Run Bandit security scan
run: bandit -r . || true
run: bandit -r . --skip B101,B105 || true

- name: Run Pytest tests
run: pytest || true

- name: Run Ruff checks with ignored rules
run: |
ruff check . --ignore B904,B905,EM101,EXE001,G004,ISC001,PLC0415,PLC1901,PLW060,PLW1641,PLW2901,PT011,PT018,PT028,S101,S311,SIM905,SLF001,UP038
run: ruff check . --ignore B904,B905,EM101,EXE001,G004,ISC001,PLC0415,PLC1901,PLW060,PLW1641,PLW2901,PT011,PT018,PT028,S101,S311,SIM905,SLF001

- name: Run Mypy type checks
run: mypy . --ignore-missing-imports || true

- name: Run Pytest tests
run: pytest
run: mypy . --ignore-missing-imports || true
18 changes: 0 additions & 18 deletions .vscode/c_cpp_properties.json

This file was deleted.

24 changes: 0 additions & 24 deletions .vscode/launch.json

This file was deleted.

59 changes: 0 additions & 59 deletions .vscode/settings.json

This file was deleted.

Binary file removed 1 File handle/File handle binary/class.dat
Binary file not shown.
Binary file removed 1 File handle/File handle binary/studrec.dat
Binary file not shown.
94 changes: 52 additions & 42 deletions 8_puzzle.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
from queue import PriorityQueue
from typing import List, Tuple, Optional, Set


class PuzzleState:
def __init__(self, board, goal, moves=0, previous=None):
self.board = board
self.goal = goal
self.moves = moves
self.previous = previous

def __lt__(self, other):
"""Represents a state in 8-puzzle solving with A* algorithm."""

def __init__(
self,
board: List[List[int]],
goal: List[List[int]],
moves: int = 0,
previous: Optional["PuzzleState"] = None,
) -> None:
self.board = board # Current 3x3 board configuration
self.goal = goal # Target 3x3 configuration
self.moves = moves # Number of moves taken to reach here
self.previous = previous # Previous state in solution path

def __lt__(self, other: "PuzzleState") -> bool:
"""For PriorityQueue ordering: compare priorities."""
return self.priority() < other.priority()

def priority(self):
def priority(self) -> int:
"""A* priority: moves + Manhattan distance."""
return self.moves + self.manhattan()

def manhattan(self):
def manhattan(self) -> int:
"""Calculate Manhattan distance from current to goal state."""
distance = 0
for i in range(3):
for j in range(3):
Expand All @@ -23,68 +35,66 @@ def manhattan(self):
distance += abs(x - i) + abs(y - j)
return distance

def is_goal(self):
def is_goal(self) -> bool:
"""Check if current state matches goal."""
return self.board == self.goal

def neighbors(self):
def neighbors(self) -> List["PuzzleState"]:
"""Generate all valid neighboring states by moving empty tile (0)."""
neighbors = []
x, y = next((i, j) for i in range(3) for j in range(3) if self.board[i][j] == 0)
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

for dx, dy in directions:
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < 3 and 0 <= ny < 3:
new_board = [row[:] for row in self.board]
new_board[x][y], new_board[nx][ny] = new_board[nx][ny], new_board[x][y]
neighbors.append(
PuzzleState(new_board, self.goal, self.moves + 1, self)
)

return neighbors


def solve_puzzle(initial_board, goal_board):
initial_state = PuzzleState(initial_board, goal_board)
def solve_puzzle(
initial_board: List[List[int]], goal_board: List[List[int]]
) -> Optional[PuzzleState]:
"""
Solve 8-puzzle using A* algorithm.

>>> solve_puzzle([[1,2,3],[4,0,5],[7,8,6]], [[1,2,3],[4,5,6],[7,8,0]]) is not None
True
"""
initial = PuzzleState(initial_board, goal_board)
frontier = PriorityQueue()
frontier.put(initial_state)
explored = set()
frontier.put(initial)
explored: Set[Tuple[Tuple[int, ...], ...]] = set()

while not frontier.empty():
current_state = frontier.get()

if current_state.is_goal():
return current_state

explored.add(tuple(map(tuple, current_state.board)))

for neighbor in current_state.neighbors():
current = frontier.get()
if current.is_goal():
return current
explored.add(tuple(map(tuple, current.board)))
for neighbor in current.neighbors():
if tuple(map(tuple, neighbor.board)) not in explored:
frontier.put(neighbor)

return None


def print_solution(solution):
def print_solution(solution: Optional[PuzzleState]) -> None:
"""Print step-by-step solution from initial to goal state."""
if not solution:
print("No solution found.")
return
steps = []
while solution:
steps.append(solution.board)
solution = solution.previous
steps.reverse()

for step in steps:
for step in reversed(steps):
for row in step:
print(" ".join(map(str, row)))
print()


# Example usage
initial_board = [[1, 2, 3], [4, 0, 5], [7, 8, 6]]

goal_board = [[1, 2, 3], [4, 5, 6], [7, 8, 0]]
if __name__ == "__main__":
import doctest

solution = solve_puzzle(initial_board, goal_board)
if solution:
print("Solution found:")
print_solution(solution)
else:
print("No solution found.")
doctest.testmod(verbose=True)
Loading
Loading