Skip to content
Open
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
78 changes: 78 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# ruff.toml
target-version = "py311"
line-length = 100

# включить все основные правила
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"YTT", # flake8-2020
"S", # flake8-bandit
"A", # flake8-builtins
"COM", # flake8-commas
"C4", # flake8-comprehensions
"DTZ", # flake8-datetimez
"T10", # flake8-debugger
"EM", # flake8-errmsg
"EXE", # flake8-executable
"ISC", # flake8-implicit-str-concat
"ICN", # flake8-import-conventions
"G", # flake8-logging-format
"INP", # flake8-no-pep420
"PIE", # flake8-pie
"T20", # flake8-print
"PYI", # flake8-pyi
"PT", # flake8-pytest-style
"Q", # flake8-quotes
"RSE", # flake8-raise
"RET", # flake8-return
"SLF", # flake8-self
"SIM", # flake8-simplify
"TID", # flake8-tidy-imports
"TCH", # flake8-type-checking
"INT", # flake8-gettext
"ARG", # flake8-unused-arguments
"FBT", # flake8-boolean-trap
"B", # flake8-bugbear
"AIR", # flake8-airflow
"PERF", # flake8-perflint
]

# игнорировать правила
ignore = [
"E501", # line too long - handled by formatter
"S101", # assert used - ok in tests
"T201", # print found - sometimes needed
"COM812", # trailing comma missing - not always required
]

# настройки для конкретных файлов
[per-file-ignores]
"__init__.py" = ["F401"] # Unused imports allowed in __init__.py
"tests/**" = ["S101", "SLF001"] # Allow assert and self in tests
"**/migrations/**" = ["ALL"] # Ignore all in migrations

# настройки форматтера
[format]
indent-style = "space"
quote-style = "double"
skip-magic-trailing-comma = false
line-ending = "auto"

# настройки для конкретных правил
[flake8-quotes]
docstring-quotes = "double"
inline-quotes = "double"

[flake8-tidy-imports]
ban-relative-imports = "all"

[isort]
known-first-party = ["myapp"]
lines-after-imports = 2
combine-as-imports = true
split-on-trailing-comma = true
98 changes: 98 additions & 0 deletions src/hw_10_dfs/hw_10_dfs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
class Graph:

# МЕТОДЫ СОЗДАНИЯ ГРАФА

def __init__(self):
"""Инициализация неориентированного графа"""
self.connections_list = {}

def add_vertex(self, vertex):
"""Добавление вершины в граф"""
if vertex not in self.connections_list:
self.connections_list[vertex] = []

def add_edge(self, vertex1, vertex2):
"""Добавление ребра"""
# добавляем вершины, если их нет
self.add_vertex(vertex1)
self.add_vertex(vertex2)

# добавляем связи в обе стороны
if vertex2 not in self.connections_list[vertex1]:
self.connections_list[vertex1].append(vertex2)
if vertex1 not in self.connections_list[vertex2]:
self.connections_list[vertex2].append(vertex1)

# РЕАЛИЗАЦИЯ ПРОТОКОЛОВ ИНТЕРФЕЙСОВ

def __iter__(self):
"""Делает граф итерируемым"""
self._dfs_order = self.dfs()
self._index = 0
return self

def __next__(self):
"""Возвращает следующую вершину при итерации"""
if self._index < len(self._dfs_order):
vertex = self._dfs_order[self._index]
self._index += 1
return vertex
raise StopIteration

def __str__(self):
"""Строковое представление"""
result = []
for vertex, neighbors in self.connections_list.items():
result.append(f"{vertex}: {neighbors}")
return "\n".join(result)

def __contains__(self, vertex):
"""Проверка наличия вершины"""
return vertex in self.connections_list

# ДОПОЛНИТЕЛЬНЫЕ МЕТОДЫ ДЛЯ РАБОТЫ С ГРАФОМ

def get_vertices(self):
"""Возвращает список всех вершин"""
return list(self.connections_list.keys())

def get_edges(self):
"""Возвращает список всех рёбер"""
edges = set()
for vertex, neighbors in self.connections_list.items():
for neighbor in neighbors:
edge = tuple(sorted((vertex, neighbor)))
edges.add(edge)

return list(edges)

# ОСНОВНОЕ ЗАДАНИЕ

def dfs(self, start_vertex=None):
"""
Обход графа в глубину | Depth-first search | DFS

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ну такое постыдились бы оставлять, явно же LLM

"""
if not self.connections_list:
return []

# если none, берём 1-ую вершину из словаря
if start_vertex is None:
start_vertex = next(iter(self.connections_list))

# проверяем существование начальной вершины
if start_vertex not in self.connections_list:
raise ValueError(f"Вершина {start_vertex} не существует в графе")

visited = [] # посещённые вершины
stack = [start_vertex] # вершины, которые необходимо обработать

while stack:
vertex = stack.pop()
if vertex not in visited:
visited.append(vertex)
# добавляем в обратном порядке для сохранения естественного порядка
for neighbor in reversed(self.connections_list[vertex]):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем? Зачем эти лишние операции? И что такое естественный порядок?

if neighbor not in visited:
stack.append(neighbor)

return visited